diff options
Diffstat (limited to 'drivers/net/wireless/ath/ar9170')
-rw-r--r-- | drivers/net/wireless/ath/ar9170/Kconfig | 20 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/ar9170.h | 258 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/cmd.c | 127 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/cmd.h | 92 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/eeprom.h | 179 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/hw.h | 430 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/led.c | 181 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/mac.c | 519 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/main.c | 2190 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/phy.c | 1719 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 1008 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.h | 82 |
13 files changed, 0 insertions, 6808 deletions
diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig deleted file mode 100644 index 7b9672b0d090..000000000000 --- a/drivers/net/wireless/ath/ar9170/Kconfig +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | config AR9170_USB | ||
2 | tristate "Atheros AR9170 802.11n USB support (OBSOLETE)" | ||
3 | depends on USB && MAC80211 | ||
4 | select FW_LOADER | ||
5 | help | ||
6 | This driver is going to get replaced by carl9170. | ||
7 | |||
8 | This is a driver for the Atheros "otus" 802.11n USB devices. | ||
9 | |||
10 | These devices require additional firmware (2 files). | ||
11 | For now, these files can be downloaded from here: | ||
12 | |||
13 | http://wireless.kernel.org/en/users/Drivers/ar9170 | ||
14 | |||
15 | If you choose to build a module, it'll be called ar9170usb. | ||
16 | |||
17 | config AR9170_LEDS | ||
18 | bool | ||
19 | depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB) | ||
20 | default y | ||
diff --git a/drivers/net/wireless/ath/ar9170/Makefile b/drivers/net/wireless/ath/ar9170/Makefile deleted file mode 100644 index 8d91c7ee3215..000000000000 --- a/drivers/net/wireless/ath/ar9170/Makefile +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o | ||
2 | |||
3 | obj-$(CONFIG_AR9170_USB) += ar9170usb.o | ||
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h deleted file mode 100644 index 371e4ce49528..000000000000 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ /dev/null | |||
@@ -1,258 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * Driver specific definitions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | #ifndef __AR9170_H | ||
39 | #define __AR9170_H | ||
40 | |||
41 | #include <linux/completion.h> | ||
42 | #include <linux/spinlock.h> | ||
43 | #include <net/cfg80211.h> | ||
44 | #include <net/mac80211.h> | ||
45 | #ifdef CONFIG_AR9170_LEDS | ||
46 | #include <linux/leds.h> | ||
47 | #endif /* CONFIG_AR9170_LEDS */ | ||
48 | #include "eeprom.h" | ||
49 | #include "hw.h" | ||
50 | |||
51 | #include "../regd.h" | ||
52 | |||
53 | #define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) | ||
54 | |||
55 | enum ar9170_bw { | ||
56 | AR9170_BW_20, | ||
57 | AR9170_BW_40_BELOW, | ||
58 | AR9170_BW_40_ABOVE, | ||
59 | |||
60 | __AR9170_NUM_BW, | ||
61 | }; | ||
62 | |||
63 | static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type) | ||
64 | { | ||
65 | switch (type) { | ||
66 | case NL80211_CHAN_NO_HT: | ||
67 | case NL80211_CHAN_HT20: | ||
68 | return AR9170_BW_20; | ||
69 | case NL80211_CHAN_HT40MINUS: | ||
70 | return AR9170_BW_40_BELOW; | ||
71 | case NL80211_CHAN_HT40PLUS: | ||
72 | return AR9170_BW_40_ABOVE; | ||
73 | default: | ||
74 | BUG(); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | enum ar9170_rf_init_mode { | ||
79 | AR9170_RFI_NONE, | ||
80 | AR9170_RFI_WARM, | ||
81 | AR9170_RFI_COLD, | ||
82 | }; | ||
83 | |||
84 | #define AR9170_MAX_RX_BUFFER_SIZE 8192 | ||
85 | |||
86 | #ifdef CONFIG_AR9170_LEDS | ||
87 | struct ar9170; | ||
88 | |||
89 | struct ar9170_led { | ||
90 | struct ar9170 *ar; | ||
91 | struct led_classdev l; | ||
92 | char name[32]; | ||
93 | unsigned int toggled; | ||
94 | bool last_state; | ||
95 | bool registered; | ||
96 | }; | ||
97 | |||
98 | #endif /* CONFIG_AR9170_LEDS */ | ||
99 | |||
100 | enum ar9170_device_state { | ||
101 | AR9170_UNKNOWN_STATE, | ||
102 | AR9170_STOPPED, | ||
103 | AR9170_IDLE, | ||
104 | AR9170_STARTED, | ||
105 | }; | ||
106 | |||
107 | struct ar9170_rxstream_mpdu_merge { | ||
108 | struct ar9170_rx_head plcp; | ||
109 | bool has_plcp; | ||
110 | }; | ||
111 | |||
112 | struct ar9170_tx_queue_stats { | ||
113 | unsigned int len; | ||
114 | unsigned int limit; | ||
115 | unsigned int count; | ||
116 | }; | ||
117 | |||
118 | #define AR9170_QUEUE_TIMEOUT 64 | ||
119 | #define AR9170_TX_TIMEOUT 8 | ||
120 | #define AR9170_JANITOR_DELAY 128 | ||
121 | #define AR9170_TX_INVALID_RATE 0xffffffff | ||
122 | |||
123 | #define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH | ||
124 | #define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) | ||
125 | |||
126 | struct ar9170 { | ||
127 | struct ieee80211_hw *hw; | ||
128 | struct ath_common common; | ||
129 | struct mutex mutex; | ||
130 | enum ar9170_device_state state; | ||
131 | bool registered; | ||
132 | unsigned long bad_hw_nagger; | ||
133 | |||
134 | int (*open)(struct ar9170 *); | ||
135 | void (*stop)(struct ar9170 *); | ||
136 | int (*tx)(struct ar9170 *, struct sk_buff *); | ||
137 | int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 , | ||
138 | void *, u32 , void *); | ||
139 | void (*callback_cmd)(struct ar9170 *, u32 , void *); | ||
140 | int (*flush)(struct ar9170 *); | ||
141 | |||
142 | /* interface mode settings */ | ||
143 | struct ieee80211_vif *vif; | ||
144 | |||
145 | /* beaconing */ | ||
146 | struct sk_buff *beacon; | ||
147 | struct work_struct beacon_work; | ||
148 | bool enable_beacon; | ||
149 | |||
150 | /* cryptographic engine */ | ||
151 | u64 usedkeys; | ||
152 | bool rx_software_decryption; | ||
153 | bool disable_offload; | ||
154 | |||
155 | /* filter settings */ | ||
156 | u64 cur_mc_hash; | ||
157 | u32 cur_filter; | ||
158 | unsigned int filter_state; | ||
159 | bool sniffer_enabled; | ||
160 | |||
161 | /* PHY */ | ||
162 | struct ieee80211_channel *channel; | ||
163 | int noise[4]; | ||
164 | |||
165 | /* power calibration data */ | ||
166 | u8 power_5G_leg[4]; | ||
167 | u8 power_2G_cck[4]; | ||
168 | u8 power_2G_ofdm[4]; | ||
169 | u8 power_5G_ht20[8]; | ||
170 | u8 power_5G_ht40[8]; | ||
171 | u8 power_2G_ht20[8]; | ||
172 | u8 power_2G_ht40[8]; | ||
173 | |||
174 | u8 phy_heavy_clip; | ||
175 | |||
176 | #ifdef CONFIG_AR9170_LEDS | ||
177 | struct delayed_work led_work; | ||
178 | struct ar9170_led leds[AR9170_NUM_LEDS]; | ||
179 | #endif /* CONFIG_AR9170_LEDS */ | ||
180 | |||
181 | /* qos queue settings */ | ||
182 | spinlock_t tx_stats_lock; | ||
183 | struct ar9170_tx_queue_stats tx_stats[5]; | ||
184 | struct ieee80211_tx_queue_params edcf[5]; | ||
185 | |||
186 | spinlock_t cmdlock; | ||
187 | __le32 cmdbuf[PAYLOAD_MAX + 1]; | ||
188 | |||
189 | /* MAC statistics */ | ||
190 | struct ieee80211_low_level_stats stats; | ||
191 | |||
192 | /* EEPROM */ | ||
193 | struct ar9170_eeprom eeprom; | ||
194 | |||
195 | /* tx queues - as seen by hw - */ | ||
196 | struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; | ||
197 | struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; | ||
198 | struct delayed_work tx_janitor; | ||
199 | |||
200 | /* rxstream mpdu merge */ | ||
201 | struct ar9170_rxstream_mpdu_merge rx_mpdu; | ||
202 | struct sk_buff *rx_failover; | ||
203 | int rx_failover_missing; | ||
204 | |||
205 | /* (cached) HW A-MPDU settings */ | ||
206 | u8 global_ampdu_density; | ||
207 | u8 global_ampdu_factor; | ||
208 | }; | ||
209 | |||
210 | struct ar9170_tx_info { | ||
211 | unsigned long timeout; | ||
212 | }; | ||
213 | |||
214 | #define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) | ||
215 | #define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) | ||
216 | |||
217 | /* exported interface */ | ||
218 | void *ar9170_alloc(size_t priv_size); | ||
219 | int ar9170_register(struct ar9170 *ar, struct device *pdev); | ||
220 | void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb); | ||
221 | void ar9170_unregister(struct ar9170 *ar); | ||
222 | void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb); | ||
223 | void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); | ||
224 | int ar9170_nag_limiter(struct ar9170 *ar); | ||
225 | |||
226 | /* MAC */ | ||
227 | void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
228 | int ar9170_init_mac(struct ar9170 *ar); | ||
229 | int ar9170_set_qos(struct ar9170 *ar); | ||
230 | int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); | ||
231 | int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter); | ||
232 | int ar9170_set_operating_mode(struct ar9170 *ar); | ||
233 | int ar9170_set_beacon_timers(struct ar9170 *ar); | ||
234 | int ar9170_set_dyn_sifs_ack(struct ar9170 *ar); | ||
235 | int ar9170_set_slot_time(struct ar9170 *ar); | ||
236 | int ar9170_set_basic_rates(struct ar9170 *ar); | ||
237 | int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry); | ||
238 | int ar9170_update_beacon(struct ar9170 *ar); | ||
239 | void ar9170_new_beacon(struct work_struct *work); | ||
240 | int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, | ||
241 | u8 keyidx, u8 *keydata, int keylen); | ||
242 | int ar9170_disable_key(struct ar9170 *ar, u8 id); | ||
243 | |||
244 | /* LEDs */ | ||
245 | #ifdef CONFIG_AR9170_LEDS | ||
246 | int ar9170_register_leds(struct ar9170 *ar); | ||
247 | void ar9170_unregister_leds(struct ar9170 *ar); | ||
248 | #endif /* CONFIG_AR9170_LEDS */ | ||
249 | int ar9170_init_leds(struct ar9170 *ar); | ||
250 | int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state); | ||
251 | |||
252 | /* PHY / RF */ | ||
253 | int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band); | ||
254 | int ar9170_init_rf(struct ar9170 *ar); | ||
255 | int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | ||
256 | enum ar9170_rf_init_mode rfi, enum ar9170_bw bw); | ||
257 | |||
258 | #endif /* __AR9170_H */ | ||
diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c deleted file mode 100644 index 6452c5055a63..000000000000 --- a/drivers/net/wireless/ath/ar9170/cmd.c +++ /dev/null | |||
@@ -1,127 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * Basic HW register/memory/command access functions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include "ar9170.h" | ||
40 | #include "cmd.h" | ||
41 | |||
42 | int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) | ||
43 | { | ||
44 | int err; | ||
45 | |||
46 | if (unlikely(!IS_ACCEPTING_CMD(ar))) | ||
47 | return 0; | ||
48 | |||
49 | err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL); | ||
50 | if (err) | ||
51 | wiphy_debug(ar->hw->wiphy, "writing memory failed\n"); | ||
52 | return err; | ||
53 | } | ||
54 | |||
55 | int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) | ||
56 | { | ||
57 | const __le32 buf[2] = { | ||
58 | cpu_to_le32(reg), | ||
59 | cpu_to_le32(val), | ||
60 | }; | ||
61 | int err; | ||
62 | |||
63 | if (unlikely(!IS_ACCEPTING_CMD(ar))) | ||
64 | return 0; | ||
65 | |||
66 | err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf), | ||
67 | (u8 *) buf, 0, NULL); | ||
68 | if (err) | ||
69 | wiphy_debug(ar->hw->wiphy, "writing reg %#x (val %#x) failed\n", | ||
70 | reg, val); | ||
71 | return err; | ||
72 | } | ||
73 | |||
74 | int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out) | ||
75 | { | ||
76 | int i, err; | ||
77 | __le32 *offs, *res; | ||
78 | |||
79 | if (unlikely(!IS_ACCEPTING_CMD(ar))) | ||
80 | return 0; | ||
81 | |||
82 | /* abuse "out" for the register offsets, must be same length */ | ||
83 | offs = (__le32 *)out; | ||
84 | for (i = 0; i < nregs; i++) | ||
85 | offs[i] = cpu_to_le32(regs[i]); | ||
86 | |||
87 | /* also use the same buffer for the input */ | ||
88 | res = (__le32 *)out; | ||
89 | |||
90 | err = ar->exec_cmd(ar, AR9170_CMD_RREG, | ||
91 | 4 * nregs, (u8 *)offs, | ||
92 | 4 * nregs, (u8 *)res); | ||
93 | if (err) | ||
94 | return err; | ||
95 | |||
96 | /* convert result to cpu endian */ | ||
97 | for (i = 0; i < nregs; i++) | ||
98 | out[i] = le32_to_cpu(res[i]); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) | ||
104 | { | ||
105 | return ar9170_read_mreg(ar, 1, ®, val); | ||
106 | } | ||
107 | |||
108 | int ar9170_echo_test(struct ar9170 *ar, u32 v) | ||
109 | { | ||
110 | __le32 echobuf = cpu_to_le32(v); | ||
111 | __le32 echores; | ||
112 | int err; | ||
113 | |||
114 | if (unlikely(!IS_ACCEPTING_CMD(ar))) | ||
115 | return -ENODEV; | ||
116 | |||
117 | err = ar->exec_cmd(ar, AR9170_CMD_ECHO, | ||
118 | 4, (u8 *)&echobuf, | ||
119 | 4, (u8 *)&echores); | ||
120 | if (err) | ||
121 | return err; | ||
122 | |||
123 | if (echobuf != echores) | ||
124 | return -EINVAL; | ||
125 | |||
126 | return 0; | ||
127 | } | ||
diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h deleted file mode 100644 index ec8134b4b949..000000000000 --- a/drivers/net/wireless/ath/ar9170/cmd.h +++ /dev/null | |||
@@ -1,92 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * Basic HW register/memory/command access functions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | #ifndef __CMD_H | ||
39 | #define __CMD_H | ||
40 | |||
41 | #include "ar9170.h" | ||
42 | |||
43 | /* basic HW access */ | ||
44 | int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); | ||
45 | int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); | ||
46 | int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); | ||
47 | int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out); | ||
48 | int ar9170_echo_test(struct ar9170 *ar, u32 v); | ||
49 | |||
50 | /* | ||
51 | * Macros to facilitate writing multiple registers in a single | ||
52 | * write-combining USB command. Note that when the first group | ||
53 | * fails the whole thing will fail without any others attempted, | ||
54 | * but you won't know which write in the group failed. | ||
55 | */ | ||
56 | #define ar9170_regwrite_begin(ar) \ | ||
57 | do { \ | ||
58 | int __nreg = 0, __err = 0; \ | ||
59 | struct ar9170 *__ar = ar; | ||
60 | |||
61 | #define ar9170_regwrite(r, v) do { \ | ||
62 | __ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r); \ | ||
63 | __ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v); \ | ||
64 | __nreg++; \ | ||
65 | if ((__nreg >= PAYLOAD_MAX/2)) { \ | ||
66 | if (IS_ACCEPTING_CMD(__ar)) \ | ||
67 | __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ | ||
68 | 8 * __nreg, \ | ||
69 | (u8 *) &__ar->cmdbuf[1], \ | ||
70 | 0, NULL); \ | ||
71 | __nreg = 0; \ | ||
72 | if (__err) \ | ||
73 | goto __regwrite_out; \ | ||
74 | } \ | ||
75 | } while (0) | ||
76 | |||
77 | #define ar9170_regwrite_finish() \ | ||
78 | __regwrite_out : \ | ||
79 | if (__nreg) { \ | ||
80 | if (IS_ACCEPTING_CMD(__ar)) \ | ||
81 | __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ | ||
82 | 8 * __nreg, \ | ||
83 | (u8 *) &__ar->cmdbuf[1], \ | ||
84 | 0, NULL); \ | ||
85 | __nreg = 0; \ | ||
86 | } | ||
87 | |||
88 | #define ar9170_regwrite_result() \ | ||
89 | __err; \ | ||
90 | } while (0); | ||
91 | |||
92 | #endif /* __CMD_H */ | ||
diff --git a/drivers/net/wireless/ath/ar9170/eeprom.h b/drivers/net/wireless/ath/ar9170/eeprom.h deleted file mode 100644 index 6c4663883423..000000000000 --- a/drivers/net/wireless/ath/ar9170/eeprom.h +++ /dev/null | |||
@@ -1,179 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * EEPROM layout | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | #ifndef __AR9170_EEPROM_H | ||
39 | #define __AR9170_EEPROM_H | ||
40 | |||
41 | #define AR5416_MAX_CHAINS 2 | ||
42 | #define AR5416_MODAL_SPURS 5 | ||
43 | |||
44 | struct ar9170_eeprom_modal { | ||
45 | __le32 antCtrlChain[AR5416_MAX_CHAINS]; | ||
46 | __le32 antCtrlCommon; | ||
47 | s8 antennaGainCh[AR5416_MAX_CHAINS]; | ||
48 | u8 switchSettling; | ||
49 | u8 txRxAttenCh[AR5416_MAX_CHAINS]; | ||
50 | u8 rxTxMarginCh[AR5416_MAX_CHAINS]; | ||
51 | s8 adcDesiredSize; | ||
52 | s8 pgaDesiredSize; | ||
53 | u8 xlnaGainCh[AR5416_MAX_CHAINS]; | ||
54 | u8 txEndToXpaOff; | ||
55 | u8 txEndToRxOn; | ||
56 | u8 txFrameToXpaOn; | ||
57 | u8 thresh62; | ||
58 | s8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; | ||
59 | u8 xpdGain; | ||
60 | u8 xpd; | ||
61 | s8 iqCalICh[AR5416_MAX_CHAINS]; | ||
62 | s8 iqCalQCh[AR5416_MAX_CHAINS]; | ||
63 | u8 pdGainOverlap; | ||
64 | u8 ob; | ||
65 | u8 db; | ||
66 | u8 xpaBiasLvl; | ||
67 | u8 pwrDecreaseFor2Chain; | ||
68 | u8 pwrDecreaseFor3Chain; | ||
69 | u8 txFrameToDataStart; | ||
70 | u8 txFrameToPaOn; | ||
71 | u8 ht40PowerIncForPdadc; | ||
72 | u8 bswAtten[AR5416_MAX_CHAINS]; | ||
73 | u8 bswMargin[AR5416_MAX_CHAINS]; | ||
74 | u8 swSettleHt40; | ||
75 | u8 reserved[22]; | ||
76 | struct spur_channel { | ||
77 | __le16 spurChan; | ||
78 | u8 spurRangeLow; | ||
79 | u8 spurRangeHigh; | ||
80 | } __packed spur_channels[AR5416_MODAL_SPURS]; | ||
81 | } __packed; | ||
82 | |||
83 | #define AR5416_NUM_PD_GAINS 4 | ||
84 | #define AR5416_PD_GAIN_ICEPTS 5 | ||
85 | |||
86 | struct ar9170_calibration_data_per_freq { | ||
87 | u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | ||
88 | u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | ||
89 | } __packed; | ||
90 | |||
91 | #define AR5416_NUM_5G_CAL_PIERS 8 | ||
92 | #define AR5416_NUM_2G_CAL_PIERS 4 | ||
93 | |||
94 | #define AR5416_NUM_5G_TARGET_PWRS 8 | ||
95 | #define AR5416_NUM_2G_CCK_TARGET_PWRS 3 | ||
96 | #define AR5416_NUM_2G_OFDM_TARGET_PWRS 4 | ||
97 | #define AR5416_MAX_NUM_TGT_PWRS 8 | ||
98 | |||
99 | struct ar9170_calibration_target_power_legacy { | ||
100 | u8 freq; | ||
101 | u8 power[4]; | ||
102 | } __packed; | ||
103 | |||
104 | struct ar9170_calibration_target_power_ht { | ||
105 | u8 freq; | ||
106 | u8 power[8]; | ||
107 | } __packed; | ||
108 | |||
109 | #define AR5416_NUM_CTLS 24 | ||
110 | |||
111 | struct ar9170_calctl_edges { | ||
112 | u8 channel; | ||
113 | #define AR9170_CALCTL_EDGE_FLAGS 0xC0 | ||
114 | u8 power_flags; | ||
115 | } __packed; | ||
116 | |||
117 | #define AR5416_NUM_BAND_EDGES 8 | ||
118 | |||
119 | struct ar9170_calctl_data { | ||
120 | struct ar9170_calctl_edges | ||
121 | control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; | ||
122 | } __packed; | ||
123 | |||
124 | |||
125 | struct ar9170_eeprom { | ||
126 | __le16 length; | ||
127 | __le16 checksum; | ||
128 | __le16 version; | ||
129 | u8 operating_flags; | ||
130 | #define AR9170_OPFLAG_5GHZ 1 | ||
131 | #define AR9170_OPFLAG_2GHZ 2 | ||
132 | u8 misc; | ||
133 | __le16 reg_domain[2]; | ||
134 | u8 mac_address[6]; | ||
135 | u8 rx_mask; | ||
136 | u8 tx_mask; | ||
137 | __le16 rf_silent; | ||
138 | __le16 bluetooth_options; | ||
139 | __le16 device_capabilities; | ||
140 | __le32 build_number; | ||
141 | u8 deviceType; | ||
142 | u8 reserved[33]; | ||
143 | |||
144 | u8 customer_data[64]; | ||
145 | |||
146 | struct ar9170_eeprom_modal | ||
147 | modal_header[2]; | ||
148 | |||
149 | u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS]; | ||
150 | u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS]; | ||
151 | |||
152 | struct ar9170_calibration_data_per_freq | ||
153 | cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS], | ||
154 | cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; | ||
155 | |||
156 | /* power calibration data */ | ||
157 | struct ar9170_calibration_target_power_legacy | ||
158 | cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS]; | ||
159 | struct ar9170_calibration_target_power_ht | ||
160 | cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS], | ||
161 | cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS]; | ||
162 | |||
163 | struct ar9170_calibration_target_power_legacy | ||
164 | cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS], | ||
165 | cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS]; | ||
166 | struct ar9170_calibration_target_power_ht | ||
167 | cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS], | ||
168 | cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS]; | ||
169 | |||
170 | /* conformance testing limits */ | ||
171 | u8 ctl_index[AR5416_NUM_CTLS]; | ||
172 | struct ar9170_calctl_data | ||
173 | ctl_data[AR5416_NUM_CTLS]; | ||
174 | |||
175 | u8 pad; | ||
176 | __le16 subsystem_id; | ||
177 | } __packed; | ||
178 | |||
179 | #endif /* __AR9170_EEPROM_H */ | ||
diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h deleted file mode 100644 index 06f1f3c951a4..000000000000 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ /dev/null | |||
@@ -1,430 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * Hardware-specific definitions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | #ifndef __AR9170_HW_H | ||
39 | #define __AR9170_HW_H | ||
40 | |||
41 | #define AR9170_MAX_CMD_LEN 64 | ||
42 | |||
43 | enum ar9170_cmd { | ||
44 | AR9170_CMD_RREG = 0x00, | ||
45 | AR9170_CMD_WREG = 0x01, | ||
46 | AR9170_CMD_RMEM = 0x02, | ||
47 | AR9170_CMD_WMEM = 0x03, | ||
48 | AR9170_CMD_BITAND = 0x04, | ||
49 | AR9170_CMD_BITOR = 0x05, | ||
50 | AR9170_CMD_EKEY = 0x28, | ||
51 | AR9170_CMD_DKEY = 0x29, | ||
52 | AR9170_CMD_FREQUENCY = 0x30, | ||
53 | AR9170_CMD_RF_INIT = 0x31, | ||
54 | AR9170_CMD_SYNTH = 0x32, | ||
55 | AR9170_CMD_FREQ_START = 0x33, | ||
56 | AR9170_CMD_ECHO = 0x80, | ||
57 | AR9170_CMD_TALLY = 0x81, | ||
58 | AR9170_CMD_TALLY_APD = 0x82, | ||
59 | AR9170_CMD_CONFIG = 0x83, | ||
60 | AR9170_CMD_RESET = 0x90, | ||
61 | AR9170_CMD_DKRESET = 0x91, | ||
62 | AR9170_CMD_DKTX_STATUS = 0x92, | ||
63 | AR9170_CMD_FDC = 0xA0, | ||
64 | AR9170_CMD_WREEPROM = 0xB0, | ||
65 | AR9170_CMD_WFLASH = 0xB0, | ||
66 | AR9170_CMD_FLASH_ERASE = 0xB1, | ||
67 | AR9170_CMD_FLASH_PROG = 0xB2, | ||
68 | AR9170_CMD_FLASH_CHKSUM = 0xB3, | ||
69 | AR9170_CMD_FLASH_READ = 0xB4, | ||
70 | AR9170_CMD_FW_DL_INIT = 0xB5, | ||
71 | AR9170_CMD_MEM_WREEPROM = 0xBB, | ||
72 | }; | ||
73 | |||
74 | /* endpoints */ | ||
75 | #define AR9170_EP_TX 1 | ||
76 | #define AR9170_EP_RX 2 | ||
77 | #define AR9170_EP_IRQ 3 | ||
78 | #define AR9170_EP_CMD 4 | ||
79 | |||
80 | #define AR9170_EEPROM_START 0x1600 | ||
81 | |||
82 | #define AR9170_GPIO_REG_BASE 0x1d0100 | ||
83 | #define AR9170_GPIO_REG_PORT_TYPE AR9170_GPIO_REG_BASE | ||
84 | #define AR9170_GPIO_REG_DATA (AR9170_GPIO_REG_BASE + 4) | ||
85 | #define AR9170_NUM_LEDS 2 | ||
86 | |||
87 | |||
88 | #define AR9170_USB_REG_BASE 0x1e1000 | ||
89 | #define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) | ||
90 | #define AR9170_DMA_CTL_ENABLE_TO_DEVICE 0x1 | ||
91 | #define AR9170_DMA_CTL_ENABLE_FROM_DEVICE 0x2 | ||
92 | #define AR9170_DMA_CTL_HIGH_SPEED 0x4 | ||
93 | #define AR9170_DMA_CTL_PACKET_MODE 0x8 | ||
94 | |||
95 | #define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) | ||
96 | #define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) | ||
97 | |||
98 | |||
99 | |||
100 | #define AR9170_MAC_REG_BASE 0x1c3000 | ||
101 | |||
102 | #define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514) | ||
103 | #define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518) | ||
104 | |||
105 | #define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51C) | ||
106 | #define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) | ||
107 | #define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) | ||
108 | |||
109 | #define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610) | ||
110 | #define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614) | ||
111 | #define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618) | ||
112 | #define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c) | ||
113 | |||
114 | #define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624) | ||
115 | #define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628) | ||
116 | |||
117 | #define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62C) | ||
118 | |||
119 | #define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630) | ||
120 | #define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634) | ||
121 | #define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638) | ||
122 | #define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c) | ||
123 | #define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640) | ||
124 | #define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64C) | ||
125 | |||
126 | #define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658) | ||
127 | #define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674) | ||
128 | #define AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC BIT(0) | ||
129 | #define AR9170_MAC_REG_SNIFFER_DEFAULTS 0x02000000 | ||
130 | #define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) | ||
131 | #define AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE BIT(3) | ||
132 | #define AR9170_MAC_REG_ENCRYPTION_DEFAULTS 0x70 | ||
133 | |||
134 | #define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) | ||
135 | #define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688) | ||
136 | |||
137 | #define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c) | ||
138 | #define AR9170_MAC_REG_FTF_ASSOC_REQ BIT(0) | ||
139 | #define AR9170_MAC_REG_FTF_ASSOC_RESP BIT(1) | ||
140 | #define AR9170_MAC_REG_FTF_REASSOC_REQ BIT(2) | ||
141 | #define AR9170_MAC_REG_FTF_REASSOC_RESP BIT(3) | ||
142 | #define AR9170_MAC_REG_FTF_PRB_REQ BIT(4) | ||
143 | #define AR9170_MAC_REG_FTF_PRB_RESP BIT(5) | ||
144 | #define AR9170_MAC_REG_FTF_BIT6 BIT(6) | ||
145 | #define AR9170_MAC_REG_FTF_BIT7 BIT(7) | ||
146 | #define AR9170_MAC_REG_FTF_BEACON BIT(8) | ||
147 | #define AR9170_MAC_REG_FTF_ATIM BIT(9) | ||
148 | #define AR9170_MAC_REG_FTF_DEASSOC BIT(10) | ||
149 | #define AR9170_MAC_REG_FTF_AUTH BIT(11) | ||
150 | #define AR9170_MAC_REG_FTF_DEAUTH BIT(12) | ||
151 | #define AR9170_MAC_REG_FTF_BIT13 BIT(13) | ||
152 | #define AR9170_MAC_REG_FTF_BIT14 BIT(14) | ||
153 | #define AR9170_MAC_REG_FTF_BIT15 BIT(15) | ||
154 | #define AR9170_MAC_REG_FTF_BAR BIT(24) | ||
155 | #define AR9170_MAC_REG_FTF_BA BIT(25) | ||
156 | #define AR9170_MAC_REG_FTF_PSPOLL BIT(26) | ||
157 | #define AR9170_MAC_REG_FTF_RTS BIT(27) | ||
158 | #define AR9170_MAC_REG_FTF_CTS BIT(28) | ||
159 | #define AR9170_MAC_REG_FTF_ACK BIT(29) | ||
160 | #define AR9170_MAC_REG_FTF_CFE BIT(30) | ||
161 | #define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) | ||
162 | #define AR9170_MAC_REG_FTF_DEFAULTS 0x0700ffff | ||
163 | #define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff | ||
164 | |||
165 | #define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) | ||
166 | #define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6A4) | ||
167 | #define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6A8) | ||
168 | #define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6AC) | ||
169 | #define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6B0) | ||
170 | #define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6BC) | ||
171 | #define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6CC) | ||
172 | #define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6F4) | ||
173 | |||
174 | |||
175 | #define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) | ||
176 | #define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) | ||
177 | |||
178 | #define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6F0) | ||
179 | |||
180 | #define AR9170_MAC_REG_POWERMANAGEMENT (AR9170_MAC_REG_BASE + 0x700) | ||
181 | #define AR9170_MAC_REG_POWERMGT_IBSS 0xe0 | ||
182 | #define AR9170_MAC_REG_POWERMGT_AP 0xa1 | ||
183 | #define AR9170_MAC_REG_POWERMGT_STA 0x2 | ||
184 | #define AR9170_MAC_REG_POWERMGT_AP_WDS 0x3 | ||
185 | #define AR9170_MAC_REG_POWERMGT_DEFAULTS (0xf << 24) | ||
186 | |||
187 | #define AR9170_MAC_REG_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) | ||
188 | #define AR9170_MAC_REG_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) | ||
189 | |||
190 | #define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xB00) | ||
191 | #define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xB04) | ||
192 | #define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xB08) | ||
193 | #define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xB0C) | ||
194 | #define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xB10) | ||
195 | #define AR9170_MAC_REG_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xB14) | ||
196 | #define AR9170_MAC_REG_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xB18) | ||
197 | |||
198 | #define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xB28) | ||
199 | |||
200 | #define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xBB0) | ||
201 | #define AR9170_MAC_FCS_SWFCS 0x1 | ||
202 | #define AR9170_MAC_FCS_FIFO_PROT 0x4 | ||
203 | |||
204 | |||
205 | #define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xB30) | ||
206 | |||
207 | #define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xB44) | ||
208 | #define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xB48) | ||
209 | |||
210 | #define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xB9C) | ||
211 | #define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xBA0) | ||
212 | |||
213 | #define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) | ||
214 | #define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) | ||
215 | |||
216 | #define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xD7C) | ||
217 | #define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f | ||
218 | #define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0 | ||
219 | #define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000 | ||
220 | #define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000 | ||
221 | |||
222 | #define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xD84) | ||
223 | #define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xD88) | ||
224 | #define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xD90) | ||
225 | #define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xD94) | ||
226 | #define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xDA0) | ||
227 | #define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xDA4) | ||
228 | |||
229 | |||
230 | #define AR9170_PWR_REG_BASE 0x1D4000 | ||
231 | |||
232 | #define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008) | ||
233 | #define AR9170_PWR_CLK_AHB_40MHZ 0 | ||
234 | #define AR9170_PWR_CLK_AHB_20_22MHZ 1 | ||
235 | #define AR9170_PWR_CLK_AHB_40_44MHZ 2 | ||
236 | #define AR9170_PWR_CLK_AHB_80_88MHZ 3 | ||
237 | #define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70 | ||
238 | |||
239 | |||
240 | /* put beacon here in memory */ | ||
241 | #define AR9170_BEACON_BUFFER_ADDRESS 0x117900 | ||
242 | |||
243 | |||
244 | struct ar9170_tx_control { | ||
245 | __le16 length; | ||
246 | __le16 mac_control; | ||
247 | __le32 phy_control; | ||
248 | u8 frame_data[0]; | ||
249 | } __packed; | ||
250 | |||
251 | /* these are either-or */ | ||
252 | #define AR9170_TX_MAC_PROT_RTS 0x0001 | ||
253 | #define AR9170_TX_MAC_PROT_CTS 0x0002 | ||
254 | |||
255 | #define AR9170_TX_MAC_NO_ACK 0x0004 | ||
256 | /* if unset, MAC will only do SIFS space before frame */ | ||
257 | #define AR9170_TX_MAC_BACKOFF 0x0008 | ||
258 | #define AR9170_TX_MAC_BURST 0x0010 | ||
259 | #define AR9170_TX_MAC_AGGR 0x0020 | ||
260 | |||
261 | /* encryption is a two-bit field */ | ||
262 | #define AR9170_TX_MAC_ENCR_NONE 0x0000 | ||
263 | #define AR9170_TX_MAC_ENCR_RC4 0x0040 | ||
264 | #define AR9170_TX_MAC_ENCR_CENC 0x0080 | ||
265 | #define AR9170_TX_MAC_ENCR_AES 0x00c0 | ||
266 | |||
267 | #define AR9170_TX_MAC_MMIC 0x0100 | ||
268 | #define AR9170_TX_MAC_HW_DURATION 0x0200 | ||
269 | #define AR9170_TX_MAC_QOS_SHIFT 10 | ||
270 | #define AR9170_TX_MAC_QOS_MASK (3 << AR9170_TX_MAC_QOS_SHIFT) | ||
271 | #define AR9170_TX_MAC_AGGR_QOS_BIT1 0x0400 | ||
272 | #define AR9170_TX_MAC_AGGR_QOS_BIT2 0x0800 | ||
273 | #define AR9170_TX_MAC_DISABLE_TXOP 0x1000 | ||
274 | #define AR9170_TX_MAC_TXOP_RIFS 0x2000 | ||
275 | #define AR9170_TX_MAC_IMM_AMPDU 0x4000 | ||
276 | #define AR9170_TX_MAC_RATE_PROBE 0x8000 | ||
277 | |||
278 | /* either-or */ | ||
279 | #define AR9170_TX_PHY_MOD_MASK 0x00000003 | ||
280 | #define AR9170_TX_PHY_MOD_CCK 0x00000000 | ||
281 | #define AR9170_TX_PHY_MOD_OFDM 0x00000001 | ||
282 | #define AR9170_TX_PHY_MOD_HT 0x00000002 | ||
283 | |||
284 | /* depends on modulation */ | ||
285 | #define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004 | ||
286 | #define AR9170_TX_PHY_GREENFIELD 0x00000004 | ||
287 | |||
288 | #define AR9170_TX_PHY_BW_SHIFT 3 | ||
289 | #define AR9170_TX_PHY_BW_MASK (3 << AR9170_TX_PHY_BW_SHIFT) | ||
290 | #define AR9170_TX_PHY_BW_20MHZ 0 | ||
291 | #define AR9170_TX_PHY_BW_40MHZ 2 | ||
292 | #define AR9170_TX_PHY_BW_40MHZ_DUP 3 | ||
293 | |||
294 | #define AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT 6 | ||
295 | #define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK (7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT) | ||
296 | |||
297 | #define AR9170_TX_PHY_TX_PWR_SHIFT 9 | ||
298 | #define AR9170_TX_PHY_TX_PWR_MASK (0x3f << AR9170_TX_PHY_TX_PWR_SHIFT) | ||
299 | |||
300 | /* not part of the hw-spec */ | ||
301 | #define AR9170_TX_PHY_QOS_SHIFT 25 | ||
302 | #define AR9170_TX_PHY_QOS_MASK (3 << AR9170_TX_PHY_QOS_SHIFT) | ||
303 | |||
304 | #define AR9170_TX_PHY_TXCHAIN_SHIFT 15 | ||
305 | #define AR9170_TX_PHY_TXCHAIN_MASK (7 << AR9170_TX_PHY_TXCHAIN_SHIFT) | ||
306 | #define AR9170_TX_PHY_TXCHAIN_1 1 | ||
307 | /* use for cck, ofdm 6/9/12/18/24 and HT if capable */ | ||
308 | #define AR9170_TX_PHY_TXCHAIN_2 5 | ||
309 | |||
310 | #define AR9170_TX_PHY_MCS_SHIFT 18 | ||
311 | #define AR9170_TX_PHY_MCS_MASK (0x7f << AR9170_TX_PHY_MCS_SHIFT) | ||
312 | |||
313 | #define AR9170_TX_PHY_SHORT_GI 0x80000000 | ||
314 | |||
315 | #define AR5416_MAX_RATE_POWER 63 | ||
316 | |||
317 | struct ar9170_rx_head { | ||
318 | u8 plcp[12]; | ||
319 | } __packed; | ||
320 | |||
321 | struct ar9170_rx_phystatus { | ||
322 | union { | ||
323 | struct { | ||
324 | u8 rssi_ant0, rssi_ant1, rssi_ant2, | ||
325 | rssi_ant0x, rssi_ant1x, rssi_ant2x, | ||
326 | rssi_combined; | ||
327 | } __packed; | ||
328 | u8 rssi[7]; | ||
329 | } __packed; | ||
330 | |||
331 | u8 evm_stream0[6], evm_stream1[6]; | ||
332 | u8 phy_err; | ||
333 | } __packed; | ||
334 | |||
335 | struct ar9170_rx_macstatus { | ||
336 | u8 SAidx, DAidx; | ||
337 | u8 error; | ||
338 | u8 status; | ||
339 | } __packed; | ||
340 | |||
341 | #define AR9170_ENC_ALG_NONE 0x0 | ||
342 | #define AR9170_ENC_ALG_WEP64 0x1 | ||
343 | #define AR9170_ENC_ALG_TKIP 0x2 | ||
344 | #define AR9170_ENC_ALG_AESCCMP 0x4 | ||
345 | #define AR9170_ENC_ALG_WEP128 0x5 | ||
346 | #define AR9170_ENC_ALG_WEP256 0x6 | ||
347 | #define AR9170_ENC_ALG_CENC 0x7 | ||
348 | |||
349 | #define AR9170_RX_ENC_SOFTWARE 0x8 | ||
350 | |||
351 | static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) | ||
352 | { | ||
353 | return (t->SAidx & 0xc0) >> 4 | | ||
354 | (t->DAidx & 0xc0) >> 6; | ||
355 | } | ||
356 | |||
357 | #define AR9170_RX_STATUS_MODULATION_MASK 0x03 | ||
358 | #define AR9170_RX_STATUS_MODULATION_CCK 0x00 | ||
359 | #define AR9170_RX_STATUS_MODULATION_OFDM 0x01 | ||
360 | #define AR9170_RX_STATUS_MODULATION_HT 0x02 | ||
361 | #define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03 | ||
362 | |||
363 | /* depends on modulation */ | ||
364 | #define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08 | ||
365 | #define AR9170_RX_STATUS_GREENFIELD 0x08 | ||
366 | |||
367 | #define AR9170_RX_STATUS_MPDU_MASK 0x30 | ||
368 | #define AR9170_RX_STATUS_MPDU_SINGLE 0x00 | ||
369 | #define AR9170_RX_STATUS_MPDU_FIRST 0x20 | ||
370 | #define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 | ||
371 | #define AR9170_RX_STATUS_MPDU_LAST 0x10 | ||
372 | |||
373 | #define AR9170_RX_ERROR_RXTO 0x01 | ||
374 | #define AR9170_RX_ERROR_OVERRUN 0x02 | ||
375 | #define AR9170_RX_ERROR_DECRYPT 0x04 | ||
376 | #define AR9170_RX_ERROR_FCS 0x08 | ||
377 | #define AR9170_RX_ERROR_WRONG_RA 0x10 | ||
378 | #define AR9170_RX_ERROR_PLCP 0x20 | ||
379 | #define AR9170_RX_ERROR_MMIC 0x40 | ||
380 | #define AR9170_RX_ERROR_FATAL 0x80 | ||
381 | |||
382 | struct ar9170_cmd_tx_status { | ||
383 | u8 dst[ETH_ALEN]; | ||
384 | __le32 rate; | ||
385 | __le16 status; | ||
386 | } __packed; | ||
387 | |||
388 | #define AR9170_TX_STATUS_COMPLETE 0x00 | ||
389 | #define AR9170_TX_STATUS_RETRY 0x01 | ||
390 | #define AR9170_TX_STATUS_FAILED 0x02 | ||
391 | |||
392 | struct ar9170_cmd_ba_failed_count { | ||
393 | __le16 failed; | ||
394 | __le16 rate; | ||
395 | } __packed; | ||
396 | |||
397 | struct ar9170_cmd_response { | ||
398 | u8 flag; | ||
399 | u8 type; | ||
400 | __le16 padding; | ||
401 | |||
402 | union { | ||
403 | struct ar9170_cmd_tx_status tx_status; | ||
404 | struct ar9170_cmd_ba_failed_count ba_fail_cnt; | ||
405 | u8 data[0]; | ||
406 | }; | ||
407 | } __packed; | ||
408 | |||
409 | /* QoS */ | ||
410 | |||
411 | /* mac80211 queue to HW/FW map */ | ||
412 | static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 }; | ||
413 | |||
414 | /* HW/FW queue to mac80211 map */ | ||
415 | static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 }; | ||
416 | |||
417 | enum ar9170_txq { | ||
418 | AR9170_TXQ_BE, | ||
419 | AR9170_TXQ_BK, | ||
420 | AR9170_TXQ_VI, | ||
421 | AR9170_TXQ_VO, | ||
422 | |||
423 | __AR9170_NUM_TXQ, | ||
424 | }; | ||
425 | |||
426 | #define AR9170_TXQ_DEPTH 32 | ||
427 | #define AR9170_TX_MAX_PENDING 128 | ||
428 | #define AR9170_RX_STREAM_MAX_SIZE 65535 | ||
429 | |||
430 | #endif /* __AR9170_HW_H */ | ||
diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c deleted file mode 100644 index 832d90087f8a..000000000000 --- a/drivers/net/wireless/ath/ar9170/led.c +++ /dev/null | |||
@@ -1,181 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * LED handling | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include "ar9170.h" | ||
40 | #include "cmd.h" | ||
41 | |||
42 | int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state) | ||
43 | { | ||
44 | return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state); | ||
45 | } | ||
46 | |||
47 | int ar9170_init_leds(struct ar9170 *ar) | ||
48 | { | ||
49 | int err; | ||
50 | |||
51 | /* disable LEDs */ | ||
52 | /* GPIO [0/1 mode: output, 2/3: input] */ | ||
53 | err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); | ||
54 | if (err) | ||
55 | goto out; | ||
56 | |||
57 | /* GPIO 0/1 value: off */ | ||
58 | err = ar9170_set_leds_state(ar, 0); | ||
59 | |||
60 | out: | ||
61 | return err; | ||
62 | } | ||
63 | |||
64 | #ifdef CONFIG_AR9170_LEDS | ||
65 | static void ar9170_update_leds(struct work_struct *work) | ||
66 | { | ||
67 | struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); | ||
68 | int i, tmp, blink_delay = 1000; | ||
69 | u32 led_val = 0; | ||
70 | bool rerun = false; | ||
71 | |||
72 | if (unlikely(!IS_ACCEPTING_CMD(ar))) | ||
73 | return ; | ||
74 | |||
75 | mutex_lock(&ar->mutex); | ||
76 | for (i = 0; i < AR9170_NUM_LEDS; i++) | ||
77 | if (ar->leds[i].registered && ar->leds[i].toggled) { | ||
78 | led_val |= 1 << i; | ||
79 | |||
80 | tmp = 70 + 200 / (ar->leds[i].toggled); | ||
81 | if (tmp < blink_delay) | ||
82 | blink_delay = tmp; | ||
83 | |||
84 | if (ar->leds[i].toggled > 1) | ||
85 | ar->leds[i].toggled = 0; | ||
86 | |||
87 | rerun = true; | ||
88 | } | ||
89 | |||
90 | ar9170_set_leds_state(ar, led_val); | ||
91 | mutex_unlock(&ar->mutex); | ||
92 | |||
93 | if (!rerun) | ||
94 | return; | ||
95 | |||
96 | ieee80211_queue_delayed_work(ar->hw, | ||
97 | &ar->led_work, | ||
98 | msecs_to_jiffies(blink_delay)); | ||
99 | } | ||
100 | |||
101 | static void ar9170_led_brightness_set(struct led_classdev *led, | ||
102 | enum led_brightness brightness) | ||
103 | { | ||
104 | struct ar9170_led *arl = container_of(led, struct ar9170_led, l); | ||
105 | struct ar9170 *ar = arl->ar; | ||
106 | |||
107 | if (unlikely(!arl->registered)) | ||
108 | return ; | ||
109 | |||
110 | if (arl->last_state != !!brightness) { | ||
111 | arl->toggled++; | ||
112 | arl->last_state = !!brightness; | ||
113 | } | ||
114 | |||
115 | if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) | ||
116 | ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10); | ||
117 | } | ||
118 | |||
119 | static int ar9170_register_led(struct ar9170 *ar, int i, char *name, | ||
120 | char *trigger) | ||
121 | { | ||
122 | int err; | ||
123 | |||
124 | snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), | ||
125 | "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name); | ||
126 | |||
127 | ar->leds[i].ar = ar; | ||
128 | ar->leds[i].l.name = ar->leds[i].name; | ||
129 | ar->leds[i].l.brightness_set = ar9170_led_brightness_set; | ||
130 | ar->leds[i].l.brightness = 0; | ||
131 | ar->leds[i].l.default_trigger = trigger; | ||
132 | |||
133 | err = led_classdev_register(wiphy_dev(ar->hw->wiphy), | ||
134 | &ar->leds[i].l); | ||
135 | if (err) | ||
136 | wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n", | ||
137 | ar->leds[i].name, err); | ||
138 | else | ||
139 | ar->leds[i].registered = true; | ||
140 | |||
141 | return err; | ||
142 | } | ||
143 | |||
144 | void ar9170_unregister_leds(struct ar9170 *ar) | ||
145 | { | ||
146 | int i; | ||
147 | |||
148 | for (i = 0; i < AR9170_NUM_LEDS; i++) | ||
149 | if (ar->leds[i].registered) { | ||
150 | led_classdev_unregister(&ar->leds[i].l); | ||
151 | ar->leds[i].registered = false; | ||
152 | ar->leds[i].toggled = 0; | ||
153 | } | ||
154 | |||
155 | cancel_delayed_work_sync(&ar->led_work); | ||
156 | } | ||
157 | |||
158 | int ar9170_register_leds(struct ar9170 *ar) | ||
159 | { | ||
160 | int err; | ||
161 | |||
162 | INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds); | ||
163 | |||
164 | err = ar9170_register_led(ar, 0, "tx", | ||
165 | ieee80211_get_tx_led_name(ar->hw)); | ||
166 | if (err) | ||
167 | goto fail; | ||
168 | |||
169 | err = ar9170_register_led(ar, 1, "assoc", | ||
170 | ieee80211_get_assoc_led_name(ar->hw)); | ||
171 | if (err) | ||
172 | goto fail; | ||
173 | |||
174 | return 0; | ||
175 | |||
176 | fail: | ||
177 | ar9170_unregister_leds(ar); | ||
178 | return err; | ||
179 | } | ||
180 | |||
181 | #endif /* CONFIG_AR9170_LEDS */ | ||
diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c deleted file mode 100644 index 857e86104295..000000000000 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ /dev/null | |||
@@ -1,519 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * MAC programming | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include <asm/unaligned.h> | ||
40 | |||
41 | #include "ar9170.h" | ||
42 | #include "cmd.h" | ||
43 | |||
44 | int ar9170_set_dyn_sifs_ack(struct ar9170 *ar) | ||
45 | { | ||
46 | u32 val; | ||
47 | |||
48 | if (conf_is_ht40(&ar->hw->conf)) | ||
49 | val = 0x010a; | ||
50 | else { | ||
51 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) | ||
52 | val = 0x105; | ||
53 | else | ||
54 | val = 0x104; | ||
55 | } | ||
56 | |||
57 | return ar9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val); | ||
58 | } | ||
59 | |||
60 | int ar9170_set_slot_time(struct ar9170 *ar) | ||
61 | { | ||
62 | u32 slottime = 20; | ||
63 | |||
64 | if (!ar->vif) | ||
65 | return 0; | ||
66 | |||
67 | if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) || | ||
68 | ar->vif->bss_conf.use_short_slot) | ||
69 | slottime = 9; | ||
70 | |||
71 | return ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, slottime << 10); | ||
72 | } | ||
73 | |||
74 | int ar9170_set_basic_rates(struct ar9170 *ar) | ||
75 | { | ||
76 | u8 cck, ofdm; | ||
77 | |||
78 | if (!ar->vif) | ||
79 | return 0; | ||
80 | |||
81 | ofdm = ar->vif->bss_conf.basic_rates >> 4; | ||
82 | |||
83 | /* FIXME: is still necessary? */ | ||
84 | if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) | ||
85 | cck = 0; | ||
86 | else | ||
87 | cck = ar->vif->bss_conf.basic_rates & 0xf; | ||
88 | |||
89 | return ar9170_write_reg(ar, AR9170_MAC_REG_BASIC_RATE, | ||
90 | ofdm << 8 | cck); | ||
91 | } | ||
92 | |||
93 | int ar9170_set_qos(struct ar9170 *ar) | ||
94 | { | ||
95 | ar9170_regwrite_begin(ar); | ||
96 | |||
97 | ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | | ||
98 | (ar->edcf[0].cw_max << 16)); | ||
99 | ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | | ||
100 | (ar->edcf[1].cw_max << 16)); | ||
101 | ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | | ||
102 | (ar->edcf[2].cw_max << 16)); | ||
103 | ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | | ||
104 | (ar->edcf[3].cw_max << 16)); | ||
105 | ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | | ||
106 | (ar->edcf[4].cw_max << 16)); | ||
107 | |||
108 | ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS, | ||
109 | ((ar->edcf[0].aifs * 9 + 10)) | | ||
110 | ((ar->edcf[1].aifs * 9 + 10) << 12) | | ||
111 | ((ar->edcf[2].aifs * 9 + 10) << 24)); | ||
112 | ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS, | ||
113 | ((ar->edcf[2].aifs * 9 + 10) >> 8) | | ||
114 | ((ar->edcf[3].aifs * 9 + 10) << 4) | | ||
115 | ((ar->edcf[4].aifs * 9 + 10) << 16)); | ||
116 | |||
117 | ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, | ||
118 | ar->edcf[0].txop | ar->edcf[1].txop << 16); | ||
119 | ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, | ||
120 | ar->edcf[2].txop | ar->edcf[3].txop << 16); | ||
121 | |||
122 | ar9170_regwrite_finish(); | ||
123 | |||
124 | return ar9170_regwrite_result(); | ||
125 | } | ||
126 | |||
127 | static int ar9170_set_ampdu_density(struct ar9170 *ar, u8 mpdudensity) | ||
128 | { | ||
129 | u32 val; | ||
130 | |||
131 | /* don't allow AMPDU density > 8us */ | ||
132 | if (mpdudensity > 6) | ||
133 | return -EINVAL; | ||
134 | |||
135 | /* Watch out! Otus uses slightly different density values. */ | ||
136 | val = 0x140a00 | (mpdudensity ? (mpdudensity + 1) : 0); | ||
137 | |||
138 | ar9170_regwrite_begin(ar); | ||
139 | ar9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, val); | ||
140 | ar9170_regwrite_finish(); | ||
141 | |||
142 | return ar9170_regwrite_result(); | ||
143 | } | ||
144 | |||
145 | int ar9170_init_mac(struct ar9170 *ar) | ||
146 | { | ||
147 | ar9170_regwrite_begin(ar); | ||
148 | |||
149 | ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); | ||
150 | |||
151 | ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0); | ||
152 | |||
153 | /* enable MMIC */ | ||
154 | ar9170_regwrite(AR9170_MAC_REG_SNIFFER, | ||
155 | AR9170_MAC_REG_SNIFFER_DEFAULTS); | ||
156 | |||
157 | ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); | ||
158 | |||
159 | ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); | ||
160 | ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); | ||
161 | ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); | ||
162 | |||
163 | /* CF-END mode */ | ||
164 | ar9170_regwrite(0x1c3b2c, 0x19000000); | ||
165 | |||
166 | /* NAV protects ACK only (in TXOP) */ | ||
167 | ar9170_regwrite(0x1c3b38, 0x201); | ||
168 | |||
169 | /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ | ||
170 | /* OTUS set AM to 0x1 */ | ||
171 | ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); | ||
172 | |||
173 | ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); | ||
174 | |||
175 | /* AGG test code*/ | ||
176 | /* Aggregation MAX number and timeout */ | ||
177 | ar9170_regwrite(0x1c3b9c, 0x10000a); | ||
178 | |||
179 | ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, | ||
180 | AR9170_MAC_REG_FTF_DEFAULTS); | ||
181 | |||
182 | /* Enable deaggregator, response in sniffer mode */ | ||
183 | ar9170_regwrite(0x1c3c40, 0x1 | 1<<30); | ||
184 | |||
185 | /* rate sets */ | ||
186 | ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); | ||
187 | ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); | ||
188 | ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb); | ||
189 | |||
190 | /* MIMO response control */ | ||
191 | ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */ | ||
192 | |||
193 | /* switch MAC to OTUS interface */ | ||
194 | ar9170_regwrite(0x1c3600, 0x3); | ||
195 | |||
196 | ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); | ||
197 | |||
198 | /* set PHY register read timeout (??) */ | ||
199 | ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); | ||
200 | |||
201 | /* Disable Rx TimeOut, workaround for BB. */ | ||
202 | ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); | ||
203 | |||
204 | /* Set CPU clock frequency to 88/80MHz */ | ||
205 | ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL, | ||
206 | AR9170_PWR_CLK_AHB_80_88MHZ | | ||
207 | AR9170_PWR_CLK_DAC_160_INV_DLY); | ||
208 | |||
209 | /* Set WLAN DMA interrupt mode: generate int per packet */ | ||
210 | ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); | ||
211 | |||
212 | ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT, | ||
213 | AR9170_MAC_FCS_FIFO_PROT); | ||
214 | |||
215 | /* Disables the CF_END frame, undocumented register */ | ||
216 | ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, | ||
217 | 0x141E0F48); | ||
218 | |||
219 | ar9170_regwrite_finish(); | ||
220 | |||
221 | return ar9170_regwrite_result(); | ||
222 | } | ||
223 | |||
224 | static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) | ||
225 | { | ||
226 | static const u8 zero[ETH_ALEN] = { 0 }; | ||
227 | |||
228 | if (!mac) | ||
229 | mac = zero; | ||
230 | |||
231 | ar9170_regwrite_begin(ar); | ||
232 | |||
233 | ar9170_regwrite(reg, get_unaligned_le32(mac)); | ||
234 | ar9170_regwrite(reg + 4, get_unaligned_le16(mac + 4)); | ||
235 | |||
236 | ar9170_regwrite_finish(); | ||
237 | |||
238 | return ar9170_regwrite_result(); | ||
239 | } | ||
240 | |||
241 | int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash) | ||
242 | { | ||
243 | int err; | ||
244 | |||
245 | ar9170_regwrite_begin(ar); | ||
246 | ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32); | ||
247 | ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash); | ||
248 | ar9170_regwrite_finish(); | ||
249 | err = ar9170_regwrite_result(); | ||
250 | if (err) | ||
251 | return err; | ||
252 | |||
253 | ar->cur_mc_hash = mc_hash; | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter) | ||
258 | { | ||
259 | int err; | ||
260 | |||
261 | err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter); | ||
262 | if (err) | ||
263 | return err; | ||
264 | |||
265 | ar->cur_filter = filter; | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static int ar9170_set_promiscouous(struct ar9170 *ar) | ||
270 | { | ||
271 | u32 encr_mode, sniffer; | ||
272 | int err; | ||
273 | |||
274 | err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer); | ||
275 | if (err) | ||
276 | return err; | ||
277 | |||
278 | err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode); | ||
279 | if (err) | ||
280 | return err; | ||
281 | |||
282 | if (ar->sniffer_enabled) { | ||
283 | sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; | ||
284 | |||
285 | /* | ||
286 | * Rx decryption works in place. | ||
287 | * | ||
288 | * If we don't disable it, the hardware will render all | ||
289 | * encrypted frames which are encrypted with an unknown | ||
290 | * key useless. | ||
291 | */ | ||
292 | |||
293 | encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; | ||
294 | ar->sniffer_enabled = true; | ||
295 | } else { | ||
296 | sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; | ||
297 | |||
298 | if (ar->rx_software_decryption) | ||
299 | encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; | ||
300 | else | ||
301 | encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; | ||
302 | } | ||
303 | |||
304 | ar9170_regwrite_begin(ar); | ||
305 | ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode); | ||
306 | ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); | ||
307 | ar9170_regwrite_finish(); | ||
308 | |||
309 | return ar9170_regwrite_result(); | ||
310 | } | ||
311 | |||
312 | int ar9170_set_operating_mode(struct ar9170 *ar) | ||
313 | { | ||
314 | struct ath_common *common = &ar->common; | ||
315 | u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; | ||
316 | u8 *mac_addr, *bssid; | ||
317 | int err; | ||
318 | |||
319 | if (ar->vif) { | ||
320 | mac_addr = common->macaddr; | ||
321 | bssid = common->curbssid; | ||
322 | |||
323 | switch (ar->vif->type) { | ||
324 | case NL80211_IFTYPE_MESH_POINT: | ||
325 | case NL80211_IFTYPE_ADHOC: | ||
326 | pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; | ||
327 | break; | ||
328 | case NL80211_IFTYPE_AP: | ||
329 | pm_mode |= AR9170_MAC_REG_POWERMGT_AP; | ||
330 | break; | ||
331 | case NL80211_IFTYPE_WDS: | ||
332 | pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; | ||
333 | break; | ||
334 | case NL80211_IFTYPE_MONITOR: | ||
335 | ar->sniffer_enabled = true; | ||
336 | ar->rx_software_decryption = true; | ||
337 | break; | ||
338 | default: | ||
339 | pm_mode |= AR9170_MAC_REG_POWERMGT_STA; | ||
340 | break; | ||
341 | } | ||
342 | } else { | ||
343 | mac_addr = NULL; | ||
344 | bssid = NULL; | ||
345 | } | ||
346 | |||
347 | err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); | ||
348 | if (err) | ||
349 | return err; | ||
350 | |||
351 | err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); | ||
352 | if (err) | ||
353 | return err; | ||
354 | |||
355 | err = ar9170_set_promiscouous(ar); | ||
356 | if (err) | ||
357 | return err; | ||
358 | |||
359 | /* set AMPDU density to 8us. */ | ||
360 | err = ar9170_set_ampdu_density(ar, 6); | ||
361 | if (err) | ||
362 | return err; | ||
363 | |||
364 | ar9170_regwrite_begin(ar); | ||
365 | |||
366 | ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); | ||
367 | ar9170_regwrite_finish(); | ||
368 | |||
369 | return ar9170_regwrite_result(); | ||
370 | } | ||
371 | |||
372 | int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry) | ||
373 | { | ||
374 | u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); | ||
375 | |||
376 | return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); | ||
377 | } | ||
378 | |||
379 | int ar9170_set_beacon_timers(struct ar9170 *ar) | ||
380 | { | ||
381 | u32 v = 0; | ||
382 | u32 pretbtt = 0; | ||
383 | |||
384 | if (ar->vif) { | ||
385 | v |= ar->vif->bss_conf.beacon_int; | ||
386 | |||
387 | if (ar->enable_beacon) { | ||
388 | switch (ar->vif->type) { | ||
389 | case NL80211_IFTYPE_MESH_POINT: | ||
390 | case NL80211_IFTYPE_ADHOC: | ||
391 | v |= BIT(25); | ||
392 | break; | ||
393 | case NL80211_IFTYPE_AP: | ||
394 | v |= BIT(24); | ||
395 | pretbtt = (ar->vif->bss_conf.beacon_int - 6) << | ||
396 | 16; | ||
397 | break; | ||
398 | default: | ||
399 | break; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | v |= ar->vif->bss_conf.dtim_period << 16; | ||
404 | } | ||
405 | |||
406 | ar9170_regwrite_begin(ar); | ||
407 | ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); | ||
408 | ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); | ||
409 | ar9170_regwrite_finish(); | ||
410 | return ar9170_regwrite_result(); | ||
411 | } | ||
412 | |||
413 | int ar9170_update_beacon(struct ar9170 *ar) | ||
414 | { | ||
415 | struct sk_buff *skb; | ||
416 | __le32 *data, *old = NULL; | ||
417 | u32 word; | ||
418 | int i; | ||
419 | |||
420 | skb = ieee80211_beacon_get(ar->hw, ar->vif); | ||
421 | if (!skb) | ||
422 | return -ENOMEM; | ||
423 | |||
424 | data = (__le32 *)skb->data; | ||
425 | if (ar->beacon) | ||
426 | old = (__le32 *)ar->beacon->data; | ||
427 | |||
428 | ar9170_regwrite_begin(ar); | ||
429 | for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { | ||
430 | /* | ||
431 | * XXX: This accesses beyond skb data for up | ||
432 | * to the last 3 bytes!! | ||
433 | */ | ||
434 | |||
435 | if (old && (data[i] == old[i])) | ||
436 | continue; | ||
437 | |||
438 | word = le32_to_cpu(data[i]); | ||
439 | ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word); | ||
440 | } | ||
441 | |||
442 | /* XXX: use skb->cb info */ | ||
443 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) | ||
444 | ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, | ||
445 | ((skb->len + 4) << (3 + 16)) + 0x0400); | ||
446 | else | ||
447 | ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, | ||
448 | ((skb->len + 4) << 16) + 0x001b); | ||
449 | |||
450 | ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4); | ||
451 | ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS); | ||
452 | ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1); | ||
453 | |||
454 | ar9170_regwrite_finish(); | ||
455 | |||
456 | dev_kfree_skb(ar->beacon); | ||
457 | ar->beacon = skb; | ||
458 | |||
459 | return ar9170_regwrite_result(); | ||
460 | } | ||
461 | |||
462 | void ar9170_new_beacon(struct work_struct *work) | ||
463 | { | ||
464 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
465 | beacon_work); | ||
466 | struct sk_buff *skb; | ||
467 | |||
468 | if (unlikely(!IS_STARTED(ar))) | ||
469 | return ; | ||
470 | |||
471 | mutex_lock(&ar->mutex); | ||
472 | |||
473 | if (!ar->vif) | ||
474 | goto out; | ||
475 | |||
476 | ar9170_update_beacon(ar); | ||
477 | |||
478 | rcu_read_lock(); | ||
479 | while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif))) | ||
480 | ar9170_op_tx(ar->hw, skb); | ||
481 | |||
482 | rcu_read_unlock(); | ||
483 | |||
484 | out: | ||
485 | mutex_unlock(&ar->mutex); | ||
486 | } | ||
487 | |||
488 | int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, | ||
489 | u8 keyidx, u8 *keydata, int keylen) | ||
490 | { | ||
491 | __le32 vals[7]; | ||
492 | static const u8 bcast[ETH_ALEN] = | ||
493 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
494 | u8 dummy; | ||
495 | |||
496 | mac = mac ? : bcast; | ||
497 | |||
498 | vals[0] = cpu_to_le32((keyidx << 16) + id); | ||
499 | vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype); | ||
500 | vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 | | ||
501 | mac[3] << 8 | mac[2]); | ||
502 | memset(&vals[3], 0, 16); | ||
503 | if (keydata) | ||
504 | memcpy(&vals[3], keydata, keylen); | ||
505 | |||
506 | return ar->exec_cmd(ar, AR9170_CMD_EKEY, | ||
507 | sizeof(vals), (u8 *)vals, | ||
508 | 1, &dummy); | ||
509 | } | ||
510 | |||
511 | int ar9170_disable_key(struct ar9170 *ar, u8 id) | ||
512 | { | ||
513 | __le32 val = cpu_to_le32(id); | ||
514 | u8 dummy; | ||
515 | |||
516 | return ar->exec_cmd(ar, AR9170_CMD_EKEY, | ||
517 | sizeof(val), (u8 *)&val, | ||
518 | 1, &dummy); | ||
519 | } | ||
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c deleted file mode 100644 index ccc2edaaeda0..000000000000 --- a/drivers/net/wireless/ath/ar9170/main.c +++ /dev/null | |||
@@ -1,2190 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * mac80211 interaction code | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, Christian Lamparter <chunkeey@web.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/module.h> | ||
43 | #include <linux/etherdevice.h> | ||
44 | #include <net/mac80211.h> | ||
45 | #include "ar9170.h" | ||
46 | #include "hw.h" | ||
47 | #include "cmd.h" | ||
48 | |||
49 | static int modparam_nohwcrypt; | ||
50 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | ||
51 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | ||
52 | |||
53 | #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ | ||
54 | .bitrate = (_bitrate), \ | ||
55 | .flags = (_flags), \ | ||
56 | .hw_value = (_hw_rate) | (_txpidx) << 4, \ | ||
57 | } | ||
58 | |||
59 | static struct ieee80211_rate __ar9170_ratetable[] = { | ||
60 | RATE(10, 0, 0, 0), | ||
61 | RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), | ||
62 | RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), | ||
63 | RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), | ||
64 | RATE(60, 0xb, 0, 0), | ||
65 | RATE(90, 0xf, 0, 0), | ||
66 | RATE(120, 0xa, 0, 0), | ||
67 | RATE(180, 0xe, 0, 0), | ||
68 | RATE(240, 0x9, 0, 0), | ||
69 | RATE(360, 0xd, 1, 0), | ||
70 | RATE(480, 0x8, 2, 0), | ||
71 | RATE(540, 0xc, 3, 0), | ||
72 | }; | ||
73 | #undef RATE | ||
74 | |||
75 | #define ar9170_g_ratetable (__ar9170_ratetable + 0) | ||
76 | #define ar9170_g_ratetable_size 12 | ||
77 | #define ar9170_a_ratetable (__ar9170_ratetable + 4) | ||
78 | #define ar9170_a_ratetable_size 8 | ||
79 | |||
80 | /* | ||
81 | * NB: The hw_value is used as an index into the ar9170_phy_freq_params | ||
82 | * array in phy.c so that we don't have to do frequency lookups! | ||
83 | */ | ||
84 | #define CHAN(_freq, _idx) { \ | ||
85 | .center_freq = (_freq), \ | ||
86 | .hw_value = (_idx), \ | ||
87 | .max_power = 18, /* XXX */ \ | ||
88 | } | ||
89 | |||
90 | static struct ieee80211_channel ar9170_2ghz_chantable[] = { | ||
91 | CHAN(2412, 0), | ||
92 | CHAN(2417, 1), | ||
93 | CHAN(2422, 2), | ||
94 | CHAN(2427, 3), | ||
95 | CHAN(2432, 4), | ||
96 | CHAN(2437, 5), | ||
97 | CHAN(2442, 6), | ||
98 | CHAN(2447, 7), | ||
99 | CHAN(2452, 8), | ||
100 | CHAN(2457, 9), | ||
101 | CHAN(2462, 10), | ||
102 | CHAN(2467, 11), | ||
103 | CHAN(2472, 12), | ||
104 | CHAN(2484, 13), | ||
105 | }; | ||
106 | |||
107 | static struct ieee80211_channel ar9170_5ghz_chantable[] = { | ||
108 | CHAN(4920, 14), | ||
109 | CHAN(4940, 15), | ||
110 | CHAN(4960, 16), | ||
111 | CHAN(4980, 17), | ||
112 | CHAN(5040, 18), | ||
113 | CHAN(5060, 19), | ||
114 | CHAN(5080, 20), | ||
115 | CHAN(5180, 21), | ||
116 | CHAN(5200, 22), | ||
117 | CHAN(5220, 23), | ||
118 | CHAN(5240, 24), | ||
119 | CHAN(5260, 25), | ||
120 | CHAN(5280, 26), | ||
121 | CHAN(5300, 27), | ||
122 | CHAN(5320, 28), | ||
123 | CHAN(5500, 29), | ||
124 | CHAN(5520, 30), | ||
125 | CHAN(5540, 31), | ||
126 | CHAN(5560, 32), | ||
127 | CHAN(5580, 33), | ||
128 | CHAN(5600, 34), | ||
129 | CHAN(5620, 35), | ||
130 | CHAN(5640, 36), | ||
131 | CHAN(5660, 37), | ||
132 | CHAN(5680, 38), | ||
133 | CHAN(5700, 39), | ||
134 | CHAN(5745, 40), | ||
135 | CHAN(5765, 41), | ||
136 | CHAN(5785, 42), | ||
137 | CHAN(5805, 43), | ||
138 | CHAN(5825, 44), | ||
139 | CHAN(5170, 45), | ||
140 | CHAN(5190, 46), | ||
141 | CHAN(5210, 47), | ||
142 | CHAN(5230, 48), | ||
143 | }; | ||
144 | #undef CHAN | ||
145 | |||
146 | #define AR9170_HT_CAP \ | ||
147 | { \ | ||
148 | .ht_supported = true, \ | ||
149 | .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ | ||
150 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ | ||
151 | IEEE80211_HT_CAP_SGI_40 | \ | ||
152 | IEEE80211_HT_CAP_GRN_FLD | \ | ||
153 | IEEE80211_HT_CAP_DSSSCCK40 | \ | ||
154 | IEEE80211_HT_CAP_SM_PS, \ | ||
155 | .ampdu_factor = 3, \ | ||
156 | .ampdu_density = 6, \ | ||
157 | .mcs = { \ | ||
158 | .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ | ||
159 | .rx_highest = cpu_to_le16(300), \ | ||
160 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ | ||
161 | }, \ | ||
162 | } | ||
163 | |||
164 | static struct ieee80211_supported_band ar9170_band_2GHz = { | ||
165 | .channels = ar9170_2ghz_chantable, | ||
166 | .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), | ||
167 | .bitrates = ar9170_g_ratetable, | ||
168 | .n_bitrates = ar9170_g_ratetable_size, | ||
169 | .ht_cap = AR9170_HT_CAP, | ||
170 | }; | ||
171 | |||
172 | static struct ieee80211_supported_band ar9170_band_5GHz = { | ||
173 | .channels = ar9170_5ghz_chantable, | ||
174 | .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), | ||
175 | .bitrates = ar9170_a_ratetable, | ||
176 | .n_bitrates = ar9170_a_ratetable_size, | ||
177 | .ht_cap = AR9170_HT_CAP, | ||
178 | }; | ||
179 | |||
180 | static void ar9170_tx(struct ar9170 *ar); | ||
181 | |||
182 | static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) | ||
183 | { | ||
184 | return le16_to_cpu(hdr->seq_ctrl) >> 4; | ||
185 | } | ||
186 | |||
187 | static inline u16 ar9170_get_seq(struct sk_buff *skb) | ||
188 | { | ||
189 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
190 | return ar9170_get_seq_h((void *) txc->frame_data); | ||
191 | } | ||
192 | |||
193 | #ifdef AR9170_QUEUE_DEBUG | ||
194 | static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) | ||
195 | { | ||
196 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
197 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
198 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | ||
199 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | ||
200 | |||
201 | wiphy_debug(ar->hw->wiphy, | ||
202 | "=> FRAME [skb:%p, q:%d, DA:[%pM] s:%d " | ||
203 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", | ||
204 | skb, skb_get_queue_mapping(skb), | ||
205 | ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), | ||
206 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), | ||
207 | jiffies_to_msecs(arinfo->timeout - jiffies)); | ||
208 | } | ||
209 | |||
210 | static void __ar9170_dump_txqueue(struct ar9170 *ar, | ||
211 | struct sk_buff_head *queue) | ||
212 | { | ||
213 | struct sk_buff *skb; | ||
214 | int i = 0; | ||
215 | |||
216 | printk(KERN_DEBUG "---[ cut here ]---\n"); | ||
217 | wiphy_debug(ar->hw->wiphy, "%d entries in queue.\n", | ||
218 | skb_queue_len(queue)); | ||
219 | |||
220 | skb_queue_walk(queue, skb) { | ||
221 | printk(KERN_DEBUG "index:%d =>\n", i++); | ||
222 | ar9170_print_txheader(ar, skb); | ||
223 | } | ||
224 | if (i != skb_queue_len(queue)) | ||
225 | printk(KERN_DEBUG "WARNING: queue frame counter " | ||
226 | "mismatch %d != %d\n", skb_queue_len(queue), i); | ||
227 | printk(KERN_DEBUG "---[ end ]---\n"); | ||
228 | } | ||
229 | #endif /* AR9170_QUEUE_DEBUG */ | ||
230 | |||
231 | #ifdef AR9170_QUEUE_DEBUG | ||
232 | static void ar9170_dump_txqueue(struct ar9170 *ar, | ||
233 | struct sk_buff_head *queue) | ||
234 | { | ||
235 | unsigned long flags; | ||
236 | |||
237 | spin_lock_irqsave(&queue->lock, flags); | ||
238 | __ar9170_dump_txqueue(ar, queue); | ||
239 | spin_unlock_irqrestore(&queue->lock, flags); | ||
240 | } | ||
241 | #endif /* AR9170_QUEUE_DEBUG */ | ||
242 | |||
243 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
244 | static void __ar9170_dump_txstats(struct ar9170 *ar) | ||
245 | { | ||
246 | int i; | ||
247 | |||
248 | wiphy_debug(ar->hw->wiphy, "QoS queue stats\n"); | ||
249 | |||
250 | for (i = 0; i < __AR9170_NUM_TXQ; i++) | ||
251 | wiphy_debug(ar->hw->wiphy, | ||
252 | "queue:%d limit:%d len:%d waitack:%d stopped:%d\n", | ||
253 | i, ar->tx_stats[i].limit, ar->tx_stats[i].len, | ||
254 | skb_queue_len(&ar->tx_status[i]), | ||
255 | ieee80211_queue_stopped(ar->hw, i)); | ||
256 | } | ||
257 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
258 | |||
259 | /* caller must guarantee exclusive access for _bin_ queue. */ | ||
260 | static void ar9170_recycle_expired(struct ar9170 *ar, | ||
261 | struct sk_buff_head *queue, | ||
262 | struct sk_buff_head *bin) | ||
263 | { | ||
264 | struct sk_buff *skb, *old = NULL; | ||
265 | unsigned long flags; | ||
266 | |||
267 | spin_lock_irqsave(&queue->lock, flags); | ||
268 | while ((skb = skb_peek(queue))) { | ||
269 | struct ieee80211_tx_info *txinfo; | ||
270 | struct ar9170_tx_info *arinfo; | ||
271 | |||
272 | txinfo = IEEE80211_SKB_CB(skb); | ||
273 | arinfo = (void *) txinfo->rate_driver_data; | ||
274 | |||
275 | if (time_is_before_jiffies(arinfo->timeout)) { | ||
276 | #ifdef AR9170_QUEUE_DEBUG | ||
277 | wiphy_debug(ar->hw->wiphy, | ||
278 | "[%ld > %ld] frame expired => recycle\n", | ||
279 | jiffies, arinfo->timeout); | ||
280 | ar9170_print_txheader(ar, skb); | ||
281 | #endif /* AR9170_QUEUE_DEBUG */ | ||
282 | __skb_unlink(skb, queue); | ||
283 | __skb_queue_tail(bin, skb); | ||
284 | } else { | ||
285 | break; | ||
286 | } | ||
287 | |||
288 | if (unlikely(old == skb)) { | ||
289 | /* bail out - queue is shot. */ | ||
290 | |||
291 | WARN_ON(1); | ||
292 | break; | ||
293 | } | ||
294 | old = skb; | ||
295 | } | ||
296 | spin_unlock_irqrestore(&queue->lock, flags); | ||
297 | } | ||
298 | |||
299 | static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, | ||
300 | u16 tx_status) | ||
301 | { | ||
302 | struct ieee80211_tx_info *txinfo; | ||
303 | unsigned int retries = 0; | ||
304 | |||
305 | txinfo = IEEE80211_SKB_CB(skb); | ||
306 | ieee80211_tx_info_clear_status(txinfo); | ||
307 | |||
308 | switch (tx_status) { | ||
309 | case AR9170_TX_STATUS_RETRY: | ||
310 | retries = 2; | ||
311 | case AR9170_TX_STATUS_COMPLETE: | ||
312 | txinfo->flags |= IEEE80211_TX_STAT_ACK; | ||
313 | break; | ||
314 | |||
315 | case AR9170_TX_STATUS_FAILED: | ||
316 | retries = ar->hw->conf.long_frame_max_tx_count; | ||
317 | break; | ||
318 | |||
319 | default: | ||
320 | wiphy_err(ar->hw->wiphy, | ||
321 | "invalid tx_status response (%x)\n", tx_status); | ||
322 | break; | ||
323 | } | ||
324 | |||
325 | txinfo->status.rates[0].count = retries + 1; | ||
326 | skb_pull(skb, sizeof(struct ar9170_tx_control)); | ||
327 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
328 | } | ||
329 | |||
330 | void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | ||
331 | { | ||
332 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
333 | struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data; | ||
334 | unsigned int queue = skb_get_queue_mapping(skb); | ||
335 | unsigned long flags; | ||
336 | |||
337 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | ||
338 | ar->tx_stats[queue].len--; | ||
339 | |||
340 | if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { | ||
341 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
342 | wiphy_debug(ar->hw->wiphy, "wake queue %d\n", queue); | ||
343 | __ar9170_dump_txstats(ar); | ||
344 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
345 | ieee80211_wake_queue(ar->hw, queue); | ||
346 | } | ||
347 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | ||
348 | |||
349 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) { | ||
350 | ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); | ||
351 | } else { | ||
352 | arinfo->timeout = jiffies + | ||
353 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | ||
354 | |||
355 | skb_queue_tail(&ar->tx_status[queue], skb); | ||
356 | } | ||
357 | |||
358 | if (!ar->tx_stats[queue].len && | ||
359 | !skb_queue_empty(&ar->tx_pending[queue])) { | ||
360 | ar9170_tx(ar); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, | ||
365 | const u8 *mac, | ||
366 | struct sk_buff_head *queue, | ||
367 | const u32 rate) | ||
368 | { | ||
369 | unsigned long flags; | ||
370 | struct sk_buff *skb; | ||
371 | |||
372 | /* | ||
373 | * Unfortunately, the firmware does not tell to which (queued) frame | ||
374 | * this transmission status report belongs to. | ||
375 | * | ||
376 | * So we have to make risky guesses - with the scarce information | ||
377 | * the firmware provided (-> destination MAC, and phy_control) - | ||
378 | * and hope that we picked the right one... | ||
379 | */ | ||
380 | |||
381 | spin_lock_irqsave(&queue->lock, flags); | ||
382 | skb_queue_walk(queue, skb) { | ||
383 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
384 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | ||
385 | u32 r; | ||
386 | |||
387 | if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) { | ||
388 | #ifdef AR9170_QUEUE_DEBUG | ||
389 | wiphy_debug(ar->hw->wiphy, | ||
390 | "skip frame => DA %pM != %pM\n", | ||
391 | mac, ieee80211_get_DA(hdr)); | ||
392 | ar9170_print_txheader(ar, skb); | ||
393 | #endif /* AR9170_QUEUE_DEBUG */ | ||
394 | continue; | ||
395 | } | ||
396 | |||
397 | r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >> | ||
398 | AR9170_TX_PHY_MCS_SHIFT; | ||
399 | |||
400 | if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) { | ||
401 | #ifdef AR9170_QUEUE_DEBUG | ||
402 | wiphy_debug(ar->hw->wiphy, | ||
403 | "skip frame => rate %d != %d\n", rate, r); | ||
404 | ar9170_print_txheader(ar, skb); | ||
405 | #endif /* AR9170_QUEUE_DEBUG */ | ||
406 | continue; | ||
407 | } | ||
408 | |||
409 | __skb_unlink(skb, queue); | ||
410 | spin_unlock_irqrestore(&queue->lock, flags); | ||
411 | return skb; | ||
412 | } | ||
413 | |||
414 | #ifdef AR9170_QUEUE_DEBUG | ||
415 | wiphy_err(ar->hw->wiphy, | ||
416 | "ESS:[%pM] does not have any outstanding frames in queue.\n", | ||
417 | mac); | ||
418 | __ar9170_dump_txqueue(ar, queue); | ||
419 | #endif /* AR9170_QUEUE_DEBUG */ | ||
420 | spin_unlock_irqrestore(&queue->lock, flags); | ||
421 | |||
422 | return NULL; | ||
423 | } | ||
424 | |||
425 | /* | ||
426 | * This worker tries to keeps an maintain tx_status queues. | ||
427 | * So we can guarantee that incoming tx_status reports are | ||
428 | * actually for a pending frame. | ||
429 | */ | ||
430 | |||
431 | static void ar9170_tx_janitor(struct work_struct *work) | ||
432 | { | ||
433 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
434 | tx_janitor.work); | ||
435 | struct sk_buff_head waste; | ||
436 | unsigned int i; | ||
437 | bool resched = false; | ||
438 | |||
439 | if (unlikely(!IS_STARTED(ar))) | ||
440 | return ; | ||
441 | |||
442 | skb_queue_head_init(&waste); | ||
443 | |||
444 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | ||
445 | #ifdef AR9170_QUEUE_DEBUG | ||
446 | wiphy_debug(ar->hw->wiphy, "garbage collector scans queue:%d\n", | ||
447 | i); | ||
448 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); | ||
449 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); | ||
450 | #endif /* AR9170_QUEUE_DEBUG */ | ||
451 | |||
452 | ar9170_recycle_expired(ar, &ar->tx_status[i], &waste); | ||
453 | ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste); | ||
454 | skb_queue_purge(&waste); | ||
455 | |||
456 | if (!skb_queue_empty(&ar->tx_status[i]) || | ||
457 | !skb_queue_empty(&ar->tx_pending[i])) | ||
458 | resched = true; | ||
459 | } | ||
460 | |||
461 | if (!resched) | ||
462 | return; | ||
463 | |||
464 | ieee80211_queue_delayed_work(ar->hw, | ||
465 | &ar->tx_janitor, | ||
466 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | ||
467 | } | ||
468 | |||
469 | void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | ||
470 | { | ||
471 | struct ar9170_cmd_response *cmd = (void *) buf; | ||
472 | |||
473 | if ((cmd->type & 0xc0) != 0xc0) { | ||
474 | ar->callback_cmd(ar, len, buf); | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | /* hardware event handlers */ | ||
479 | switch (cmd->type) { | ||
480 | case 0xc1: { | ||
481 | /* | ||
482 | * TX status notification: | ||
483 | * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1 | ||
484 | * | ||
485 | * XX always 81 | ||
486 | * YY always 00 | ||
487 | * M1-M6 is the MAC address | ||
488 | * R1-R4 is the transmit rate | ||
489 | * S1-S2 is the transmit status | ||
490 | */ | ||
491 | |||
492 | struct sk_buff *skb; | ||
493 | u32 phy = le32_to_cpu(cmd->tx_status.rate); | ||
494 | u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >> | ||
495 | AR9170_TX_PHY_QOS_SHIFT; | ||
496 | #ifdef AR9170_QUEUE_DEBUG | ||
497 | wiphy_debug(ar->hw->wiphy, | ||
498 | "recv tx_status for %pm, p:%08x, q:%d\n", | ||
499 | cmd->tx_status.dst, phy, q); | ||
500 | #endif /* AR9170_QUEUE_DEBUG */ | ||
501 | |||
502 | skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst, | ||
503 | &ar->tx_status[q], | ||
504 | AR9170_TX_INVALID_RATE); | ||
505 | if (unlikely(!skb)) | ||
506 | return ; | ||
507 | |||
508 | ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status)); | ||
509 | break; | ||
510 | } | ||
511 | |||
512 | case 0xc0: | ||
513 | /* | ||
514 | * pre-TBTT event | ||
515 | */ | ||
516 | if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) | ||
517 | ieee80211_queue_work(ar->hw, &ar->beacon_work); | ||
518 | break; | ||
519 | |||
520 | case 0xc2: | ||
521 | /* | ||
522 | * (IBSS) beacon send notification | ||
523 | * bytes: 04 c2 XX YY B4 B3 B2 B1 | ||
524 | * | ||
525 | * XX always 80 | ||
526 | * YY always 00 | ||
527 | * B1-B4 "should" be the number of send out beacons. | ||
528 | */ | ||
529 | break; | ||
530 | |||
531 | case 0xc3: | ||
532 | /* End of Atim Window */ | ||
533 | break; | ||
534 | |||
535 | case 0xc4: | ||
536 | /* BlockACK bitmap */ | ||
537 | break; | ||
538 | |||
539 | case 0xc5: | ||
540 | /* BlockACK events */ | ||
541 | break; | ||
542 | |||
543 | case 0xc6: | ||
544 | /* Watchdog Interrupt */ | ||
545 | break; | ||
546 | |||
547 | case 0xc9: | ||
548 | /* retransmission issue / SIFS/EIFS collision ?! */ | ||
549 | break; | ||
550 | |||
551 | /* firmware debug */ | ||
552 | case 0xca: | ||
553 | printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, | ||
554 | (char *)buf + 4); | ||
555 | break; | ||
556 | case 0xcb: | ||
557 | len -= 4; | ||
558 | |||
559 | switch (len) { | ||
560 | case 1: | ||
561 | printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n", | ||
562 | *((char *)buf + 4)); | ||
563 | break; | ||
564 | case 2: | ||
565 | printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n", | ||
566 | le16_to_cpup((__le16 *)((char *)buf + 4))); | ||
567 | break; | ||
568 | case 4: | ||
569 | printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n", | ||
570 | le32_to_cpup((__le32 *)((char *)buf + 4))); | ||
571 | break; | ||
572 | case 8: | ||
573 | printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n", | ||
574 | (unsigned long)le64_to_cpup( | ||
575 | (__le64 *)((char *)buf + 4))); | ||
576 | break; | ||
577 | } | ||
578 | break; | ||
579 | case 0xcc: | ||
580 | print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE, | ||
581 | (char *)buf + 4, len - 4); | ||
582 | break; | ||
583 | |||
584 | default: | ||
585 | pr_info("received unhandled event %x\n", cmd->type); | ||
586 | print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); | ||
587 | break; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar) | ||
592 | { | ||
593 | memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head)); | ||
594 | ar->rx_mpdu.has_plcp = false; | ||
595 | } | ||
596 | |||
597 | int ar9170_nag_limiter(struct ar9170 *ar) | ||
598 | { | ||
599 | bool print_message; | ||
600 | |||
601 | /* | ||
602 | * we expect all sorts of errors in promiscuous mode. | ||
603 | * don't bother with it, it's OK! | ||
604 | */ | ||
605 | if (ar->sniffer_enabled) | ||
606 | return false; | ||
607 | |||
608 | /* | ||
609 | * only go for frequent errors! The hardware tends to | ||
610 | * do some stupid thing once in a while under load, in | ||
611 | * noisy environments or just for fun! | ||
612 | */ | ||
613 | if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit()) | ||
614 | print_message = true; | ||
615 | else | ||
616 | print_message = false; | ||
617 | |||
618 | /* reset threshold for "once in a while" */ | ||
619 | ar->bad_hw_nagger = jiffies + HZ / 4; | ||
620 | return print_message; | ||
621 | } | ||
622 | |||
623 | static int ar9170_rx_mac_status(struct ar9170 *ar, | ||
624 | struct ar9170_rx_head *head, | ||
625 | struct ar9170_rx_macstatus *mac, | ||
626 | struct ieee80211_rx_status *status) | ||
627 | { | ||
628 | u8 error, decrypt; | ||
629 | |||
630 | BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); | ||
631 | BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); | ||
632 | |||
633 | error = mac->error; | ||
634 | if (error & AR9170_RX_ERROR_MMIC) { | ||
635 | status->flag |= RX_FLAG_MMIC_ERROR; | ||
636 | error &= ~AR9170_RX_ERROR_MMIC; | ||
637 | } | ||
638 | |||
639 | if (error & AR9170_RX_ERROR_PLCP) { | ||
640 | status->flag |= RX_FLAG_FAILED_PLCP_CRC; | ||
641 | error &= ~AR9170_RX_ERROR_PLCP; | ||
642 | |||
643 | if (!(ar->filter_state & FIF_PLCPFAIL)) | ||
644 | return -EINVAL; | ||
645 | } | ||
646 | |||
647 | if (error & AR9170_RX_ERROR_FCS) { | ||
648 | status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
649 | error &= ~AR9170_RX_ERROR_FCS; | ||
650 | |||
651 | if (!(ar->filter_state & FIF_FCSFAIL)) | ||
652 | return -EINVAL; | ||
653 | } | ||
654 | |||
655 | decrypt = ar9170_get_decrypt_type(mac); | ||
656 | if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && | ||
657 | decrypt != AR9170_ENC_ALG_NONE) | ||
658 | status->flag |= RX_FLAG_DECRYPTED; | ||
659 | |||
660 | /* ignore wrong RA errors */ | ||
661 | error &= ~AR9170_RX_ERROR_WRONG_RA; | ||
662 | |||
663 | if (error & AR9170_RX_ERROR_DECRYPT) { | ||
664 | error &= ~AR9170_RX_ERROR_DECRYPT; | ||
665 | /* | ||
666 | * Rx decryption is done in place, | ||
667 | * the original data is lost anyway. | ||
668 | */ | ||
669 | |||
670 | return -EINVAL; | ||
671 | } | ||
672 | |||
673 | /* drop any other error frames */ | ||
674 | if (unlikely(error)) { | ||
675 | /* TODO: update netdevice's RX dropped/errors statistics */ | ||
676 | |||
677 | if (ar9170_nag_limiter(ar)) | ||
678 | wiphy_debug(ar->hw->wiphy, | ||
679 | "received frame with suspicious error code (%#x).\n", | ||
680 | error); | ||
681 | |||
682 | return -EINVAL; | ||
683 | } | ||
684 | |||
685 | status->band = ar->channel->band; | ||
686 | status->freq = ar->channel->center_freq; | ||
687 | |||
688 | switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) { | ||
689 | case AR9170_RX_STATUS_MODULATION_CCK: | ||
690 | if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) | ||
691 | status->flag |= RX_FLAG_SHORTPRE; | ||
692 | switch (head->plcp[0]) { | ||
693 | case 0x0a: | ||
694 | status->rate_idx = 0; | ||
695 | break; | ||
696 | case 0x14: | ||
697 | status->rate_idx = 1; | ||
698 | break; | ||
699 | case 0x37: | ||
700 | status->rate_idx = 2; | ||
701 | break; | ||
702 | case 0x6e: | ||
703 | status->rate_idx = 3; | ||
704 | break; | ||
705 | default: | ||
706 | if (ar9170_nag_limiter(ar)) | ||
707 | wiphy_err(ar->hw->wiphy, | ||
708 | "invalid plcp cck rate (%x).\n", | ||
709 | head->plcp[0]); | ||
710 | return -EINVAL; | ||
711 | } | ||
712 | break; | ||
713 | |||
714 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | ||
715 | case AR9170_RX_STATUS_MODULATION_OFDM: | ||
716 | switch (head->plcp[0] & 0xf) { | ||
717 | case 0xb: | ||
718 | status->rate_idx = 0; | ||
719 | break; | ||
720 | case 0xf: | ||
721 | status->rate_idx = 1; | ||
722 | break; | ||
723 | case 0xa: | ||
724 | status->rate_idx = 2; | ||
725 | break; | ||
726 | case 0xe: | ||
727 | status->rate_idx = 3; | ||
728 | break; | ||
729 | case 0x9: | ||
730 | status->rate_idx = 4; | ||
731 | break; | ||
732 | case 0xd: | ||
733 | status->rate_idx = 5; | ||
734 | break; | ||
735 | case 0x8: | ||
736 | status->rate_idx = 6; | ||
737 | break; | ||
738 | case 0xc: | ||
739 | status->rate_idx = 7; | ||
740 | break; | ||
741 | default: | ||
742 | if (ar9170_nag_limiter(ar)) | ||
743 | wiphy_err(ar->hw->wiphy, | ||
744 | "invalid plcp ofdm rate (%x).\n", | ||
745 | head->plcp[0]); | ||
746 | return -EINVAL; | ||
747 | } | ||
748 | if (status->band == IEEE80211_BAND_2GHZ) | ||
749 | status->rate_idx += 4; | ||
750 | break; | ||
751 | |||
752 | case AR9170_RX_STATUS_MODULATION_HT: | ||
753 | if (head->plcp[3] & 0x80) | ||
754 | status->flag |= RX_FLAG_40MHZ; | ||
755 | if (head->plcp[6] & 0x80) | ||
756 | status->flag |= RX_FLAG_SHORT_GI; | ||
757 | |||
758 | status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f); | ||
759 | status->flag |= RX_FLAG_HT; | ||
760 | break; | ||
761 | |||
762 | default: | ||
763 | if (ar9170_nag_limiter(ar)) | ||
764 | wiphy_err(ar->hw->wiphy, "invalid modulation\n"); | ||
765 | return -EINVAL; | ||
766 | } | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | static void ar9170_rx_phy_status(struct ar9170 *ar, | ||
772 | struct ar9170_rx_phystatus *phy, | ||
773 | struct ieee80211_rx_status *status) | ||
774 | { | ||
775 | int i; | ||
776 | |||
777 | BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); | ||
778 | |||
779 | for (i = 0; i < 3; i++) | ||
780 | if (phy->rssi[i] != 0x80) | ||
781 | status->antenna |= BIT(i); | ||
782 | |||
783 | /* post-process RSSI */ | ||
784 | for (i = 0; i < 7; i++) | ||
785 | if (phy->rssi[i] & 0x80) | ||
786 | phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; | ||
787 | |||
788 | /* TODO: we could do something with phy_errors */ | ||
789 | status->signal = ar->noise[0] + phy->rssi_combined; | ||
790 | } | ||
791 | |||
792 | static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len) | ||
793 | { | ||
794 | struct sk_buff *skb; | ||
795 | int reserved = 0; | ||
796 | struct ieee80211_hdr *hdr = (void *) buf; | ||
797 | |||
798 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
799 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
800 | reserved += NET_IP_ALIGN; | ||
801 | |||
802 | if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | ||
803 | reserved += NET_IP_ALIGN; | ||
804 | } | ||
805 | |||
806 | if (ieee80211_has_a4(hdr->frame_control)) | ||
807 | reserved += NET_IP_ALIGN; | ||
808 | |||
809 | reserved = 32 + (reserved & NET_IP_ALIGN); | ||
810 | |||
811 | skb = dev_alloc_skb(len + reserved); | ||
812 | if (likely(skb)) { | ||
813 | skb_reserve(skb, reserved); | ||
814 | memcpy(skb_put(skb, len), buf, len); | ||
815 | } | ||
816 | |||
817 | return skb; | ||
818 | } | ||
819 | |||
820 | /* | ||
821 | * If the frame alignment is right (or the kernel has | ||
822 | * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there | ||
823 | * is only a single MPDU in the USB frame, then we could | ||
824 | * submit to mac80211 the SKB directly. However, since | ||
825 | * there may be multiple packets in one SKB in stream | ||
826 | * mode, and we need to observe the proper ordering, | ||
827 | * this is non-trivial. | ||
828 | */ | ||
829 | |||
830 | static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) | ||
831 | { | ||
832 | struct ar9170_rx_head *head; | ||
833 | struct ar9170_rx_macstatus *mac; | ||
834 | struct ar9170_rx_phystatus *phy = NULL; | ||
835 | struct ieee80211_rx_status status; | ||
836 | struct sk_buff *skb; | ||
837 | int mpdu_len; | ||
838 | |||
839 | if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac)))) | ||
840 | return ; | ||
841 | |||
842 | /* Received MPDU */ | ||
843 | mpdu_len = len - sizeof(*mac); | ||
844 | |||
845 | mac = (void *)(buf + mpdu_len); | ||
846 | if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) { | ||
847 | /* this frame is too damaged and can't be used - drop it */ | ||
848 | |||
849 | return ; | ||
850 | } | ||
851 | |||
852 | switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) { | ||
853 | case AR9170_RX_STATUS_MPDU_FIRST: | ||
854 | /* first mpdu packet has the plcp header */ | ||
855 | if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { | ||
856 | head = (void *) buf; | ||
857 | memcpy(&ar->rx_mpdu.plcp, (void *) buf, | ||
858 | sizeof(struct ar9170_rx_head)); | ||
859 | |||
860 | mpdu_len -= sizeof(struct ar9170_rx_head); | ||
861 | buf += sizeof(struct ar9170_rx_head); | ||
862 | ar->rx_mpdu.has_plcp = true; | ||
863 | } else { | ||
864 | if (ar9170_nag_limiter(ar)) | ||
865 | wiphy_err(ar->hw->wiphy, | ||
866 | "plcp info is clipped.\n"); | ||
867 | return ; | ||
868 | } | ||
869 | break; | ||
870 | |||
871 | case AR9170_RX_STATUS_MPDU_LAST: | ||
872 | /* last mpdu has a extra tail with phy status information */ | ||
873 | |||
874 | if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { | ||
875 | mpdu_len -= sizeof(struct ar9170_rx_phystatus); | ||
876 | phy = (void *)(buf + mpdu_len); | ||
877 | } else { | ||
878 | if (ar9170_nag_limiter(ar)) | ||
879 | wiphy_err(ar->hw->wiphy, | ||
880 | "frame tail is clipped.\n"); | ||
881 | return ; | ||
882 | } | ||
883 | |||
884 | case AR9170_RX_STATUS_MPDU_MIDDLE: | ||
885 | /* middle mpdus are just data */ | ||
886 | if (unlikely(!ar->rx_mpdu.has_plcp)) { | ||
887 | if (!ar9170_nag_limiter(ar)) | ||
888 | return ; | ||
889 | |||
890 | wiphy_err(ar->hw->wiphy, | ||
891 | "rx stream did not start with a first_mpdu frame tag.\n"); | ||
892 | |||
893 | return ; | ||
894 | } | ||
895 | |||
896 | head = &ar->rx_mpdu.plcp; | ||
897 | break; | ||
898 | |||
899 | case AR9170_RX_STATUS_MPDU_SINGLE: | ||
900 | /* single mpdu - has plcp (head) and phy status (tail) */ | ||
901 | head = (void *) buf; | ||
902 | |||
903 | mpdu_len -= sizeof(struct ar9170_rx_head); | ||
904 | mpdu_len -= sizeof(struct ar9170_rx_phystatus); | ||
905 | |||
906 | buf += sizeof(struct ar9170_rx_head); | ||
907 | phy = (void *)(buf + mpdu_len); | ||
908 | break; | ||
909 | |||
910 | default: | ||
911 | BUG_ON(1); | ||
912 | break; | ||
913 | } | ||
914 | |||
915 | if (unlikely(mpdu_len < FCS_LEN)) | ||
916 | return ; | ||
917 | |||
918 | memset(&status, 0, sizeof(status)); | ||
919 | if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status))) | ||
920 | return ; | ||
921 | |||
922 | if (phy) | ||
923 | ar9170_rx_phy_status(ar, phy, &status); | ||
924 | |||
925 | skb = ar9170_rx_copy_data(buf, mpdu_len); | ||
926 | if (likely(skb)) { | ||
927 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | ||
928 | ieee80211_rx_irqsafe(ar->hw, skb); | ||
929 | } | ||
930 | } | ||
931 | |||
932 | void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) | ||
933 | { | ||
934 | unsigned int i, tlen, resplen, wlen = 0, clen = 0; | ||
935 | u8 *tbuf, *respbuf; | ||
936 | |||
937 | tbuf = skb->data; | ||
938 | tlen = skb->len; | ||
939 | |||
940 | while (tlen >= 4) { | ||
941 | clen = tbuf[1] << 8 | tbuf[0]; | ||
942 | wlen = ALIGN(clen, 4); | ||
943 | |||
944 | /* check if this is stream has a valid tag.*/ | ||
945 | if (tbuf[2] != 0 || tbuf[3] != 0x4e) { | ||
946 | /* | ||
947 | * TODO: handle the highly unlikely event that the | ||
948 | * corrupted stream has the TAG at the right position. | ||
949 | */ | ||
950 | |||
951 | /* check if the frame can be repaired. */ | ||
952 | if (!ar->rx_failover_missing) { | ||
953 | /* this is no "short read". */ | ||
954 | if (ar9170_nag_limiter(ar)) { | ||
955 | wiphy_err(ar->hw->wiphy, | ||
956 | "missing tag!\n"); | ||
957 | goto err_telluser; | ||
958 | } else | ||
959 | goto err_silent; | ||
960 | } | ||
961 | |||
962 | if (ar->rx_failover_missing > tlen) { | ||
963 | if (ar9170_nag_limiter(ar)) { | ||
964 | wiphy_err(ar->hw->wiphy, | ||
965 | "possible multi stream corruption!\n"); | ||
966 | goto err_telluser; | ||
967 | } else | ||
968 | goto err_silent; | ||
969 | } | ||
970 | |||
971 | memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); | ||
972 | ar->rx_failover_missing -= tlen; | ||
973 | |||
974 | if (ar->rx_failover_missing <= 0) { | ||
975 | /* | ||
976 | * nested ar9170_rx call! | ||
977 | * termination is guaranteed, even when the | ||
978 | * combined frame also have a element with | ||
979 | * a bad tag. | ||
980 | */ | ||
981 | |||
982 | ar->rx_failover_missing = 0; | ||
983 | ar9170_rx(ar, ar->rx_failover); | ||
984 | |||
985 | skb_reset_tail_pointer(ar->rx_failover); | ||
986 | skb_trim(ar->rx_failover, 0); | ||
987 | } | ||
988 | |||
989 | return ; | ||
990 | } | ||
991 | |||
992 | /* check if stream is clipped */ | ||
993 | if (wlen > tlen - 4) { | ||
994 | if (ar->rx_failover_missing) { | ||
995 | /* TODO: handle double stream corruption. */ | ||
996 | if (ar9170_nag_limiter(ar)) { | ||
997 | wiphy_err(ar->hw->wiphy, | ||
998 | "double rx stream corruption!\n"); | ||
999 | goto err_telluser; | ||
1000 | } else | ||
1001 | goto err_silent; | ||
1002 | } | ||
1003 | |||
1004 | /* | ||
1005 | * save incomplete data set. | ||
1006 | * the firmware will resend the missing bits when | ||
1007 | * the rx - descriptor comes round again. | ||
1008 | */ | ||
1009 | |||
1010 | memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); | ||
1011 | ar->rx_failover_missing = clen - tlen; | ||
1012 | return ; | ||
1013 | } | ||
1014 | resplen = clen; | ||
1015 | respbuf = tbuf + 4; | ||
1016 | tbuf += wlen + 4; | ||
1017 | tlen -= wlen + 4; | ||
1018 | |||
1019 | i = 0; | ||
1020 | |||
1021 | /* weird thing, but this is the same in the original driver */ | ||
1022 | while (resplen > 2 && i < 12 && | ||
1023 | respbuf[0] == 0xff && respbuf[1] == 0xff) { | ||
1024 | i += 2; | ||
1025 | resplen -= 2; | ||
1026 | respbuf += 2; | ||
1027 | } | ||
1028 | |||
1029 | if (resplen < 4) | ||
1030 | continue; | ||
1031 | |||
1032 | /* found the 6 * 0xffff marker? */ | ||
1033 | if (i == 12) | ||
1034 | ar9170_handle_command_response(ar, respbuf, resplen); | ||
1035 | else | ||
1036 | ar9170_handle_mpdu(ar, respbuf, clen); | ||
1037 | } | ||
1038 | |||
1039 | if (tlen) { | ||
1040 | if (net_ratelimit()) | ||
1041 | wiphy_err(ar->hw->wiphy, | ||
1042 | "%d bytes of unprocessed data left in rx stream!\n", | ||
1043 | tlen); | ||
1044 | |||
1045 | goto err_telluser; | ||
1046 | } | ||
1047 | |||
1048 | return ; | ||
1049 | |||
1050 | err_telluser: | ||
1051 | wiphy_err(ar->hw->wiphy, | ||
1052 | "damaged RX stream data [want:%d, data:%d, rx:%d, pending:%d ]\n", | ||
1053 | clen, wlen, tlen, ar->rx_failover_missing); | ||
1054 | |||
1055 | if (ar->rx_failover_missing) | ||
1056 | print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, | ||
1057 | ar->rx_failover->data, | ||
1058 | ar->rx_failover->len); | ||
1059 | |||
1060 | print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, | ||
1061 | skb->data, skb->len); | ||
1062 | |||
1063 | wiphy_err(ar->hw->wiphy, | ||
1064 | "If you see this message frequently, please check your hardware and cables.\n"); | ||
1065 | |||
1066 | err_silent: | ||
1067 | if (ar->rx_failover_missing) { | ||
1068 | skb_reset_tail_pointer(ar->rx_failover); | ||
1069 | skb_trim(ar->rx_failover, 0); | ||
1070 | ar->rx_failover_missing = 0; | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | #define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ | ||
1075 | do { \ | ||
1076 | queue.aifs = ai_fs; \ | ||
1077 | queue.cw_min = cwmin; \ | ||
1078 | queue.cw_max = cwmax; \ | ||
1079 | queue.txop = _txop; \ | ||
1080 | } while (0) | ||
1081 | |||
1082 | static int ar9170_op_start(struct ieee80211_hw *hw) | ||
1083 | { | ||
1084 | struct ar9170 *ar = hw->priv; | ||
1085 | int err, i; | ||
1086 | |||
1087 | mutex_lock(&ar->mutex); | ||
1088 | |||
1089 | /* reinitialize queues statistics */ | ||
1090 | memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); | ||
1091 | for (i = 0; i < __AR9170_NUM_TXQ; i++) | ||
1092 | ar->tx_stats[i].limit = AR9170_TXQ_DEPTH; | ||
1093 | |||
1094 | /* reset QoS defaults */ | ||
1095 | AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/ | ||
1096 | AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */ | ||
1097 | AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */ | ||
1098 | AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ | ||
1099 | AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ | ||
1100 | |||
1101 | /* set sane AMPDU defaults */ | ||
1102 | ar->global_ampdu_density = 6; | ||
1103 | ar->global_ampdu_factor = 3; | ||
1104 | |||
1105 | ar->bad_hw_nagger = jiffies; | ||
1106 | |||
1107 | err = ar->open(ar); | ||
1108 | if (err) | ||
1109 | goto out; | ||
1110 | |||
1111 | err = ar9170_init_mac(ar); | ||
1112 | if (err) | ||
1113 | goto out; | ||
1114 | |||
1115 | err = ar9170_set_qos(ar); | ||
1116 | if (err) | ||
1117 | goto out; | ||
1118 | |||
1119 | err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ); | ||
1120 | if (err) | ||
1121 | goto out; | ||
1122 | |||
1123 | err = ar9170_init_rf(ar); | ||
1124 | if (err) | ||
1125 | goto out; | ||
1126 | |||
1127 | /* start DMA */ | ||
1128 | err = ar9170_write_reg(ar, 0x1c3d30, 0x100); | ||
1129 | if (err) | ||
1130 | goto out; | ||
1131 | |||
1132 | ar->state = AR9170_STARTED; | ||
1133 | |||
1134 | out: | ||
1135 | mutex_unlock(&ar->mutex); | ||
1136 | return err; | ||
1137 | } | ||
1138 | |||
1139 | static void ar9170_op_stop(struct ieee80211_hw *hw) | ||
1140 | { | ||
1141 | struct ar9170 *ar = hw->priv; | ||
1142 | unsigned int i; | ||
1143 | |||
1144 | if (IS_STARTED(ar)) | ||
1145 | ar->state = AR9170_IDLE; | ||
1146 | |||
1147 | cancel_delayed_work_sync(&ar->tx_janitor); | ||
1148 | #ifdef CONFIG_AR9170_LEDS | ||
1149 | cancel_delayed_work_sync(&ar->led_work); | ||
1150 | #endif | ||
1151 | cancel_work_sync(&ar->beacon_work); | ||
1152 | |||
1153 | mutex_lock(&ar->mutex); | ||
1154 | |||
1155 | if (IS_ACCEPTING_CMD(ar)) { | ||
1156 | ar9170_set_leds_state(ar, 0); | ||
1157 | |||
1158 | /* stop DMA */ | ||
1159 | ar9170_write_reg(ar, 0x1c3d30, 0); | ||
1160 | ar->stop(ar); | ||
1161 | } | ||
1162 | |||
1163 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | ||
1164 | skb_queue_purge(&ar->tx_pending[i]); | ||
1165 | skb_queue_purge(&ar->tx_status[i]); | ||
1166 | } | ||
1167 | |||
1168 | mutex_unlock(&ar->mutex); | ||
1169 | } | ||
1170 | |||
1171 | static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | ||
1172 | { | ||
1173 | struct ieee80211_hdr *hdr; | ||
1174 | struct ar9170_tx_control *txc; | ||
1175 | struct ieee80211_tx_info *info; | ||
1176 | struct ieee80211_tx_rate *txrate; | ||
1177 | struct ar9170_tx_info *arinfo; | ||
1178 | unsigned int queue = skb_get_queue_mapping(skb); | ||
1179 | u16 keytype = 0; | ||
1180 | u16 len, icv = 0; | ||
1181 | |||
1182 | BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); | ||
1183 | |||
1184 | hdr = (void *)skb->data; | ||
1185 | info = IEEE80211_SKB_CB(skb); | ||
1186 | len = skb->len; | ||
1187 | |||
1188 | txc = (void *)skb_push(skb, sizeof(*txc)); | ||
1189 | |||
1190 | if (info->control.hw_key) { | ||
1191 | icv = info->control.hw_key->icv_len; | ||
1192 | |||
1193 | switch (info->control.hw_key->cipher) { | ||
1194 | case WLAN_CIPHER_SUITE_WEP40: | ||
1195 | case WLAN_CIPHER_SUITE_WEP104: | ||
1196 | case WLAN_CIPHER_SUITE_TKIP: | ||
1197 | keytype = AR9170_TX_MAC_ENCR_RC4; | ||
1198 | break; | ||
1199 | case WLAN_CIPHER_SUITE_CCMP: | ||
1200 | keytype = AR9170_TX_MAC_ENCR_AES; | ||
1201 | break; | ||
1202 | default: | ||
1203 | WARN_ON(1); | ||
1204 | goto err_out; | ||
1205 | } | ||
1206 | } | ||
1207 | |||
1208 | /* Length */ | ||
1209 | txc->length = cpu_to_le16(len + icv + 4); | ||
1210 | |||
1211 | txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | | ||
1212 | AR9170_TX_MAC_BACKOFF); | ||
1213 | txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] << | ||
1214 | AR9170_TX_MAC_QOS_SHIFT); | ||
1215 | txc->mac_control |= cpu_to_le16(keytype); | ||
1216 | txc->phy_control = cpu_to_le32(0); | ||
1217 | |||
1218 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
1219 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); | ||
1220 | |||
1221 | txrate = &info->control.rates[0]; | ||
1222 | if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) | ||
1223 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); | ||
1224 | else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
1225 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); | ||
1226 | |||
1227 | arinfo = (void *)info->rate_driver_data; | ||
1228 | arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT); | ||
1229 | |||
1230 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
1231 | (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { | ||
1232 | /* | ||
1233 | * WARNING: | ||
1234 | * Putting the QoS queue bits into an unexplored territory is | ||
1235 | * certainly not elegant. | ||
1236 | * | ||
1237 | * In my defense: This idea provides a reasonable way to | ||
1238 | * smuggle valuable information to the tx_status callback. | ||
1239 | * Also, the idea behind this bit-abuse came straight from | ||
1240 | * the original driver code. | ||
1241 | */ | ||
1242 | |||
1243 | txc->phy_control |= | ||
1244 | cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); | ||
1245 | |||
1246 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); | ||
1247 | } | ||
1248 | |||
1249 | return 0; | ||
1250 | |||
1251 | err_out: | ||
1252 | skb_pull(skb, sizeof(*txc)); | ||
1253 | return -EINVAL; | ||
1254 | } | ||
1255 | |||
1256 | static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) | ||
1257 | { | ||
1258 | struct ar9170_tx_control *txc; | ||
1259 | struct ieee80211_tx_info *info; | ||
1260 | struct ieee80211_rate *rate = NULL; | ||
1261 | struct ieee80211_tx_rate *txrate; | ||
1262 | u32 power, chains; | ||
1263 | |||
1264 | txc = (void *) skb->data; | ||
1265 | info = IEEE80211_SKB_CB(skb); | ||
1266 | txrate = &info->control.rates[0]; | ||
1267 | |||
1268 | if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) | ||
1269 | txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); | ||
1270 | |||
1271 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
1272 | txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); | ||
1273 | |||
1274 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
1275 | txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ); | ||
1276 | /* this works because 40 MHz is 2 and dup is 3 */ | ||
1277 | if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) | ||
1278 | txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP); | ||
1279 | |||
1280 | if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
1281 | txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); | ||
1282 | |||
1283 | if (txrate->flags & IEEE80211_TX_RC_MCS) { | ||
1284 | u32 r = txrate->idx; | ||
1285 | u8 *txpower; | ||
1286 | |||
1287 | /* heavy clip control */ | ||
1288 | txc->phy_control |= cpu_to_le32((r & 0x7) << 7); | ||
1289 | |||
1290 | r <<= AR9170_TX_PHY_MCS_SHIFT; | ||
1291 | BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK); | ||
1292 | |||
1293 | txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK); | ||
1294 | txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); | ||
1295 | |||
1296 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { | ||
1297 | if (info->band == IEEE80211_BAND_5GHZ) | ||
1298 | txpower = ar->power_5G_ht40; | ||
1299 | else | ||
1300 | txpower = ar->power_2G_ht40; | ||
1301 | } else { | ||
1302 | if (info->band == IEEE80211_BAND_5GHZ) | ||
1303 | txpower = ar->power_5G_ht20; | ||
1304 | else | ||
1305 | txpower = ar->power_2G_ht20; | ||
1306 | } | ||
1307 | |||
1308 | power = txpower[(txrate->idx) & 7]; | ||
1309 | } else { | ||
1310 | u8 *txpower; | ||
1311 | u32 mod; | ||
1312 | u32 phyrate; | ||
1313 | u8 idx = txrate->idx; | ||
1314 | |||
1315 | if (info->band != IEEE80211_BAND_2GHZ) { | ||
1316 | idx += 4; | ||
1317 | txpower = ar->power_5G_leg; | ||
1318 | mod = AR9170_TX_PHY_MOD_OFDM; | ||
1319 | } else { | ||
1320 | if (idx < 4) { | ||
1321 | txpower = ar->power_2G_cck; | ||
1322 | mod = AR9170_TX_PHY_MOD_CCK; | ||
1323 | } else { | ||
1324 | mod = AR9170_TX_PHY_MOD_OFDM; | ||
1325 | txpower = ar->power_2G_ofdm; | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1329 | rate = &__ar9170_ratetable[idx]; | ||
1330 | |||
1331 | phyrate = rate->hw_value & 0xF; | ||
1332 | power = txpower[(rate->hw_value & 0x30) >> 4]; | ||
1333 | phyrate <<= AR9170_TX_PHY_MCS_SHIFT; | ||
1334 | |||
1335 | txc->phy_control |= cpu_to_le32(mod); | ||
1336 | txc->phy_control |= cpu_to_le32(phyrate); | ||
1337 | } | ||
1338 | |||
1339 | power <<= AR9170_TX_PHY_TX_PWR_SHIFT; | ||
1340 | power &= AR9170_TX_PHY_TX_PWR_MASK; | ||
1341 | txc->phy_control |= cpu_to_le32(power); | ||
1342 | |||
1343 | /* set TX chains */ | ||
1344 | if (ar->eeprom.tx_mask == 1) { | ||
1345 | chains = AR9170_TX_PHY_TXCHAIN_1; | ||
1346 | } else { | ||
1347 | chains = AR9170_TX_PHY_TXCHAIN_2; | ||
1348 | |||
1349 | /* >= 36M legacy OFDM - use only one chain */ | ||
1350 | if (rate && rate->bitrate >= 360) | ||
1351 | chains = AR9170_TX_PHY_TXCHAIN_1; | ||
1352 | } | ||
1353 | txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); | ||
1354 | } | ||
1355 | |||
1356 | static void ar9170_tx(struct ar9170 *ar) | ||
1357 | { | ||
1358 | struct sk_buff *skb; | ||
1359 | unsigned long flags; | ||
1360 | struct ieee80211_tx_info *info; | ||
1361 | struct ar9170_tx_info *arinfo; | ||
1362 | unsigned int i, frames, frames_failed, remaining_space; | ||
1363 | int err; | ||
1364 | bool schedule_garbagecollector = false; | ||
1365 | |||
1366 | BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); | ||
1367 | |||
1368 | if (unlikely(!IS_STARTED(ar))) | ||
1369 | return ; | ||
1370 | |||
1371 | remaining_space = AR9170_TX_MAX_PENDING; | ||
1372 | |||
1373 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | ||
1374 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | ||
1375 | frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, | ||
1376 | skb_queue_len(&ar->tx_pending[i])); | ||
1377 | |||
1378 | if (remaining_space < frames) { | ||
1379 | #ifdef AR9170_QUEUE_DEBUG | ||
1380 | wiphy_debug(ar->hw->wiphy, | ||
1381 | "tx quota reached queue:%d, " | ||
1382 | "remaining slots:%d, needed:%d\n", | ||
1383 | i, remaining_space, frames); | ||
1384 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1385 | frames = remaining_space; | ||
1386 | } | ||
1387 | |||
1388 | ar->tx_stats[i].len += frames; | ||
1389 | ar->tx_stats[i].count += frames; | ||
1390 | if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { | ||
1391 | #ifdef AR9170_QUEUE_DEBUG | ||
1392 | wiphy_debug(ar->hw->wiphy, "queue %d full\n", i); | ||
1393 | wiphy_debug(ar->hw->wiphy, "stuck frames: ===>\n"); | ||
1394 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); | ||
1395 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); | ||
1396 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1397 | |||
1398 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
1399 | wiphy_debug(ar->hw->wiphy, "stop queue %d\n", i); | ||
1400 | __ar9170_dump_txstats(ar); | ||
1401 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
1402 | ieee80211_stop_queue(ar->hw, i); | ||
1403 | } | ||
1404 | |||
1405 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | ||
1406 | |||
1407 | if (!frames) | ||
1408 | continue; | ||
1409 | |||
1410 | frames_failed = 0; | ||
1411 | while (frames) { | ||
1412 | skb = skb_dequeue(&ar->tx_pending[i]); | ||
1413 | if (unlikely(!skb)) { | ||
1414 | frames_failed += frames; | ||
1415 | frames = 0; | ||
1416 | break; | ||
1417 | } | ||
1418 | |||
1419 | info = IEEE80211_SKB_CB(skb); | ||
1420 | arinfo = (void *) info->rate_driver_data; | ||
1421 | |||
1422 | /* TODO: cancel stuck frames */ | ||
1423 | arinfo->timeout = jiffies + | ||
1424 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | ||
1425 | |||
1426 | #ifdef AR9170_QUEUE_DEBUG | ||
1427 | wiphy_debug(ar->hw->wiphy, "send frame q:%d =>\n", i); | ||
1428 | ar9170_print_txheader(ar, skb); | ||
1429 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1430 | |||
1431 | err = ar->tx(ar, skb); | ||
1432 | if (unlikely(err)) { | ||
1433 | frames_failed++; | ||
1434 | dev_kfree_skb_any(skb); | ||
1435 | } else { | ||
1436 | remaining_space--; | ||
1437 | schedule_garbagecollector = true; | ||
1438 | } | ||
1439 | |||
1440 | frames--; | ||
1441 | } | ||
1442 | |||
1443 | #ifdef AR9170_QUEUE_DEBUG | ||
1444 | wiphy_debug(ar->hw->wiphy, | ||
1445 | "ar9170_tx report for queue %d\n", i); | ||
1446 | |||
1447 | wiphy_debug(ar->hw->wiphy, | ||
1448 | "unprocessed pending frames left:\n"); | ||
1449 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); | ||
1450 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1451 | |||
1452 | if (unlikely(frames_failed)) { | ||
1453 | #ifdef AR9170_QUEUE_DEBUG | ||
1454 | wiphy_debug(ar->hw->wiphy, | ||
1455 | "frames failed %d =>\n", frames_failed); | ||
1456 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1457 | |||
1458 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | ||
1459 | ar->tx_stats[i].len -= frames_failed; | ||
1460 | ar->tx_stats[i].count -= frames_failed; | ||
1461 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
1462 | wiphy_debug(ar->hw->wiphy, "wake queue %d\n", i); | ||
1463 | __ar9170_dump_txstats(ar); | ||
1464 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
1465 | ieee80211_wake_queue(ar->hw, i); | ||
1466 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | ||
1467 | } | ||
1468 | } | ||
1469 | |||
1470 | if (!schedule_garbagecollector) | ||
1471 | return; | ||
1472 | |||
1473 | ieee80211_queue_delayed_work(ar->hw, | ||
1474 | &ar->tx_janitor, | ||
1475 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | ||
1476 | } | ||
1477 | |||
1478 | void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1479 | { | ||
1480 | struct ar9170 *ar = hw->priv; | ||
1481 | struct ieee80211_tx_info *info; | ||
1482 | unsigned int queue; | ||
1483 | |||
1484 | if (unlikely(!IS_STARTED(ar))) | ||
1485 | goto err_free; | ||
1486 | |||
1487 | if (unlikely(ar9170_tx_prepare(ar, skb))) | ||
1488 | goto err_free; | ||
1489 | |||
1490 | queue = skb_get_queue_mapping(skb); | ||
1491 | info = IEEE80211_SKB_CB(skb); | ||
1492 | ar9170_tx_prepare_phy(ar, skb); | ||
1493 | skb_queue_tail(&ar->tx_pending[queue], skb); | ||
1494 | |||
1495 | ar9170_tx(ar); | ||
1496 | return; | ||
1497 | |||
1498 | err_free: | ||
1499 | dev_kfree_skb_any(skb); | ||
1500 | } | ||
1501 | |||
1502 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, | ||
1503 | struct ieee80211_vif *vif) | ||
1504 | { | ||
1505 | struct ar9170 *ar = hw->priv; | ||
1506 | struct ath_common *common = &ar->common; | ||
1507 | int err = 0; | ||
1508 | |||
1509 | mutex_lock(&ar->mutex); | ||
1510 | |||
1511 | if (ar->vif) { | ||
1512 | err = -EBUSY; | ||
1513 | goto unlock; | ||
1514 | } | ||
1515 | |||
1516 | ar->vif = vif; | ||
1517 | memcpy(common->macaddr, vif->addr, ETH_ALEN); | ||
1518 | |||
1519 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { | ||
1520 | ar->rx_software_decryption = true; | ||
1521 | ar->disable_offload = true; | ||
1522 | } | ||
1523 | |||
1524 | ar->cur_filter = 0; | ||
1525 | err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS); | ||
1526 | if (err) | ||
1527 | goto unlock; | ||
1528 | |||
1529 | err = ar9170_set_operating_mode(ar); | ||
1530 | |||
1531 | unlock: | ||
1532 | mutex_unlock(&ar->mutex); | ||
1533 | return err; | ||
1534 | } | ||
1535 | |||
1536 | static void ar9170_op_remove_interface(struct ieee80211_hw *hw, | ||
1537 | struct ieee80211_vif *vif) | ||
1538 | { | ||
1539 | struct ar9170 *ar = hw->priv; | ||
1540 | |||
1541 | mutex_lock(&ar->mutex); | ||
1542 | ar->vif = NULL; | ||
1543 | ar9170_update_frame_filter(ar, 0); | ||
1544 | ar9170_set_beacon_timers(ar); | ||
1545 | dev_kfree_skb(ar->beacon); | ||
1546 | ar->beacon = NULL; | ||
1547 | ar->sniffer_enabled = false; | ||
1548 | ar->rx_software_decryption = false; | ||
1549 | ar9170_set_operating_mode(ar); | ||
1550 | mutex_unlock(&ar->mutex); | ||
1551 | } | ||
1552 | |||
1553 | static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) | ||
1554 | { | ||
1555 | struct ar9170 *ar = hw->priv; | ||
1556 | int err = 0; | ||
1557 | |||
1558 | mutex_lock(&ar->mutex); | ||
1559 | |||
1560 | if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { | ||
1561 | /* TODO */ | ||
1562 | err = 0; | ||
1563 | } | ||
1564 | |||
1565 | if (changed & IEEE80211_CONF_CHANGE_PS) { | ||
1566 | /* TODO */ | ||
1567 | err = 0; | ||
1568 | } | ||
1569 | |||
1570 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | ||
1571 | /* TODO */ | ||
1572 | err = 0; | ||
1573 | } | ||
1574 | |||
1575 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { | ||
1576 | /* | ||
1577 | * is it long_frame_max_tx_count or short_frame_max_tx_count? | ||
1578 | */ | ||
1579 | |||
1580 | err = ar9170_set_hwretry_limit(ar, | ||
1581 | ar->hw->conf.long_frame_max_tx_count); | ||
1582 | if (err) | ||
1583 | goto out; | ||
1584 | } | ||
1585 | |||
1586 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
1587 | |||
1588 | /* adjust slot time for 5 GHz */ | ||
1589 | err = ar9170_set_slot_time(ar); | ||
1590 | if (err) | ||
1591 | goto out; | ||
1592 | |||
1593 | err = ar9170_set_dyn_sifs_ack(ar); | ||
1594 | if (err) | ||
1595 | goto out; | ||
1596 | |||
1597 | err = ar9170_set_channel(ar, hw->conf.channel, | ||
1598 | AR9170_RFI_NONE, | ||
1599 | nl80211_to_ar9170(hw->conf.channel_type)); | ||
1600 | if (err) | ||
1601 | goto out; | ||
1602 | } | ||
1603 | |||
1604 | out: | ||
1605 | mutex_unlock(&ar->mutex); | ||
1606 | return err; | ||
1607 | } | ||
1608 | |||
1609 | static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, | ||
1610 | struct netdev_hw_addr_list *mc_list) | ||
1611 | { | ||
1612 | u64 mchash; | ||
1613 | struct netdev_hw_addr *ha; | ||
1614 | |||
1615 | /* always get broadcast frames */ | ||
1616 | mchash = 1ULL << (0xff >> 2); | ||
1617 | |||
1618 | netdev_hw_addr_list_for_each(ha, mc_list) | ||
1619 | mchash |= 1ULL << (ha->addr[5] >> 2); | ||
1620 | |||
1621 | return mchash; | ||
1622 | } | ||
1623 | |||
1624 | static void ar9170_op_configure_filter(struct ieee80211_hw *hw, | ||
1625 | unsigned int changed_flags, | ||
1626 | unsigned int *new_flags, | ||
1627 | u64 multicast) | ||
1628 | { | ||
1629 | struct ar9170 *ar = hw->priv; | ||
1630 | |||
1631 | if (unlikely(!IS_ACCEPTING_CMD(ar))) | ||
1632 | return ; | ||
1633 | |||
1634 | mutex_lock(&ar->mutex); | ||
1635 | |||
1636 | /* mask supported flags */ | ||
1637 | *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | | ||
1638 | FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; | ||
1639 | ar->filter_state = *new_flags; | ||
1640 | /* | ||
1641 | * We can support more by setting the sniffer bit and | ||
1642 | * then checking the error flags, later. | ||
1643 | */ | ||
1644 | |||
1645 | if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) | ||
1646 | multicast = ~0ULL; | ||
1647 | |||
1648 | if (multicast != ar->cur_mc_hash) | ||
1649 | ar9170_update_multicast(ar, multicast); | ||
1650 | |||
1651 | if (changed_flags & FIF_CONTROL) { | ||
1652 | u32 filter = AR9170_MAC_REG_FTF_PSPOLL | | ||
1653 | AR9170_MAC_REG_FTF_RTS | | ||
1654 | AR9170_MAC_REG_FTF_CTS | | ||
1655 | AR9170_MAC_REG_FTF_ACK | | ||
1656 | AR9170_MAC_REG_FTF_CFE | | ||
1657 | AR9170_MAC_REG_FTF_CFE_ACK; | ||
1658 | |||
1659 | if (*new_flags & FIF_CONTROL) | ||
1660 | filter |= ar->cur_filter; | ||
1661 | else | ||
1662 | filter &= (~ar->cur_filter); | ||
1663 | |||
1664 | ar9170_update_frame_filter(ar, filter); | ||
1665 | } | ||
1666 | |||
1667 | if (changed_flags & FIF_PROMISC_IN_BSS) { | ||
1668 | ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; | ||
1669 | ar9170_set_operating_mode(ar); | ||
1670 | } | ||
1671 | |||
1672 | mutex_unlock(&ar->mutex); | ||
1673 | } | ||
1674 | |||
1675 | |||
1676 | static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, | ||
1677 | struct ieee80211_vif *vif, | ||
1678 | struct ieee80211_bss_conf *bss_conf, | ||
1679 | u32 changed) | ||
1680 | { | ||
1681 | struct ar9170 *ar = hw->priv; | ||
1682 | struct ath_common *common = &ar->common; | ||
1683 | int err = 0; | ||
1684 | |||
1685 | mutex_lock(&ar->mutex); | ||
1686 | |||
1687 | if (changed & BSS_CHANGED_BSSID) { | ||
1688 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1689 | err = ar9170_set_operating_mode(ar); | ||
1690 | if (err) | ||
1691 | goto out; | ||
1692 | } | ||
1693 | |||
1694 | if (changed & BSS_CHANGED_BEACON_ENABLED) | ||
1695 | ar->enable_beacon = bss_conf->enable_beacon; | ||
1696 | |||
1697 | if (changed & BSS_CHANGED_BEACON) { | ||
1698 | err = ar9170_update_beacon(ar); | ||
1699 | if (err) | ||
1700 | goto out; | ||
1701 | } | ||
1702 | |||
1703 | if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON | | ||
1704 | BSS_CHANGED_BEACON_INT)) { | ||
1705 | err = ar9170_set_beacon_timers(ar); | ||
1706 | if (err) | ||
1707 | goto out; | ||
1708 | } | ||
1709 | |||
1710 | if (changed & BSS_CHANGED_ASSOC) { | ||
1711 | #ifndef CONFIG_AR9170_LEDS | ||
1712 | /* enable assoc LED. */ | ||
1713 | err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0); | ||
1714 | #endif /* CONFIG_AR9170_LEDS */ | ||
1715 | } | ||
1716 | |||
1717 | if (changed & BSS_CHANGED_HT) { | ||
1718 | /* TODO */ | ||
1719 | err = 0; | ||
1720 | } | ||
1721 | |||
1722 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
1723 | err = ar9170_set_slot_time(ar); | ||
1724 | if (err) | ||
1725 | goto out; | ||
1726 | } | ||
1727 | |||
1728 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
1729 | err = ar9170_set_basic_rates(ar); | ||
1730 | if (err) | ||
1731 | goto out; | ||
1732 | } | ||
1733 | |||
1734 | out: | ||
1735 | mutex_unlock(&ar->mutex); | ||
1736 | } | ||
1737 | |||
1738 | static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) | ||
1739 | { | ||
1740 | struct ar9170 *ar = hw->priv; | ||
1741 | int err; | ||
1742 | u64 tsf; | ||
1743 | #define NR 3 | ||
1744 | static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H, | ||
1745 | AR9170_MAC_REG_TSF_L, | ||
1746 | AR9170_MAC_REG_TSF_H }; | ||
1747 | u32 val[NR]; | ||
1748 | int loops = 0; | ||
1749 | |||
1750 | mutex_lock(&ar->mutex); | ||
1751 | |||
1752 | while (loops++ < 10) { | ||
1753 | err = ar9170_read_mreg(ar, NR, addr, val); | ||
1754 | if (err || val[0] == val[2]) | ||
1755 | break; | ||
1756 | } | ||
1757 | |||
1758 | mutex_unlock(&ar->mutex); | ||
1759 | |||
1760 | if (WARN_ON(err)) | ||
1761 | return 0; | ||
1762 | tsf = val[0]; | ||
1763 | tsf = (tsf << 32) | val[1]; | ||
1764 | return tsf; | ||
1765 | #undef NR | ||
1766 | } | ||
1767 | |||
1768 | static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
1769 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | ||
1770 | struct ieee80211_key_conf *key) | ||
1771 | { | ||
1772 | struct ar9170 *ar = hw->priv; | ||
1773 | int err = 0, i; | ||
1774 | u8 ktype; | ||
1775 | |||
1776 | if ((!ar->vif) || (ar->disable_offload)) | ||
1777 | return -EOPNOTSUPP; | ||
1778 | |||
1779 | switch (key->cipher) { | ||
1780 | case WLAN_CIPHER_SUITE_WEP40: | ||
1781 | ktype = AR9170_ENC_ALG_WEP64; | ||
1782 | break; | ||
1783 | case WLAN_CIPHER_SUITE_WEP104: | ||
1784 | ktype = AR9170_ENC_ALG_WEP128; | ||
1785 | break; | ||
1786 | case WLAN_CIPHER_SUITE_TKIP: | ||
1787 | ktype = AR9170_ENC_ALG_TKIP; | ||
1788 | break; | ||
1789 | case WLAN_CIPHER_SUITE_CCMP: | ||
1790 | ktype = AR9170_ENC_ALG_AESCCMP; | ||
1791 | break; | ||
1792 | default: | ||
1793 | return -EOPNOTSUPP; | ||
1794 | } | ||
1795 | |||
1796 | mutex_lock(&ar->mutex); | ||
1797 | if (cmd == SET_KEY) { | ||
1798 | if (unlikely(!IS_STARTED(ar))) { | ||
1799 | err = -EOPNOTSUPP; | ||
1800 | goto out; | ||
1801 | } | ||
1802 | |||
1803 | /* group keys need all-zeroes address */ | ||
1804 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
1805 | sta = NULL; | ||
1806 | |||
1807 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { | ||
1808 | for (i = 0; i < 64; i++) | ||
1809 | if (!(ar->usedkeys & BIT(i))) | ||
1810 | break; | ||
1811 | if (i == 64) { | ||
1812 | ar->rx_software_decryption = true; | ||
1813 | ar9170_set_operating_mode(ar); | ||
1814 | err = -ENOSPC; | ||
1815 | goto out; | ||
1816 | } | ||
1817 | } else { | ||
1818 | i = 64 + key->keyidx; | ||
1819 | } | ||
1820 | |||
1821 | key->hw_key_idx = i; | ||
1822 | |||
1823 | err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0, | ||
1824 | key->key, min_t(u8, 16, key->keylen)); | ||
1825 | if (err) | ||
1826 | goto out; | ||
1827 | |||
1828 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
1829 | err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, | ||
1830 | ktype, 1, key->key + 16, 16); | ||
1831 | if (err) | ||
1832 | goto out; | ||
1833 | |||
1834 | /* | ||
1835 | * hardware is not capable generating the MMIC | ||
1836 | * for fragmented frames! | ||
1837 | */ | ||
1838 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
1839 | } | ||
1840 | |||
1841 | if (i < 64) | ||
1842 | ar->usedkeys |= BIT(i); | ||
1843 | |||
1844 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
1845 | } else { | ||
1846 | if (unlikely(!IS_STARTED(ar))) { | ||
1847 | /* The device is gone... together with the key ;-) */ | ||
1848 | err = 0; | ||
1849 | goto out; | ||
1850 | } | ||
1851 | |||
1852 | err = ar9170_disable_key(ar, key->hw_key_idx); | ||
1853 | if (err) | ||
1854 | goto out; | ||
1855 | |||
1856 | if (key->hw_key_idx < 64) { | ||
1857 | ar->usedkeys &= ~BIT(key->hw_key_idx); | ||
1858 | } else { | ||
1859 | err = ar9170_upload_key(ar, key->hw_key_idx, NULL, | ||
1860 | AR9170_ENC_ALG_NONE, 0, | ||
1861 | NULL, 0); | ||
1862 | if (err) | ||
1863 | goto out; | ||
1864 | |||
1865 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
1866 | err = ar9170_upload_key(ar, key->hw_key_idx, | ||
1867 | NULL, | ||
1868 | AR9170_ENC_ALG_NONE, 1, | ||
1869 | NULL, 0); | ||
1870 | if (err) | ||
1871 | goto out; | ||
1872 | } | ||
1873 | |||
1874 | } | ||
1875 | } | ||
1876 | |||
1877 | ar9170_regwrite_begin(ar); | ||
1878 | ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys); | ||
1879 | ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32); | ||
1880 | ar9170_regwrite_finish(); | ||
1881 | err = ar9170_regwrite_result(); | ||
1882 | |||
1883 | out: | ||
1884 | mutex_unlock(&ar->mutex); | ||
1885 | |||
1886 | return err; | ||
1887 | } | ||
1888 | |||
1889 | static int ar9170_get_stats(struct ieee80211_hw *hw, | ||
1890 | struct ieee80211_low_level_stats *stats) | ||
1891 | { | ||
1892 | struct ar9170 *ar = hw->priv; | ||
1893 | u32 val; | ||
1894 | int err; | ||
1895 | |||
1896 | mutex_lock(&ar->mutex); | ||
1897 | err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val); | ||
1898 | ar->stats.dot11ACKFailureCount += val; | ||
1899 | |||
1900 | memcpy(stats, &ar->stats, sizeof(*stats)); | ||
1901 | mutex_unlock(&ar->mutex); | ||
1902 | |||
1903 | return 0; | ||
1904 | } | ||
1905 | |||
1906 | static int ar9170_get_survey(struct ieee80211_hw *hw, int idx, | ||
1907 | struct survey_info *survey) | ||
1908 | { | ||
1909 | struct ar9170 *ar = hw->priv; | ||
1910 | struct ieee80211_conf *conf = &hw->conf; | ||
1911 | |||
1912 | if (idx != 0) | ||
1913 | return -ENOENT; | ||
1914 | |||
1915 | /* TODO: update noise value, e.g. call ar9170_set_channel */ | ||
1916 | |||
1917 | survey->channel = conf->channel; | ||
1918 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
1919 | survey->noise = ar->noise[0]; | ||
1920 | |||
1921 | return 0; | ||
1922 | } | ||
1923 | |||
1924 | static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1925 | const struct ieee80211_tx_queue_params *param) | ||
1926 | { | ||
1927 | struct ar9170 *ar = hw->priv; | ||
1928 | int ret; | ||
1929 | |||
1930 | mutex_lock(&ar->mutex); | ||
1931 | if (queue < __AR9170_NUM_TXQ) { | ||
1932 | memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], | ||
1933 | param, sizeof(*param)); | ||
1934 | |||
1935 | ret = ar9170_set_qos(ar); | ||
1936 | } else { | ||
1937 | ret = -EINVAL; | ||
1938 | } | ||
1939 | |||
1940 | mutex_unlock(&ar->mutex); | ||
1941 | return ret; | ||
1942 | } | ||
1943 | |||
1944 | static int ar9170_ampdu_action(struct ieee80211_hw *hw, | ||
1945 | struct ieee80211_vif *vif, | ||
1946 | enum ieee80211_ampdu_mlme_action action, | ||
1947 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
1948 | u8 buf_size) | ||
1949 | { | ||
1950 | switch (action) { | ||
1951 | case IEEE80211_AMPDU_RX_START: | ||
1952 | case IEEE80211_AMPDU_RX_STOP: | ||
1953 | /* Handled by firmware */ | ||
1954 | break; | ||
1955 | |||
1956 | default: | ||
1957 | return -EOPNOTSUPP; | ||
1958 | } | ||
1959 | |||
1960 | return 0; | ||
1961 | } | ||
1962 | |||
1963 | static const struct ieee80211_ops ar9170_ops = { | ||
1964 | .start = ar9170_op_start, | ||
1965 | .stop = ar9170_op_stop, | ||
1966 | .tx = ar9170_op_tx, | ||
1967 | .add_interface = ar9170_op_add_interface, | ||
1968 | .remove_interface = ar9170_op_remove_interface, | ||
1969 | .config = ar9170_op_config, | ||
1970 | .prepare_multicast = ar9170_op_prepare_multicast, | ||
1971 | .configure_filter = ar9170_op_configure_filter, | ||
1972 | .conf_tx = ar9170_conf_tx, | ||
1973 | .bss_info_changed = ar9170_op_bss_info_changed, | ||
1974 | .get_tsf = ar9170_op_get_tsf, | ||
1975 | .set_key = ar9170_set_key, | ||
1976 | .get_stats = ar9170_get_stats, | ||
1977 | .get_survey = ar9170_get_survey, | ||
1978 | .ampdu_action = ar9170_ampdu_action, | ||
1979 | }; | ||
1980 | |||
1981 | void *ar9170_alloc(size_t priv_size) | ||
1982 | { | ||
1983 | struct ieee80211_hw *hw; | ||
1984 | struct ar9170 *ar; | ||
1985 | struct sk_buff *skb; | ||
1986 | int i; | ||
1987 | |||
1988 | /* | ||
1989 | * this buffer is used for rx stream reconstruction. | ||
1990 | * Under heavy load this device (or the transport layer?) | ||
1991 | * tends to split the streams into separate rx descriptors. | ||
1992 | */ | ||
1993 | |||
1994 | skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); | ||
1995 | if (!skb) | ||
1996 | goto err_nomem; | ||
1997 | |||
1998 | hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); | ||
1999 | if (!hw) | ||
2000 | goto err_nomem; | ||
2001 | |||
2002 | ar = hw->priv; | ||
2003 | ar->hw = hw; | ||
2004 | ar->rx_failover = skb; | ||
2005 | |||
2006 | mutex_init(&ar->mutex); | ||
2007 | spin_lock_init(&ar->cmdlock); | ||
2008 | spin_lock_init(&ar->tx_stats_lock); | ||
2009 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | ||
2010 | skb_queue_head_init(&ar->tx_status[i]); | ||
2011 | skb_queue_head_init(&ar->tx_pending[i]); | ||
2012 | } | ||
2013 | ar9170_rx_reset_rx_mpdu(ar); | ||
2014 | INIT_WORK(&ar->beacon_work, ar9170_new_beacon); | ||
2015 | INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); | ||
2016 | |||
2017 | /* all hw supports 2.4 GHz, so set channel to 1 by default */ | ||
2018 | ar->channel = &ar9170_2ghz_chantable[0]; | ||
2019 | |||
2020 | /* first part of wiphy init */ | ||
2021 | ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
2022 | BIT(NL80211_IFTYPE_WDS) | | ||
2023 | BIT(NL80211_IFTYPE_ADHOC); | ||
2024 | ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | | ||
2025 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
2026 | IEEE80211_HW_SIGNAL_DBM; | ||
2027 | |||
2028 | ar->hw->queues = __AR9170_NUM_TXQ; | ||
2029 | ar->hw->extra_tx_headroom = 8; | ||
2030 | |||
2031 | ar->hw->max_rates = 1; | ||
2032 | ar->hw->max_rate_tries = 3; | ||
2033 | |||
2034 | for (i = 0; i < ARRAY_SIZE(ar->noise); i++) | ||
2035 | ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ | ||
2036 | |||
2037 | return ar; | ||
2038 | |||
2039 | err_nomem: | ||
2040 | kfree_skb(skb); | ||
2041 | return ERR_PTR(-ENOMEM); | ||
2042 | } | ||
2043 | |||
2044 | static int ar9170_read_eeprom(struct ar9170 *ar) | ||
2045 | { | ||
2046 | #define RW 8 /* number of words to read at once */ | ||
2047 | #define RB (sizeof(u32) * RW) | ||
2048 | struct ath_regulatory *regulatory = &ar->common.regulatory; | ||
2049 | u8 *eeprom = (void *)&ar->eeprom; | ||
2050 | u8 *addr = ar->eeprom.mac_address; | ||
2051 | __le32 offsets[RW]; | ||
2052 | unsigned int rx_streams, tx_streams, tx_params = 0; | ||
2053 | int i, j, err, bands = 0; | ||
2054 | |||
2055 | BUILD_BUG_ON(sizeof(ar->eeprom) & 3); | ||
2056 | |||
2057 | BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4); | ||
2058 | #ifndef __CHECKER__ | ||
2059 | /* don't want to handle trailing remains */ | ||
2060 | BUILD_BUG_ON(sizeof(ar->eeprom) % RB); | ||
2061 | #endif | ||
2062 | |||
2063 | for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { | ||
2064 | for (j = 0; j < RW; j++) | ||
2065 | offsets[j] = cpu_to_le32(AR9170_EEPROM_START + | ||
2066 | RB * i + 4 * j); | ||
2067 | |||
2068 | err = ar->exec_cmd(ar, AR9170_CMD_RREG, | ||
2069 | RB, (u8 *) &offsets, | ||
2070 | RB, eeprom + RB * i); | ||
2071 | if (err) | ||
2072 | return err; | ||
2073 | } | ||
2074 | |||
2075 | #undef RW | ||
2076 | #undef RB | ||
2077 | |||
2078 | if (ar->eeprom.length == cpu_to_le16(0xFFFF)) | ||
2079 | return -ENODATA; | ||
2080 | |||
2081 | if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { | ||
2082 | ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz; | ||
2083 | bands++; | ||
2084 | } | ||
2085 | if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { | ||
2086 | ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; | ||
2087 | bands++; | ||
2088 | } | ||
2089 | |||
2090 | rx_streams = hweight8(ar->eeprom.rx_mask); | ||
2091 | tx_streams = hweight8(ar->eeprom.tx_mask); | ||
2092 | |||
2093 | if (rx_streams != tx_streams) | ||
2094 | tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; | ||
2095 | |||
2096 | if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS) | ||
2097 | tx_params = (tx_streams - 1) << | ||
2098 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
2099 | |||
2100 | ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; | ||
2101 | ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; | ||
2102 | |||
2103 | /* | ||
2104 | * I measured this, a bandswitch takes roughly | ||
2105 | * 135 ms and a frequency switch about 80. | ||
2106 | * | ||
2107 | * FIXME: measure these values again once EEPROM settings | ||
2108 | * are used, that will influence them! | ||
2109 | */ | ||
2110 | if (bands == 2) | ||
2111 | ar->hw->channel_change_time = 135 * 1000; | ||
2112 | else | ||
2113 | ar->hw->channel_change_time = 80 * 1000; | ||
2114 | |||
2115 | regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); | ||
2116 | regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); | ||
2117 | |||
2118 | /* second part of wiphy init */ | ||
2119 | SET_IEEE80211_PERM_ADDR(ar->hw, addr); | ||
2120 | |||
2121 | return bands ? 0 : -EINVAL; | ||
2122 | } | ||
2123 | |||
2124 | static int ar9170_reg_notifier(struct wiphy *wiphy, | ||
2125 | struct regulatory_request *request) | ||
2126 | { | ||
2127 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
2128 | struct ar9170 *ar = hw->priv; | ||
2129 | |||
2130 | return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); | ||
2131 | } | ||
2132 | |||
2133 | int ar9170_register(struct ar9170 *ar, struct device *pdev) | ||
2134 | { | ||
2135 | struct ath_regulatory *regulatory = &ar->common.regulatory; | ||
2136 | int err; | ||
2137 | |||
2138 | /* try to read EEPROM, init MAC addr */ | ||
2139 | err = ar9170_read_eeprom(ar); | ||
2140 | if (err) | ||
2141 | goto err_out; | ||
2142 | |||
2143 | err = ath_regd_init(regulatory, ar->hw->wiphy, | ||
2144 | ar9170_reg_notifier); | ||
2145 | if (err) | ||
2146 | goto err_out; | ||
2147 | |||
2148 | err = ieee80211_register_hw(ar->hw); | ||
2149 | if (err) | ||
2150 | goto err_out; | ||
2151 | |||
2152 | if (!ath_is_world_regd(regulatory)) | ||
2153 | regulatory_hint(ar->hw->wiphy, regulatory->alpha2); | ||
2154 | |||
2155 | err = ar9170_init_leds(ar); | ||
2156 | if (err) | ||
2157 | goto err_unreg; | ||
2158 | |||
2159 | #ifdef CONFIG_AR9170_LEDS | ||
2160 | err = ar9170_register_leds(ar); | ||
2161 | if (err) | ||
2162 | goto err_unreg; | ||
2163 | #endif /* CONFIG_AR9170_LEDS */ | ||
2164 | |||
2165 | dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", | ||
2166 | wiphy_name(ar->hw->wiphy)); | ||
2167 | |||
2168 | ar->registered = true; | ||
2169 | return 0; | ||
2170 | |||
2171 | err_unreg: | ||
2172 | ieee80211_unregister_hw(ar->hw); | ||
2173 | |||
2174 | err_out: | ||
2175 | return err; | ||
2176 | } | ||
2177 | |||
2178 | void ar9170_unregister(struct ar9170 *ar) | ||
2179 | { | ||
2180 | if (ar->registered) { | ||
2181 | #ifdef CONFIG_AR9170_LEDS | ||
2182 | ar9170_unregister_leds(ar); | ||
2183 | #endif /* CONFIG_AR9170_LEDS */ | ||
2184 | |||
2185 | ieee80211_unregister_hw(ar->hw); | ||
2186 | } | ||
2187 | |||
2188 | kfree_skb(ar->rx_failover); | ||
2189 | mutex_destroy(&ar->mutex); | ||
2190 | } | ||
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c deleted file mode 100644 index aa8d06ba1ee4..000000000000 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ /dev/null | |||
@@ -1,1719 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * PHY and RF code | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include <linux/bitrev.h> | ||
40 | #include "ar9170.h" | ||
41 | #include "cmd.h" | ||
42 | |||
43 | static int ar9170_init_power_cal(struct ar9170 *ar) | ||
44 | { | ||
45 | ar9170_regwrite_begin(ar); | ||
46 | |||
47 | ar9170_regwrite(0x1bc000 + 0x993c, 0x7f); | ||
48 | ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f); | ||
49 | ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f); | ||
50 | ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f); | ||
51 | ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f); | ||
52 | ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f); | ||
53 | ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f); | ||
54 | ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f); | ||
55 | ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f); | ||
56 | ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f); | ||
57 | |||
58 | ar9170_regwrite_finish(); | ||
59 | return ar9170_regwrite_result(); | ||
60 | } | ||
61 | |||
62 | struct ar9170_phy_init { | ||
63 | u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; | ||
64 | }; | ||
65 | |||
66 | static struct ar9170_phy_init ar5416_phy_init[] = { | ||
67 | { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
68 | { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, | ||
69 | { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
70 | { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, | ||
71 | { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, | ||
72 | { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, | ||
73 | { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, | ||
74 | { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
75 | { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, | ||
76 | { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, | ||
77 | { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, | ||
78 | { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, | ||
79 | { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
80 | { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, | ||
81 | { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
82 | { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, | ||
83 | { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, | ||
84 | { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, | ||
85 | { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, | ||
86 | { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, | ||
87 | { 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, }, | ||
88 | { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, | ||
89 | { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, | ||
90 | { 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, }, | ||
91 | { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, | ||
92 | { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, | ||
93 | { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, | ||
94 | { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
95 | { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
96 | { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
97 | { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
98 | { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, | ||
99 | { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, | ||
100 | { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, | ||
101 | { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, | ||
102 | { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, | ||
103 | { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
104 | { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, | ||
105 | { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
106 | { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
107 | { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, | ||
108 | { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, | ||
109 | { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, | ||
110 | { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, | ||
111 | { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, | ||
112 | { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, | ||
113 | { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, | ||
114 | { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, | ||
115 | { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, | ||
116 | { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
117 | { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
118 | { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
119 | { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
120 | { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
121 | { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
122 | { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
123 | { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
124 | { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
125 | { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
126 | { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
127 | { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
128 | { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
129 | { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, | ||
130 | { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, | ||
131 | { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, | ||
132 | { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, | ||
133 | { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, | ||
134 | { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, | ||
135 | { 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, }, | ||
136 | { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, | ||
137 | { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, | ||
138 | { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
139 | { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
140 | { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
141 | { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, | ||
142 | { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, | ||
143 | { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, | ||
144 | { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, | ||
145 | { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
146 | { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, | ||
147 | { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
148 | { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, | ||
149 | { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, | ||
150 | { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, | ||
151 | { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, | ||
152 | { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, | ||
153 | { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, | ||
154 | { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, | ||
155 | { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, | ||
156 | { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, | ||
157 | { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, | ||
158 | { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, | ||
159 | { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, | ||
160 | { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, | ||
161 | { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, | ||
162 | { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, | ||
163 | { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, | ||
164 | { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, | ||
165 | { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, | ||
166 | { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, | ||
167 | { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, | ||
168 | { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, | ||
169 | { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, | ||
170 | { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, | ||
171 | { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, | ||
172 | { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, | ||
173 | { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, | ||
174 | { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, | ||
175 | { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, | ||
176 | { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, | ||
177 | { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, | ||
178 | { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, | ||
179 | { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, | ||
180 | { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, | ||
181 | { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, | ||
182 | { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, | ||
183 | { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, | ||
184 | { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, | ||
185 | { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, | ||
186 | { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, | ||
187 | { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
188 | { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
189 | { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
190 | { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
191 | { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
192 | { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
193 | { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
194 | { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
195 | { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
196 | { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
197 | { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
198 | { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
199 | { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
200 | { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
201 | { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
202 | { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
203 | { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
204 | { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
205 | { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
206 | { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
207 | { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
208 | { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
209 | { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
210 | { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
211 | { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
212 | { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
213 | { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, | ||
214 | { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, | ||
215 | { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, | ||
216 | { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, | ||
217 | { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, | ||
218 | { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, | ||
219 | { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, | ||
220 | { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, | ||
221 | { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, | ||
222 | { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, | ||
223 | { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, | ||
224 | { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, | ||
225 | { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, | ||
226 | { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, | ||
227 | { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, | ||
228 | { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, | ||
229 | { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, | ||
230 | { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, | ||
231 | { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, | ||
232 | { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, | ||
233 | { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, | ||
234 | { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, | ||
235 | { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, | ||
236 | { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, | ||
237 | { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, | ||
238 | { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, | ||
239 | { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, | ||
240 | { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, | ||
241 | { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, | ||
242 | { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, | ||
243 | { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, | ||
244 | { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, | ||
245 | { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, | ||
246 | { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, | ||
247 | { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, | ||
248 | { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, | ||
249 | { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, | ||
250 | { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, | ||
251 | { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, | ||
252 | { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
253 | { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
254 | { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
255 | { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
256 | { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
257 | { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
258 | { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
259 | { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
260 | { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
261 | { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
262 | { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
263 | { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
264 | { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
265 | { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
266 | { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
267 | { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
268 | { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
269 | { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
270 | { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
271 | { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
272 | { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
273 | { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, | ||
274 | { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, | ||
275 | { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
276 | { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
277 | { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
278 | { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
279 | { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
280 | { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
281 | { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
282 | { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
283 | { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
284 | { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
285 | { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
286 | { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
287 | { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
288 | { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
289 | { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
290 | { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
291 | { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
292 | { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
293 | { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, | ||
294 | { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, | ||
295 | { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, | ||
296 | { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, | ||
297 | { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, | ||
298 | { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, | ||
299 | { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, | ||
300 | { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, | ||
301 | { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, | ||
302 | { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, | ||
303 | { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, | ||
304 | { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
305 | { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, | ||
306 | { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
307 | { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
308 | { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, | ||
309 | { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, | ||
310 | { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, | ||
311 | { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, | ||
312 | { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
313 | { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, | ||
314 | { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
315 | { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, | ||
316 | { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, | ||
317 | { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, | ||
318 | { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, | ||
319 | { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
320 | { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, | ||
321 | { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, | ||
322 | { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, | ||
323 | { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, | ||
324 | { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, | ||
325 | { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, | ||
326 | { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, | ||
327 | { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, | ||
328 | { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, | ||
329 | { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, | ||
330 | { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, | ||
331 | { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, | ||
332 | { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, | ||
333 | { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, | ||
334 | { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, | ||
335 | { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
336 | { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
337 | { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
338 | { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
339 | { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
340 | { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
341 | { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
342 | { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, | ||
343 | { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, | ||
344 | { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, | ||
345 | { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, | ||
346 | { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, | ||
347 | { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, | ||
348 | { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
349 | { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
350 | { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, | ||
351 | { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, | ||
352 | { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
353 | { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
354 | { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
355 | { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
356 | { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
357 | { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
358 | { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
359 | { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
360 | { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
361 | { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
362 | { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
363 | { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
364 | { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
365 | { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
366 | { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
367 | { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
368 | { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, | ||
369 | { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, | ||
370 | { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, | ||
371 | { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, | ||
372 | { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, | ||
373 | { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, | ||
374 | { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, | ||
375 | { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, | ||
376 | { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, | ||
377 | { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, | ||
378 | { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, | ||
379 | { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, | ||
380 | /* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ | ||
381 | { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, | ||
382 | { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, | ||
383 | { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, | ||
384 | { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, | ||
385 | { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, | ||
386 | { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, | ||
387 | { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, | ||
388 | { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, | ||
389 | { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, | ||
390 | { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, | ||
391 | { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, | ||
392 | { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, | ||
393 | { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, | ||
394 | { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, | ||
395 | { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, | ||
396 | { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } | ||
397 | }; | ||
398 | |||
399 | /* | ||
400 | * look up a certain register in ar5416_phy_init[] and return the init. value | ||
401 | * for the band and bandwidth given. Return 0 if register address not found. | ||
402 | */ | ||
403 | static u32 ar9170_get_default_phy_reg_val(u32 reg, bool is_2ghz, bool is_40mhz) | ||
404 | { | ||
405 | unsigned int i; | ||
406 | for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { | ||
407 | if (ar5416_phy_init[i].reg != reg) | ||
408 | continue; | ||
409 | |||
410 | if (is_2ghz) { | ||
411 | if (is_40mhz) | ||
412 | return ar5416_phy_init[i]._2ghz_40; | ||
413 | else | ||
414 | return ar5416_phy_init[i]._2ghz_20; | ||
415 | } else { | ||
416 | if (is_40mhz) | ||
417 | return ar5416_phy_init[i]._5ghz_40; | ||
418 | else | ||
419 | return ar5416_phy_init[i]._5ghz_20; | ||
420 | } | ||
421 | } | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | /* | ||
426 | * initialize some phy regs from eeprom values in modal_header[] | ||
427 | * acc. to band and bandwidth | ||
428 | */ | ||
429 | static int ar9170_init_phy_from_eeprom(struct ar9170 *ar, | ||
430 | bool is_2ghz, bool is_40mhz) | ||
431 | { | ||
432 | static const u8 xpd2pd[16] = { | ||
433 | 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2, | ||
434 | 0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2 | ||
435 | }; | ||
436 | u32 defval, newval; | ||
437 | /* pointer to the modal_header acc. to band */ | ||
438 | struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz]; | ||
439 | |||
440 | ar9170_regwrite_begin(ar); | ||
441 | |||
442 | /* ant common control (index 0) */ | ||
443 | newval = le32_to_cpu(m->antCtrlCommon); | ||
444 | ar9170_regwrite(0x1c5964, newval); | ||
445 | |||
446 | /* ant control chain 0 (index 1) */ | ||
447 | newval = le32_to_cpu(m->antCtrlChain[0]); | ||
448 | ar9170_regwrite(0x1c5960, newval); | ||
449 | |||
450 | /* ant control chain 2 (index 2) */ | ||
451 | newval = le32_to_cpu(m->antCtrlChain[1]); | ||
452 | ar9170_regwrite(0x1c7960, newval); | ||
453 | |||
454 | /* SwSettle (index 3) */ | ||
455 | if (!is_40mhz) { | ||
456 | defval = ar9170_get_default_phy_reg_val(0x1c5844, | ||
457 | is_2ghz, is_40mhz); | ||
458 | newval = (defval & ~0x3f80) | | ||
459 | ((m->switchSettling & 0x7f) << 7); | ||
460 | ar9170_regwrite(0x1c5844, newval); | ||
461 | } | ||
462 | |||
463 | /* adcDesired, pdaDesired (index 4) */ | ||
464 | defval = ar9170_get_default_phy_reg_val(0x1c5850, is_2ghz, is_40mhz); | ||
465 | newval = (defval & ~0xffff) | ((u8)m->pgaDesiredSize << 8) | | ||
466 | ((u8)m->adcDesiredSize); | ||
467 | ar9170_regwrite(0x1c5850, newval); | ||
468 | |||
469 | /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */ | ||
470 | defval = ar9170_get_default_phy_reg_val(0x1c5834, is_2ghz, is_40mhz); | ||
471 | newval = (m->txEndToXpaOff << 24) | (m->txEndToXpaOff << 16) | | ||
472 | (m->txFrameToXpaOn << 8) | m->txFrameToXpaOn; | ||
473 | ar9170_regwrite(0x1c5834, newval); | ||
474 | |||
475 | /* TxEndToRxOn (index 6) */ | ||
476 | defval = ar9170_get_default_phy_reg_val(0x1c5828, is_2ghz, is_40mhz); | ||
477 | newval = (defval & ~0xff0000) | (m->txEndToRxOn << 16); | ||
478 | ar9170_regwrite(0x1c5828, newval); | ||
479 | |||
480 | /* thresh62 (index 7) */ | ||
481 | defval = ar9170_get_default_phy_reg_val(0x1c8864, is_2ghz, is_40mhz); | ||
482 | newval = (defval & ~0x7f000) | (m->thresh62 << 12); | ||
483 | ar9170_regwrite(0x1c8864, newval); | ||
484 | |||
485 | /* tx/rx attenuation chain 0 (index 8) */ | ||
486 | defval = ar9170_get_default_phy_reg_val(0x1c5848, is_2ghz, is_40mhz); | ||
487 | newval = (defval & ~0x3f000) | ((m->txRxAttenCh[0] & 0x3f) << 12); | ||
488 | ar9170_regwrite(0x1c5848, newval); | ||
489 | |||
490 | /* tx/rx attenuation chain 2 (index 9) */ | ||
491 | defval = ar9170_get_default_phy_reg_val(0x1c7848, is_2ghz, is_40mhz); | ||
492 | newval = (defval & ~0x3f000) | ((m->txRxAttenCh[1] & 0x3f) << 12); | ||
493 | ar9170_regwrite(0x1c7848, newval); | ||
494 | |||
495 | /* tx/rx margin chain 0 (index 10) */ | ||
496 | defval = ar9170_get_default_phy_reg_val(0x1c620c, is_2ghz, is_40mhz); | ||
497 | newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[0] & 0x3f) << 18); | ||
498 | /* bsw margin chain 0 for 5GHz only */ | ||
499 | if (!is_2ghz) | ||
500 | newval = (newval & ~0x3c00) | ((m->bswMargin[0] & 0xf) << 10); | ||
501 | ar9170_regwrite(0x1c620c, newval); | ||
502 | |||
503 | /* tx/rx margin chain 2 (index 11) */ | ||
504 | defval = ar9170_get_default_phy_reg_val(0x1c820c, is_2ghz, is_40mhz); | ||
505 | newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[1] & 0x3f) << 18); | ||
506 | ar9170_regwrite(0x1c820c, newval); | ||
507 | |||
508 | /* iqCall, iqCallq chain 0 (index 12) */ | ||
509 | defval = ar9170_get_default_phy_reg_val(0x1c5920, is_2ghz, is_40mhz); | ||
510 | newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[0] & 0x3f) << 5) | | ||
511 | ((u8)m->iqCalQCh[0] & 0x1f); | ||
512 | ar9170_regwrite(0x1c5920, newval); | ||
513 | |||
514 | /* iqCall, iqCallq chain 2 (index 13) */ | ||
515 | defval = ar9170_get_default_phy_reg_val(0x1c7920, is_2ghz, is_40mhz); | ||
516 | newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[1] & 0x3f) << 5) | | ||
517 | ((u8)m->iqCalQCh[1] & 0x1f); | ||
518 | ar9170_regwrite(0x1c7920, newval); | ||
519 | |||
520 | /* xpd gain mask (index 14) */ | ||
521 | defval = ar9170_get_default_phy_reg_val(0x1c6258, is_2ghz, is_40mhz); | ||
522 | newval = (defval & ~0xf0000) | (xpd2pd[m->xpdGain & 0xf] << 16); | ||
523 | ar9170_regwrite(0x1c6258, newval); | ||
524 | ar9170_regwrite_finish(); | ||
525 | |||
526 | return ar9170_regwrite_result(); | ||
527 | } | ||
528 | |||
529 | int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) | ||
530 | { | ||
531 | int i, err; | ||
532 | u32 val; | ||
533 | bool is_2ghz = band == IEEE80211_BAND_2GHZ; | ||
534 | bool is_40mhz = conf_is_ht40(&ar->hw->conf); | ||
535 | |||
536 | ar9170_regwrite_begin(ar); | ||
537 | |||
538 | for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { | ||
539 | if (is_40mhz) { | ||
540 | if (is_2ghz) | ||
541 | val = ar5416_phy_init[i]._2ghz_40; | ||
542 | else | ||
543 | val = ar5416_phy_init[i]._5ghz_40; | ||
544 | } else { | ||
545 | if (is_2ghz) | ||
546 | val = ar5416_phy_init[i]._2ghz_20; | ||
547 | else | ||
548 | val = ar5416_phy_init[i]._5ghz_20; | ||
549 | } | ||
550 | |||
551 | ar9170_regwrite(ar5416_phy_init[i].reg, val); | ||
552 | } | ||
553 | |||
554 | ar9170_regwrite_finish(); | ||
555 | err = ar9170_regwrite_result(); | ||
556 | if (err) | ||
557 | return err; | ||
558 | |||
559 | err = ar9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz); | ||
560 | if (err) | ||
561 | return err; | ||
562 | |||
563 | err = ar9170_init_power_cal(ar); | ||
564 | if (err) | ||
565 | return err; | ||
566 | |||
567 | /* XXX: remove magic! */ | ||
568 | if (is_2ghz) | ||
569 | err = ar9170_write_reg(ar, 0x1d4014, 0x5163); | ||
570 | else | ||
571 | err = ar9170_write_reg(ar, 0x1d4014, 0x5143); | ||
572 | |||
573 | return err; | ||
574 | } | ||
575 | |||
576 | struct ar9170_rf_init { | ||
577 | u32 reg, _5ghz, _2ghz; | ||
578 | }; | ||
579 | |||
580 | static struct ar9170_rf_init ar9170_rf_init[] = { | ||
581 | /* bank 0 */ | ||
582 | { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, | ||
583 | { 0x1c58e0, 0x02008020, 0x02008020}, | ||
584 | /* bank 1 */ | ||
585 | { 0x1c58b0, 0x02108421, 0x02108421}, | ||
586 | { 0x1c58ec, 0x00000008, 0x00000008}, | ||
587 | /* bank 2 */ | ||
588 | { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, | ||
589 | { 0x1c58e0, 0x00000420, 0x00000420}, | ||
590 | /* bank 3 */ | ||
591 | { 0x1c58f0, 0x01400018, 0x01c00018}, | ||
592 | /* bank 4 */ | ||
593 | { 0x1c58b0, 0x000001a1, 0x000001a1}, | ||
594 | { 0x1c58e8, 0x00000001, 0x00000001}, | ||
595 | /* bank 5 */ | ||
596 | { 0x1c58b0, 0x00000013, 0x00000013}, | ||
597 | { 0x1c58e4, 0x00000002, 0x00000002}, | ||
598 | /* bank 6 */ | ||
599 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
600 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
601 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
602 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
603 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
604 | { 0x1c58b0, 0x00004000, 0x00004000}, | ||
605 | { 0x1c58b0, 0x00006c00, 0x00006c00}, | ||
606 | { 0x1c58b0, 0x00002c00, 0x00002c00}, | ||
607 | { 0x1c58b0, 0x00004800, 0x00004800}, | ||
608 | { 0x1c58b0, 0x00004000, 0x00004000}, | ||
609 | { 0x1c58b0, 0x00006000, 0x00006000}, | ||
610 | { 0x1c58b0, 0x00001000, 0x00001000}, | ||
611 | { 0x1c58b0, 0x00004000, 0x00004000}, | ||
612 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
613 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
614 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
615 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
616 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
617 | { 0x1c58b0, 0x00087c00, 0x00087c00}, | ||
618 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
619 | { 0x1c58b0, 0x00005400, 0x00005400}, | ||
620 | { 0x1c58b0, 0x00000c00, 0x00000c00}, | ||
621 | { 0x1c58b0, 0x00001800, 0x00001800}, | ||
622 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
623 | { 0x1c58b0, 0x00006c00, 0x00006c00}, | ||
624 | { 0x1c58b0, 0x00006c00, 0x00006c00}, | ||
625 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
626 | { 0x1c58b0, 0x00002c00, 0x00002c00}, | ||
627 | { 0x1c58b0, 0x00003c00, 0x00003c00}, | ||
628 | { 0x1c58b0, 0x00003800, 0x00003800}, | ||
629 | { 0x1c58b0, 0x00001c00, 0x00001c00}, | ||
630 | { 0x1c58b0, 0x00000800, 0x00000800}, | ||
631 | { 0x1c58b0, 0x00000408, 0x00000408}, | ||
632 | { 0x1c58b0, 0x00004c15, 0x00004c15}, | ||
633 | { 0x1c58b0, 0x00004188, 0x00004188}, | ||
634 | { 0x1c58b0, 0x0000201e, 0x0000201e}, | ||
635 | { 0x1c58b0, 0x00010408, 0x00010408}, | ||
636 | { 0x1c58b0, 0x00000801, 0x00000801}, | ||
637 | { 0x1c58b0, 0x00000c08, 0x00000c08}, | ||
638 | { 0x1c58b0, 0x0000181e, 0x0000181e}, | ||
639 | { 0x1c58b0, 0x00001016, 0x00001016}, | ||
640 | { 0x1c58b0, 0x00002800, 0x00002800}, | ||
641 | { 0x1c58b0, 0x00004010, 0x00004010}, | ||
642 | { 0x1c58b0, 0x0000081c, 0x0000081c}, | ||
643 | { 0x1c58b0, 0x00000115, 0x00000115}, | ||
644 | { 0x1c58b0, 0x00000015, 0x00000015}, | ||
645 | { 0x1c58b0, 0x00000066, 0x00000066}, | ||
646 | { 0x1c58b0, 0x0000001c, 0x0000001c}, | ||
647 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
648 | { 0x1c58b0, 0x00000004, 0x00000004}, | ||
649 | { 0x1c58b0, 0x00000015, 0x00000015}, | ||
650 | { 0x1c58b0, 0x0000001f, 0x0000001f}, | ||
651 | { 0x1c58e0, 0x00000000, 0x00000400}, | ||
652 | /* bank 7 */ | ||
653 | { 0x1c58b0, 0x000000a0, 0x000000a0}, | ||
654 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
655 | { 0x1c58b0, 0x00000040, 0x00000040}, | ||
656 | { 0x1c58f0, 0x0000001c, 0x0000001c}, | ||
657 | }; | ||
658 | |||
659 | static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) | ||
660 | { | ||
661 | int err, i; | ||
662 | |||
663 | ar9170_regwrite_begin(ar); | ||
664 | |||
665 | for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++) | ||
666 | ar9170_regwrite(ar9170_rf_init[i].reg, | ||
667 | band5ghz ? ar9170_rf_init[i]._5ghz | ||
668 | : ar9170_rf_init[i]._2ghz); | ||
669 | |||
670 | ar9170_regwrite_finish(); | ||
671 | err = ar9170_regwrite_result(); | ||
672 | if (err) | ||
673 | wiphy_err(ar->hw->wiphy, "rf init failed\n"); | ||
674 | return err; | ||
675 | } | ||
676 | |||
677 | static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, | ||
678 | u32 freq, enum ar9170_bw bw) | ||
679 | { | ||
680 | int err; | ||
681 | u32 d0, d1, td0, td1, fd0, fd1; | ||
682 | u8 chansel; | ||
683 | u8 refsel0 = 1, refsel1 = 0; | ||
684 | u8 lf_synth = 0; | ||
685 | |||
686 | switch (bw) { | ||
687 | case AR9170_BW_40_ABOVE: | ||
688 | freq += 10; | ||
689 | break; | ||
690 | case AR9170_BW_40_BELOW: | ||
691 | freq -= 10; | ||
692 | break; | ||
693 | case AR9170_BW_20: | ||
694 | break; | ||
695 | case __AR9170_NUM_BW: | ||
696 | BUG(); | ||
697 | } | ||
698 | |||
699 | if (band5ghz) { | ||
700 | if (freq % 10) { | ||
701 | chansel = (freq - 4800) / 5; | ||
702 | } else { | ||
703 | chansel = ((freq - 4800) / 10) * 2; | ||
704 | refsel0 = 0; | ||
705 | refsel1 = 1; | ||
706 | } | ||
707 | chansel = byte_rev_table[chansel]; | ||
708 | } else { | ||
709 | if (freq == 2484) { | ||
710 | chansel = 10 + (freq - 2274) / 5; | ||
711 | lf_synth = 1; | ||
712 | } else | ||
713 | chansel = 16 + (freq - 2272) / 5; | ||
714 | chansel *= 4; | ||
715 | chansel = byte_rev_table[chansel]; | ||
716 | } | ||
717 | |||
718 | d1 = chansel; | ||
719 | d0 = 0x21 | | ||
720 | refsel0 << 3 | | ||
721 | refsel1 << 2 | | ||
722 | lf_synth << 1; | ||
723 | td0 = d0 & 0x1f; | ||
724 | td1 = d1 & 0x1f; | ||
725 | fd0 = td1 << 5 | td0; | ||
726 | |||
727 | td0 = (d0 >> 5) & 0x7; | ||
728 | td1 = (d1 >> 5) & 0x7; | ||
729 | fd1 = td1 << 5 | td0; | ||
730 | |||
731 | ar9170_regwrite_begin(ar); | ||
732 | |||
733 | ar9170_regwrite(0x1c58b0, fd0); | ||
734 | ar9170_regwrite(0x1c58e8, fd1); | ||
735 | |||
736 | ar9170_regwrite_finish(); | ||
737 | err = ar9170_regwrite_result(); | ||
738 | if (err) | ||
739 | return err; | ||
740 | |||
741 | msleep(10); | ||
742 | |||
743 | return 0; | ||
744 | } | ||
745 | |||
746 | struct ar9170_phy_freq_params { | ||
747 | u8 coeff_exp; | ||
748 | u16 coeff_man; | ||
749 | u8 coeff_exp_shgi; | ||
750 | u16 coeff_man_shgi; | ||
751 | }; | ||
752 | |||
753 | struct ar9170_phy_freq_entry { | ||
754 | u16 freq; | ||
755 | struct ar9170_phy_freq_params params[__AR9170_NUM_BW]; | ||
756 | }; | ||
757 | |||
758 | /* NB: must be in sync with channel tables in main! */ | ||
759 | static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = { | ||
760 | /* | ||
761 | * freq, | ||
762 | * 20MHz, | ||
763 | * 40MHz (below), | ||
764 | * 40Mhz (above), | ||
765 | */ | ||
766 | { 2412, { | ||
767 | { 3, 21737, 3, 19563, }, | ||
768 | { 3, 21827, 3, 19644, }, | ||
769 | { 3, 21647, 3, 19482, }, | ||
770 | } }, | ||
771 | { 2417, { | ||
772 | { 3, 21692, 3, 19523, }, | ||
773 | { 3, 21782, 3, 19604, }, | ||
774 | { 3, 21602, 3, 19442, }, | ||
775 | } }, | ||
776 | { 2422, { | ||
777 | { 3, 21647, 3, 19482, }, | ||
778 | { 3, 21737, 3, 19563, }, | ||
779 | { 3, 21558, 3, 19402, }, | ||
780 | } }, | ||
781 | { 2427, { | ||
782 | { 3, 21602, 3, 19442, }, | ||
783 | { 3, 21692, 3, 19523, }, | ||
784 | { 3, 21514, 3, 19362, }, | ||
785 | } }, | ||
786 | { 2432, { | ||
787 | { 3, 21558, 3, 19402, }, | ||
788 | { 3, 21647, 3, 19482, }, | ||
789 | { 3, 21470, 3, 19323, }, | ||
790 | } }, | ||
791 | { 2437, { | ||
792 | { 3, 21514, 3, 19362, }, | ||
793 | { 3, 21602, 3, 19442, }, | ||
794 | { 3, 21426, 3, 19283, }, | ||
795 | } }, | ||
796 | { 2442, { | ||
797 | { 3, 21470, 3, 19323, }, | ||
798 | { 3, 21558, 3, 19402, }, | ||
799 | { 3, 21382, 3, 19244, }, | ||
800 | } }, | ||
801 | { 2447, { | ||
802 | { 3, 21426, 3, 19283, }, | ||
803 | { 3, 21514, 3, 19362, }, | ||
804 | { 3, 21339, 3, 19205, }, | ||
805 | } }, | ||
806 | { 2452, { | ||
807 | { 3, 21382, 3, 19244, }, | ||
808 | { 3, 21470, 3, 19323, }, | ||
809 | { 3, 21295, 3, 19166, }, | ||
810 | } }, | ||
811 | { 2457, { | ||
812 | { 3, 21339, 3, 19205, }, | ||
813 | { 3, 21426, 3, 19283, }, | ||
814 | { 3, 21252, 3, 19127, }, | ||
815 | } }, | ||
816 | { 2462, { | ||
817 | { 3, 21295, 3, 19166, }, | ||
818 | { 3, 21382, 3, 19244, }, | ||
819 | { 3, 21209, 3, 19088, }, | ||
820 | } }, | ||
821 | { 2467, { | ||
822 | { 3, 21252, 3, 19127, }, | ||
823 | { 3, 21339, 3, 19205, }, | ||
824 | { 3, 21166, 3, 19050, }, | ||
825 | } }, | ||
826 | { 2472, { | ||
827 | { 3, 21209, 3, 19088, }, | ||
828 | { 3, 21295, 3, 19166, }, | ||
829 | { 3, 21124, 3, 19011, }, | ||
830 | } }, | ||
831 | { 2484, { | ||
832 | { 3, 21107, 3, 18996, }, | ||
833 | { 3, 21192, 3, 19073, }, | ||
834 | { 3, 21022, 3, 18920, }, | ||
835 | } }, | ||
836 | { 4920, { | ||
837 | { 4, 21313, 4, 19181, }, | ||
838 | { 4, 21356, 4, 19220, }, | ||
839 | { 4, 21269, 4, 19142, }, | ||
840 | } }, | ||
841 | { 4940, { | ||
842 | { 4, 21226, 4, 19104, }, | ||
843 | { 4, 21269, 4, 19142, }, | ||
844 | { 4, 21183, 4, 19065, }, | ||
845 | } }, | ||
846 | { 4960, { | ||
847 | { 4, 21141, 4, 19027, }, | ||
848 | { 4, 21183, 4, 19065, }, | ||
849 | { 4, 21098, 4, 18988, }, | ||
850 | } }, | ||
851 | { 4980, { | ||
852 | { 4, 21056, 4, 18950, }, | ||
853 | { 4, 21098, 4, 18988, }, | ||
854 | { 4, 21014, 4, 18912, }, | ||
855 | } }, | ||
856 | { 5040, { | ||
857 | { 4, 20805, 4, 18725, }, | ||
858 | { 4, 20846, 4, 18762, }, | ||
859 | { 4, 20764, 4, 18687, }, | ||
860 | } }, | ||
861 | { 5060, { | ||
862 | { 4, 20723, 4, 18651, }, | ||
863 | { 4, 20764, 4, 18687, }, | ||
864 | { 4, 20682, 4, 18614, }, | ||
865 | } }, | ||
866 | { 5080, { | ||
867 | { 4, 20641, 4, 18577, }, | ||
868 | { 4, 20682, 4, 18614, }, | ||
869 | { 4, 20601, 4, 18541, }, | ||
870 | } }, | ||
871 | { 5180, { | ||
872 | { 4, 20243, 4, 18219, }, | ||
873 | { 4, 20282, 4, 18254, }, | ||
874 | { 4, 20204, 4, 18183, }, | ||
875 | } }, | ||
876 | { 5200, { | ||
877 | { 4, 20165, 4, 18148, }, | ||
878 | { 4, 20204, 4, 18183, }, | ||
879 | { 4, 20126, 4, 18114, }, | ||
880 | } }, | ||
881 | { 5220, { | ||
882 | { 4, 20088, 4, 18079, }, | ||
883 | { 4, 20126, 4, 18114, }, | ||
884 | { 4, 20049, 4, 18044, }, | ||
885 | } }, | ||
886 | { 5240, { | ||
887 | { 4, 20011, 4, 18010, }, | ||
888 | { 4, 20049, 4, 18044, }, | ||
889 | { 4, 19973, 4, 17976, }, | ||
890 | } }, | ||
891 | { 5260, { | ||
892 | { 4, 19935, 4, 17941, }, | ||
893 | { 4, 19973, 4, 17976, }, | ||
894 | { 4, 19897, 4, 17907, }, | ||
895 | } }, | ||
896 | { 5280, { | ||
897 | { 4, 19859, 4, 17873, }, | ||
898 | { 4, 19897, 4, 17907, }, | ||
899 | { 4, 19822, 4, 17840, }, | ||
900 | } }, | ||
901 | { 5300, { | ||
902 | { 4, 19784, 4, 17806, }, | ||
903 | { 4, 19822, 4, 17840, }, | ||
904 | { 4, 19747, 4, 17772, }, | ||
905 | } }, | ||
906 | { 5320, { | ||
907 | { 4, 19710, 4, 17739, }, | ||
908 | { 4, 19747, 4, 17772, }, | ||
909 | { 4, 19673, 4, 17706, }, | ||
910 | } }, | ||
911 | { 5500, { | ||
912 | { 4, 19065, 4, 17159, }, | ||
913 | { 4, 19100, 4, 17190, }, | ||
914 | { 4, 19030, 4, 17127, }, | ||
915 | } }, | ||
916 | { 5520, { | ||
917 | { 4, 18996, 4, 17096, }, | ||
918 | { 4, 19030, 4, 17127, }, | ||
919 | { 4, 18962, 4, 17065, }, | ||
920 | } }, | ||
921 | { 5540, { | ||
922 | { 4, 18927, 4, 17035, }, | ||
923 | { 4, 18962, 4, 17065, }, | ||
924 | { 4, 18893, 4, 17004, }, | ||
925 | } }, | ||
926 | { 5560, { | ||
927 | { 4, 18859, 4, 16973, }, | ||
928 | { 4, 18893, 4, 17004, }, | ||
929 | { 4, 18825, 4, 16943, }, | ||
930 | } }, | ||
931 | { 5580, { | ||
932 | { 4, 18792, 4, 16913, }, | ||
933 | { 4, 18825, 4, 16943, }, | ||
934 | { 4, 18758, 4, 16882, }, | ||
935 | } }, | ||
936 | { 5600, { | ||
937 | { 4, 18725, 4, 16852, }, | ||
938 | { 4, 18758, 4, 16882, }, | ||
939 | { 4, 18691, 4, 16822, }, | ||
940 | } }, | ||
941 | { 5620, { | ||
942 | { 4, 18658, 4, 16792, }, | ||
943 | { 4, 18691, 4, 16822, }, | ||
944 | { 4, 18625, 4, 16762, }, | ||
945 | } }, | ||
946 | { 5640, { | ||
947 | { 4, 18592, 4, 16733, }, | ||
948 | { 4, 18625, 4, 16762, }, | ||
949 | { 4, 18559, 4, 16703, }, | ||
950 | } }, | ||
951 | { 5660, { | ||
952 | { 4, 18526, 4, 16673, }, | ||
953 | { 4, 18559, 4, 16703, }, | ||
954 | { 4, 18493, 4, 16644, }, | ||
955 | } }, | ||
956 | { 5680, { | ||
957 | { 4, 18461, 4, 16615, }, | ||
958 | { 4, 18493, 4, 16644, }, | ||
959 | { 4, 18428, 4, 16586, }, | ||
960 | } }, | ||
961 | { 5700, { | ||
962 | { 4, 18396, 4, 16556, }, | ||
963 | { 4, 18428, 4, 16586, }, | ||
964 | { 4, 18364, 4, 16527, }, | ||
965 | } }, | ||
966 | { 5745, { | ||
967 | { 4, 18252, 4, 16427, }, | ||
968 | { 4, 18284, 4, 16455, }, | ||
969 | { 4, 18220, 4, 16398, }, | ||
970 | } }, | ||
971 | { 5765, { | ||
972 | { 4, 18189, 5, 32740, }, | ||
973 | { 4, 18220, 4, 16398, }, | ||
974 | { 4, 18157, 5, 32683, }, | ||
975 | } }, | ||
976 | { 5785, { | ||
977 | { 4, 18126, 5, 32626, }, | ||
978 | { 4, 18157, 5, 32683, }, | ||
979 | { 4, 18094, 5, 32570, }, | ||
980 | } }, | ||
981 | { 5805, { | ||
982 | { 4, 18063, 5, 32514, }, | ||
983 | { 4, 18094, 5, 32570, }, | ||
984 | { 4, 18032, 5, 32458, }, | ||
985 | } }, | ||
986 | { 5825, { | ||
987 | { 4, 18001, 5, 32402, }, | ||
988 | { 4, 18032, 5, 32458, }, | ||
989 | { 4, 17970, 5, 32347, }, | ||
990 | } }, | ||
991 | { 5170, { | ||
992 | { 4, 20282, 4, 18254, }, | ||
993 | { 4, 20321, 4, 18289, }, | ||
994 | { 4, 20243, 4, 18219, }, | ||
995 | } }, | ||
996 | { 5190, { | ||
997 | { 4, 20204, 4, 18183, }, | ||
998 | { 4, 20243, 4, 18219, }, | ||
999 | { 4, 20165, 4, 18148, }, | ||
1000 | } }, | ||
1001 | { 5210, { | ||
1002 | { 4, 20126, 4, 18114, }, | ||
1003 | { 4, 20165, 4, 18148, }, | ||
1004 | { 4, 20088, 4, 18079, }, | ||
1005 | } }, | ||
1006 | { 5230, { | ||
1007 | { 4, 20049, 4, 18044, }, | ||
1008 | { 4, 20088, 4, 18079, }, | ||
1009 | { 4, 20011, 4, 18010, }, | ||
1010 | } }, | ||
1011 | }; | ||
1012 | |||
1013 | static const struct ar9170_phy_freq_params * | ||
1014 | ar9170_get_hw_dyn_params(struct ieee80211_channel *channel, | ||
1015 | enum ar9170_bw bw) | ||
1016 | { | ||
1017 | unsigned int chanidx = 0; | ||
1018 | u16 freq = 2412; | ||
1019 | |||
1020 | if (channel) { | ||
1021 | chanidx = channel->hw_value; | ||
1022 | freq = channel->center_freq; | ||
1023 | } | ||
1024 | |||
1025 | BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params)); | ||
1026 | |||
1027 | BUILD_BUG_ON(__AR9170_NUM_BW != 3); | ||
1028 | |||
1029 | WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq); | ||
1030 | |||
1031 | return &ar9170_phy_freq_params[chanidx].params[bw]; | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | int ar9170_init_rf(struct ar9170 *ar) | ||
1036 | { | ||
1037 | const struct ar9170_phy_freq_params *freqpar; | ||
1038 | __le32 cmd[7]; | ||
1039 | int err; | ||
1040 | |||
1041 | err = ar9170_init_rf_banks_0_7(ar, false); | ||
1042 | if (err) | ||
1043 | return err; | ||
1044 | |||
1045 | err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20); | ||
1046 | if (err) | ||
1047 | return err; | ||
1048 | |||
1049 | freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20); | ||
1050 | |||
1051 | cmd[0] = cpu_to_le32(2412 * 1000); | ||
1052 | cmd[1] = cpu_to_le32(0); | ||
1053 | cmd[2] = cpu_to_le32(1); | ||
1054 | cmd[3] = cpu_to_le32(freqpar->coeff_exp); | ||
1055 | cmd[4] = cpu_to_le32(freqpar->coeff_man); | ||
1056 | cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi); | ||
1057 | cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi); | ||
1058 | |||
1059 | /* RF_INIT echoes the command back to us */ | ||
1060 | err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT, | ||
1061 | sizeof(cmd), (u8 *)cmd, | ||
1062 | sizeof(cmd), (u8 *)cmd); | ||
1063 | if (err) | ||
1064 | return err; | ||
1065 | |||
1066 | msleep(1000); | ||
1067 | |||
1068 | return ar9170_echo_test(ar, 0xaabbccdd); | ||
1069 | } | ||
1070 | |||
1071 | static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) | ||
1072 | { | ||
1073 | int idx = nfreqs - 2; | ||
1074 | |||
1075 | while (idx >= 0) { | ||
1076 | if (f >= freqs[idx]) | ||
1077 | return idx; | ||
1078 | idx--; | ||
1079 | } | ||
1080 | |||
1081 | return 0; | ||
1082 | } | ||
1083 | |||
1084 | static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) | ||
1085 | { | ||
1086 | /* nothing to interpolate, it's horizontal */ | ||
1087 | if (y2 == y1) | ||
1088 | return y1; | ||
1089 | |||
1090 | /* check if we hit one of the edges */ | ||
1091 | if (x == x1) | ||
1092 | return y1; | ||
1093 | if (x == x2) | ||
1094 | return y2; | ||
1095 | |||
1096 | /* x1 == x2 is bad, hopefully == x */ | ||
1097 | if (x2 == x1) | ||
1098 | return y1; | ||
1099 | |||
1100 | return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); | ||
1101 | } | ||
1102 | |||
1103 | static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) | ||
1104 | { | ||
1105 | #define SHIFT 8 | ||
1106 | s32 y; | ||
1107 | |||
1108 | y = ar9170_interpolate_s32(x << SHIFT, | ||
1109 | x1 << SHIFT, y1 << SHIFT, | ||
1110 | x2 << SHIFT, y2 << SHIFT); | ||
1111 | |||
1112 | /* | ||
1113 | * XXX: unwrap this expression | ||
1114 | * Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)? | ||
1115 | * Can we rely on the compiler to optimise away the div? | ||
1116 | */ | ||
1117 | return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); | ||
1118 | #undef SHIFT | ||
1119 | } | ||
1120 | |||
1121 | static u8 ar9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array) | ||
1122 | { | ||
1123 | int i; | ||
1124 | |||
1125 | for (i = 0; i < 3; i++) | ||
1126 | if (x <= x_array[i + 1]) | ||
1127 | break; | ||
1128 | |||
1129 | return ar9170_interpolate_u8(x, | ||
1130 | x_array[i], | ||
1131 | y_array[i], | ||
1132 | x_array[i + 1], | ||
1133 | y_array[i + 1]); | ||
1134 | } | ||
1135 | |||
1136 | static int ar9170_set_freq_cal_data(struct ar9170 *ar, | ||
1137 | struct ieee80211_channel *channel) | ||
1138 | { | ||
1139 | u8 *cal_freq_pier; | ||
1140 | u8 vpds[2][AR5416_PD_GAIN_ICEPTS]; | ||
1141 | u8 pwrs[2][AR5416_PD_GAIN_ICEPTS]; | ||
1142 | int chain, idx, i; | ||
1143 | u32 phy_data = 0; | ||
1144 | u8 f, tmp; | ||
1145 | |||
1146 | switch (channel->band) { | ||
1147 | case IEEE80211_BAND_2GHZ: | ||
1148 | f = channel->center_freq - 2300; | ||
1149 | cal_freq_pier = ar->eeprom.cal_freq_pier_2G; | ||
1150 | i = AR5416_NUM_2G_CAL_PIERS - 1; | ||
1151 | break; | ||
1152 | |||
1153 | case IEEE80211_BAND_5GHZ: | ||
1154 | f = (channel->center_freq - 4800) / 5; | ||
1155 | cal_freq_pier = ar->eeprom.cal_freq_pier_5G; | ||
1156 | i = AR5416_NUM_5G_CAL_PIERS - 1; | ||
1157 | break; | ||
1158 | |||
1159 | default: | ||
1160 | return -EINVAL; | ||
1161 | break; | ||
1162 | } | ||
1163 | |||
1164 | for (; i >= 0; i--) { | ||
1165 | if (cal_freq_pier[i] != 0xff) | ||
1166 | break; | ||
1167 | } | ||
1168 | if (i < 0) | ||
1169 | return -EINVAL; | ||
1170 | |||
1171 | idx = ar9170_find_freq_idx(i, cal_freq_pier, f); | ||
1172 | |||
1173 | ar9170_regwrite_begin(ar); | ||
1174 | |||
1175 | for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) { | ||
1176 | for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) { | ||
1177 | struct ar9170_calibration_data_per_freq *cal_pier_data; | ||
1178 | int j; | ||
1179 | |||
1180 | switch (channel->band) { | ||
1181 | case IEEE80211_BAND_2GHZ: | ||
1182 | cal_pier_data = &ar->eeprom. | ||
1183 | cal_pier_data_2G[chain][idx]; | ||
1184 | break; | ||
1185 | |||
1186 | case IEEE80211_BAND_5GHZ: | ||
1187 | cal_pier_data = &ar->eeprom. | ||
1188 | cal_pier_data_5G[chain][idx]; | ||
1189 | break; | ||
1190 | |||
1191 | default: | ||
1192 | return -EINVAL; | ||
1193 | } | ||
1194 | |||
1195 | for (j = 0; j < 2; j++) { | ||
1196 | vpds[j][i] = ar9170_interpolate_u8(f, | ||
1197 | cal_freq_pier[idx], | ||
1198 | cal_pier_data->vpd_pdg[j][i], | ||
1199 | cal_freq_pier[idx + 1], | ||
1200 | cal_pier_data[1].vpd_pdg[j][i]); | ||
1201 | |||
1202 | pwrs[j][i] = ar9170_interpolate_u8(f, | ||
1203 | cal_freq_pier[idx], | ||
1204 | cal_pier_data->pwr_pdg[j][i], | ||
1205 | cal_freq_pier[idx + 1], | ||
1206 | cal_pier_data[1].pwr_pdg[j][i]) / 2; | ||
1207 | } | ||
1208 | } | ||
1209 | |||
1210 | for (i = 0; i < 76; i++) { | ||
1211 | if (i < 25) { | ||
1212 | tmp = ar9170_interpolate_val(i, &pwrs[0][0], | ||
1213 | &vpds[0][0]); | ||
1214 | } else { | ||
1215 | tmp = ar9170_interpolate_val(i - 12, | ||
1216 | &pwrs[1][0], | ||
1217 | &vpds[1][0]); | ||
1218 | } | ||
1219 | |||
1220 | phy_data |= tmp << ((i & 3) << 3); | ||
1221 | if ((i & 3) == 3) { | ||
1222 | ar9170_regwrite(0x1c6280 + chain * 0x1000 + | ||
1223 | (i & ~3), phy_data); | ||
1224 | phy_data = 0; | ||
1225 | } | ||
1226 | } | ||
1227 | |||
1228 | for (i = 19; i < 32; i++) | ||
1229 | ar9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2), | ||
1230 | 0x0); | ||
1231 | } | ||
1232 | |||
1233 | ar9170_regwrite_finish(); | ||
1234 | return ar9170_regwrite_result(); | ||
1235 | } | ||
1236 | |||
1237 | static u8 ar9170_get_max_edge_power(struct ar9170 *ar, | ||
1238 | struct ar9170_calctl_edges edges[], | ||
1239 | u32 freq) | ||
1240 | { | ||
1241 | int i; | ||
1242 | u8 rc = AR5416_MAX_RATE_POWER; | ||
1243 | u8 f; | ||
1244 | if (freq < 3000) | ||
1245 | f = freq - 2300; | ||
1246 | else | ||
1247 | f = (freq - 4800) / 5; | ||
1248 | |||
1249 | for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { | ||
1250 | if (edges[i].channel == 0xff) | ||
1251 | break; | ||
1252 | if (f == edges[i].channel) { | ||
1253 | /* exact freq match */ | ||
1254 | rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS; | ||
1255 | break; | ||
1256 | } | ||
1257 | if (i > 0 && f < edges[i].channel) { | ||
1258 | if (f > edges[i - 1].channel && | ||
1259 | edges[i - 1].power_flags & | ||
1260 | AR9170_CALCTL_EDGE_FLAGS) { | ||
1261 | /* lower channel has the inband flag set */ | ||
1262 | rc = edges[i - 1].power_flags & | ||
1263 | ~AR9170_CALCTL_EDGE_FLAGS; | ||
1264 | } | ||
1265 | break; | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | if (i == AR5416_NUM_BAND_EDGES) { | ||
1270 | if (f > edges[i - 1].channel && | ||
1271 | edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { | ||
1272 | /* lower channel has the inband flag set */ | ||
1273 | rc = edges[i - 1].power_flags & | ||
1274 | ~AR9170_CALCTL_EDGE_FLAGS; | ||
1275 | } | ||
1276 | } | ||
1277 | return rc; | ||
1278 | } | ||
1279 | |||
1280 | static u8 ar9170_get_heavy_clip(struct ar9170 *ar, | ||
1281 | struct ar9170_calctl_edges edges[], | ||
1282 | u32 freq, enum ar9170_bw bw) | ||
1283 | { | ||
1284 | u8 f; | ||
1285 | int i; | ||
1286 | u8 rc = 0; | ||
1287 | |||
1288 | if (freq < 3000) | ||
1289 | f = freq - 2300; | ||
1290 | else | ||
1291 | f = (freq - 4800) / 5; | ||
1292 | |||
1293 | if (bw == AR9170_BW_40_BELOW || bw == AR9170_BW_40_ABOVE) | ||
1294 | rc |= 0xf0; | ||
1295 | |||
1296 | for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { | ||
1297 | if (edges[i].channel == 0xff) | ||
1298 | break; | ||
1299 | if (f == edges[i].channel) { | ||
1300 | if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS)) | ||
1301 | rc |= 0x0f; | ||
1302 | break; | ||
1303 | } | ||
1304 | } | ||
1305 | |||
1306 | return rc; | ||
1307 | } | ||
1308 | |||
1309 | /* | ||
1310 | * calculate the conformance test limits and the heavy clip parameter | ||
1311 | * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706) | ||
1312 | */ | ||
1313 | static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | ||
1314 | { | ||
1315 | u8 ctl_grp; /* CTL group */ | ||
1316 | u8 ctl_idx; /* CTL index */ | ||
1317 | int i, j; | ||
1318 | struct ctl_modes { | ||
1319 | u8 ctl_mode; | ||
1320 | u8 max_power; | ||
1321 | u8 *pwr_cal_data; | ||
1322 | int pwr_cal_len; | ||
1323 | } *modes; | ||
1324 | |||
1325 | /* | ||
1326 | * order is relevant in the mode_list_*: we fall back to the | ||
1327 | * lower indices if any mode is missed in the EEPROM. | ||
1328 | */ | ||
1329 | struct ctl_modes mode_list_2ghz[] = { | ||
1330 | { CTL_11B, 0, ar->power_2G_cck, 4 }, | ||
1331 | { CTL_11G, 0, ar->power_2G_ofdm, 4 }, | ||
1332 | { CTL_2GHT20, 0, ar->power_2G_ht20, 8 }, | ||
1333 | { CTL_2GHT40, 0, ar->power_2G_ht40, 8 }, | ||
1334 | }; | ||
1335 | struct ctl_modes mode_list_5ghz[] = { | ||
1336 | { CTL_11A, 0, ar->power_5G_leg, 4 }, | ||
1337 | { CTL_5GHT20, 0, ar->power_5G_ht20, 8 }, | ||
1338 | { CTL_5GHT40, 0, ar->power_5G_ht40, 8 }, | ||
1339 | }; | ||
1340 | int nr_modes; | ||
1341 | |||
1342 | #define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) | ||
1343 | |||
1344 | ar->phy_heavy_clip = 0; | ||
1345 | |||
1346 | /* | ||
1347 | * TODO: investigate the differences between OTUS' | ||
1348 | * hpreg.c::zfHpGetRegulatoryDomain() and | ||
1349 | * ath/regd.c::ath_regd_get_band_ctl() - | ||
1350 | * e.g. for FCC3_WORLD the OTUS procedure | ||
1351 | * always returns CTL_FCC, while the one in ath/ delivers | ||
1352 | * CTL_ETSI for 2GHz and CTL_FCC for 5GHz. | ||
1353 | */ | ||
1354 | ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory, | ||
1355 | ar->hw->conf.channel->band); | ||
1356 | |||
1357 | /* ctl group not found - either invalid band (NO_CTL) or ww roaming */ | ||
1358 | if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL) | ||
1359 | ctl_grp = CTL_FCC; | ||
1360 | |||
1361 | if (ctl_grp != CTL_FCC) | ||
1362 | /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */ | ||
1363 | return; | ||
1364 | |||
1365 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { | ||
1366 | modes = mode_list_2ghz; | ||
1367 | nr_modes = ARRAY_SIZE(mode_list_2ghz); | ||
1368 | } else { | ||
1369 | modes = mode_list_5ghz; | ||
1370 | nr_modes = ARRAY_SIZE(mode_list_5ghz); | ||
1371 | } | ||
1372 | |||
1373 | for (i = 0; i < nr_modes; i++) { | ||
1374 | u8 c = ctl_grp | modes[i].ctl_mode; | ||
1375 | for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++) | ||
1376 | if (c == ar->eeprom.ctl_index[ctl_idx]) | ||
1377 | break; | ||
1378 | if (ctl_idx < AR5416_NUM_CTLS) { | ||
1379 | int f_off = 0; | ||
1380 | |||
1381 | /* determine heav clip parameter from | ||
1382 | the 11G edges array */ | ||
1383 | if (modes[i].ctl_mode == CTL_11G) { | ||
1384 | ar->phy_heavy_clip = | ||
1385 | ar9170_get_heavy_clip(ar, | ||
1386 | EDGES(ctl_idx, 1), | ||
1387 | freq, bw); | ||
1388 | } | ||
1389 | |||
1390 | /* adjust freq for 40MHz */ | ||
1391 | if (modes[i].ctl_mode == CTL_2GHT40 || | ||
1392 | modes[i].ctl_mode == CTL_5GHT40) { | ||
1393 | if (bw == AR9170_BW_40_BELOW) | ||
1394 | f_off = -10; | ||
1395 | else | ||
1396 | f_off = 10; | ||
1397 | } | ||
1398 | |||
1399 | modes[i].max_power = | ||
1400 | ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1), | ||
1401 | freq+f_off); | ||
1402 | |||
1403 | /* | ||
1404 | * TODO: check if the regulatory max. power is | ||
1405 | * controlled by cfg80211 for DFS | ||
1406 | * (hpmain applies it to max_power itself for DFS freq) | ||
1407 | */ | ||
1408 | |||
1409 | } else { | ||
1410 | /* | ||
1411 | * Workaround in otus driver, hpmain.c, line 3906: | ||
1412 | * if no data for 5GHT20 are found, take the | ||
1413 | * legacy 5G value. | ||
1414 | * We extend this here to fallback from any other *HT or | ||
1415 | * 11G, too. | ||
1416 | */ | ||
1417 | int k = i; | ||
1418 | |||
1419 | modes[i].max_power = AR5416_MAX_RATE_POWER; | ||
1420 | while (k-- > 0) { | ||
1421 | if (modes[k].max_power != | ||
1422 | AR5416_MAX_RATE_POWER) { | ||
1423 | modes[i].max_power = modes[k].max_power; | ||
1424 | break; | ||
1425 | } | ||
1426 | } | ||
1427 | } | ||
1428 | |||
1429 | /* apply max power to pwr_cal_data (ar->power_*) */ | ||
1430 | for (j = 0; j < modes[i].pwr_cal_len; j++) { | ||
1431 | modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j], | ||
1432 | modes[i].max_power); | ||
1433 | } | ||
1434 | } | ||
1435 | |||
1436 | if (ar->phy_heavy_clip & 0xf0) { | ||
1437 | ar->power_2G_ht40[0]--; | ||
1438 | ar->power_2G_ht40[1]--; | ||
1439 | ar->power_2G_ht40[2]--; | ||
1440 | } | ||
1441 | if (ar->phy_heavy_clip & 0xf) { | ||
1442 | ar->power_2G_ht20[0]++; | ||
1443 | ar->power_2G_ht20[1]++; | ||
1444 | ar->power_2G_ht20[2]++; | ||
1445 | } | ||
1446 | |||
1447 | |||
1448 | #undef EDGES | ||
1449 | } | ||
1450 | |||
1451 | static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | ||
1452 | { | ||
1453 | struct ar9170_calibration_target_power_legacy *ctpl; | ||
1454 | struct ar9170_calibration_target_power_ht *ctph; | ||
1455 | u8 *ctpres; | ||
1456 | int ntargets; | ||
1457 | int idx, i, n; | ||
1458 | u8 ackpower, ackchains, f; | ||
1459 | u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; | ||
1460 | |||
1461 | if (freq < 3000) | ||
1462 | f = freq - 2300; | ||
1463 | else | ||
1464 | f = (freq - 4800)/5; | ||
1465 | |||
1466 | /* | ||
1467 | * cycle through the various modes | ||
1468 | * | ||
1469 | * legacy modes first: 5G, 2G CCK, 2G OFDM | ||
1470 | */ | ||
1471 | for (i = 0; i < 3; i++) { | ||
1472 | switch (i) { | ||
1473 | case 0: /* 5 GHz legacy */ | ||
1474 | ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; | ||
1475 | ntargets = AR5416_NUM_5G_TARGET_PWRS; | ||
1476 | ctpres = ar->power_5G_leg; | ||
1477 | break; | ||
1478 | case 1: /* 2.4 GHz CCK */ | ||
1479 | ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; | ||
1480 | ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; | ||
1481 | ctpres = ar->power_2G_cck; | ||
1482 | break; | ||
1483 | case 2: /* 2.4 GHz OFDM */ | ||
1484 | ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; | ||
1485 | ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; | ||
1486 | ctpres = ar->power_2G_ofdm; | ||
1487 | break; | ||
1488 | default: | ||
1489 | BUG(); | ||
1490 | } | ||
1491 | |||
1492 | for (n = 0; n < ntargets; n++) { | ||
1493 | if (ctpl[n].freq == 0xff) | ||
1494 | break; | ||
1495 | pwr_freqs[n] = ctpl[n].freq; | ||
1496 | } | ||
1497 | ntargets = n; | ||
1498 | idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); | ||
1499 | for (n = 0; n < 4; n++) | ||
1500 | ctpres[n] = ar9170_interpolate_u8( | ||
1501 | f, | ||
1502 | ctpl[idx + 0].freq, | ||
1503 | ctpl[idx + 0].power[n], | ||
1504 | ctpl[idx + 1].freq, | ||
1505 | ctpl[idx + 1].power[n]); | ||
1506 | } | ||
1507 | |||
1508 | /* | ||
1509 | * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 | ||
1510 | */ | ||
1511 | for (i = 0; i < 4; i++) { | ||
1512 | switch (i) { | ||
1513 | case 0: /* 5 GHz HT 20 */ | ||
1514 | ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; | ||
1515 | ntargets = AR5416_NUM_5G_TARGET_PWRS; | ||
1516 | ctpres = ar->power_5G_ht20; | ||
1517 | break; | ||
1518 | case 1: /* 5 GHz HT 40 */ | ||
1519 | ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; | ||
1520 | ntargets = AR5416_NUM_5G_TARGET_PWRS; | ||
1521 | ctpres = ar->power_5G_ht40; | ||
1522 | break; | ||
1523 | case 2: /* 2.4 GHz HT 20 */ | ||
1524 | ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; | ||
1525 | ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; | ||
1526 | ctpres = ar->power_2G_ht20; | ||
1527 | break; | ||
1528 | case 3: /* 2.4 GHz HT 40 */ | ||
1529 | ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; | ||
1530 | ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; | ||
1531 | ctpres = ar->power_2G_ht40; | ||
1532 | break; | ||
1533 | default: | ||
1534 | BUG(); | ||
1535 | } | ||
1536 | |||
1537 | for (n = 0; n < ntargets; n++) { | ||
1538 | if (ctph[n].freq == 0xff) | ||
1539 | break; | ||
1540 | pwr_freqs[n] = ctph[n].freq; | ||
1541 | } | ||
1542 | ntargets = n; | ||
1543 | idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); | ||
1544 | for (n = 0; n < 8; n++) | ||
1545 | ctpres[n] = ar9170_interpolate_u8( | ||
1546 | f, | ||
1547 | ctph[idx + 0].freq, | ||
1548 | ctph[idx + 0].power[n], | ||
1549 | ctph[idx + 1].freq, | ||
1550 | ctph[idx + 1].power[n]); | ||
1551 | } | ||
1552 | |||
1553 | |||
1554 | /* calc. conformance test limits and apply to ar->power*[] */ | ||
1555 | ar9170_calc_ctl(ar, freq, bw); | ||
1556 | |||
1557 | /* set ACK/CTS TX power */ | ||
1558 | ar9170_regwrite_begin(ar); | ||
1559 | |||
1560 | if (ar->eeprom.tx_mask != 1) | ||
1561 | ackchains = AR9170_TX_PHY_TXCHAIN_2; | ||
1562 | else | ||
1563 | ackchains = AR9170_TX_PHY_TXCHAIN_1; | ||
1564 | |||
1565 | if (freq < 3000) | ||
1566 | ackpower = ar->power_2G_ofdm[0] & 0x3f; | ||
1567 | else | ||
1568 | ackpower = ar->power_5G_leg[0] & 0x3f; | ||
1569 | |||
1570 | ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26); | ||
1571 | ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 | | ||
1572 | ackpower << 21 | ackchains << 27); | ||
1573 | |||
1574 | ar9170_regwrite_finish(); | ||
1575 | return ar9170_regwrite_result(); | ||
1576 | } | ||
1577 | |||
1578 | static int ar9170_calc_noise_dbm(u32 raw_noise) | ||
1579 | { | ||
1580 | if (raw_noise & 0x100) | ||
1581 | return ~((raw_noise & 0x0ff) >> 1); | ||
1582 | else | ||
1583 | return (raw_noise & 0xff) >> 1; | ||
1584 | } | ||
1585 | |||
1586 | int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | ||
1587 | enum ar9170_rf_init_mode rfi, enum ar9170_bw bw) | ||
1588 | { | ||
1589 | const struct ar9170_phy_freq_params *freqpar; | ||
1590 | u32 cmd, tmp, offs; | ||
1591 | __le32 vals[8]; | ||
1592 | int i, err; | ||
1593 | bool bandswitch; | ||
1594 | |||
1595 | /* clear BB heavy clip enable */ | ||
1596 | err = ar9170_write_reg(ar, 0x1c59e0, 0x200); | ||
1597 | if (err) | ||
1598 | return err; | ||
1599 | |||
1600 | /* may be NULL at first setup */ | ||
1601 | if (ar->channel) | ||
1602 | bandswitch = ar->channel->band != channel->band; | ||
1603 | else | ||
1604 | bandswitch = true; | ||
1605 | |||
1606 | /* HW workaround */ | ||
1607 | if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && | ||
1608 | channel->center_freq <= 2417) | ||
1609 | bandswitch = true; | ||
1610 | |||
1611 | err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL); | ||
1612 | if (err) | ||
1613 | return err; | ||
1614 | |||
1615 | if (rfi != AR9170_RFI_NONE || bandswitch) { | ||
1616 | u32 val = 0x400; | ||
1617 | |||
1618 | if (rfi == AR9170_RFI_COLD) | ||
1619 | val = 0x800; | ||
1620 | |||
1621 | /* warm/cold reset BB/ADDA */ | ||
1622 | err = ar9170_write_reg(ar, 0x1d4004, val); | ||
1623 | if (err) | ||
1624 | return err; | ||
1625 | |||
1626 | err = ar9170_write_reg(ar, 0x1d4004, 0x0); | ||
1627 | if (err) | ||
1628 | return err; | ||
1629 | |||
1630 | err = ar9170_init_phy(ar, channel->band); | ||
1631 | if (err) | ||
1632 | return err; | ||
1633 | |||
1634 | err = ar9170_init_rf_banks_0_7(ar, | ||
1635 | channel->band == IEEE80211_BAND_5GHZ); | ||
1636 | if (err) | ||
1637 | return err; | ||
1638 | |||
1639 | cmd = AR9170_CMD_RF_INIT; | ||
1640 | } else { | ||
1641 | cmd = AR9170_CMD_FREQUENCY; | ||
1642 | } | ||
1643 | |||
1644 | err = ar9170_init_rf_bank4_pwr(ar, | ||
1645 | channel->band == IEEE80211_BAND_5GHZ, | ||
1646 | channel->center_freq, bw); | ||
1647 | if (err) | ||
1648 | return err; | ||
1649 | |||
1650 | switch (bw) { | ||
1651 | case AR9170_BW_20: | ||
1652 | tmp = 0x240; | ||
1653 | offs = 0; | ||
1654 | break; | ||
1655 | case AR9170_BW_40_BELOW: | ||
1656 | tmp = 0x2c4; | ||
1657 | offs = 3; | ||
1658 | break; | ||
1659 | case AR9170_BW_40_ABOVE: | ||
1660 | tmp = 0x2d4; | ||
1661 | offs = 1; | ||
1662 | break; | ||
1663 | default: | ||
1664 | BUG(); | ||
1665 | return -ENOSYS; | ||
1666 | } | ||
1667 | |||
1668 | if (ar->eeprom.tx_mask != 1) | ||
1669 | tmp |= 0x100; | ||
1670 | |||
1671 | err = ar9170_write_reg(ar, 0x1c5804, tmp); | ||
1672 | if (err) | ||
1673 | return err; | ||
1674 | |||
1675 | err = ar9170_set_freq_cal_data(ar, channel); | ||
1676 | if (err) | ||
1677 | return err; | ||
1678 | |||
1679 | err = ar9170_set_power_cal(ar, channel->center_freq, bw); | ||
1680 | if (err) | ||
1681 | return err; | ||
1682 | |||
1683 | freqpar = ar9170_get_hw_dyn_params(channel, bw); | ||
1684 | |||
1685 | vals[0] = cpu_to_le32(channel->center_freq * 1000); | ||
1686 | vals[1] = cpu_to_le32(conf_is_ht40(&ar->hw->conf)); | ||
1687 | vals[2] = cpu_to_le32(offs << 2 | 1); | ||
1688 | vals[3] = cpu_to_le32(freqpar->coeff_exp); | ||
1689 | vals[4] = cpu_to_le32(freqpar->coeff_man); | ||
1690 | vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi); | ||
1691 | vals[6] = cpu_to_le32(freqpar->coeff_man_shgi); | ||
1692 | vals[7] = cpu_to_le32(1000); | ||
1693 | |||
1694 | err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals, | ||
1695 | sizeof(vals), (u8 *)vals); | ||
1696 | if (err) | ||
1697 | return err; | ||
1698 | |||
1699 | if (ar->phy_heavy_clip) { | ||
1700 | err = ar9170_write_reg(ar, 0x1c59e0, | ||
1701 | 0x200 | ar->phy_heavy_clip); | ||
1702 | if (err) { | ||
1703 | if (ar9170_nag_limiter(ar)) | ||
1704 | wiphy_err(ar->hw->wiphy, | ||
1705 | "failed to set heavy clip\n"); | ||
1706 | } | ||
1707 | } | ||
1708 | |||
1709 | for (i = 0; i < 2; i++) { | ||
1710 | ar->noise[i] = ar9170_calc_noise_dbm( | ||
1711 | (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); | ||
1712 | |||
1713 | ar->noise[i + 2] = ar9170_calc_noise_dbm( | ||
1714 | (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff); | ||
1715 | } | ||
1716 | |||
1717 | ar->channel = channel; | ||
1718 | return 0; | ||
1719 | } | ||
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c deleted file mode 100644 index d3be6f9816b5..000000000000 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ /dev/null | |||
@@ -1,1008 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 driver | ||
3 | * | ||
4 | * USB - frontend | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, Christian Lamparter <chunkeey@web.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/module.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/usb.h> | ||
43 | #include <linux/firmware.h> | ||
44 | #include <linux/etherdevice.h> | ||
45 | #include <linux/device.h> | ||
46 | #include <net/mac80211.h> | ||
47 | #include "ar9170.h" | ||
48 | #include "cmd.h" | ||
49 | #include "hw.h" | ||
50 | #include "usb.h" | ||
51 | |||
52 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
53 | MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>"); | ||
54 | MODULE_LICENSE("GPL"); | ||
55 | MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); | ||
56 | MODULE_FIRMWARE("ar9170.fw"); | ||
57 | |||
58 | enum ar9170_requirements { | ||
59 | AR9170_REQ_FW1_ONLY = 1, | ||
60 | }; | ||
61 | |||
62 | static struct usb_device_id ar9170_usb_ids[] = { | ||
63 | /* Atheros 9170 */ | ||
64 | { USB_DEVICE(0x0cf3, 0x9170) }, | ||
65 | /* Atheros TG121N */ | ||
66 | { USB_DEVICE(0x0cf3, 0x1001) }, | ||
67 | /* TP-Link TL-WN821N v2 */ | ||
68 | { USB_DEVICE(0x0cf3, 0x1002) }, | ||
69 | /* 3Com Dual Band 802.11n USB Adapter */ | ||
70 | { USB_DEVICE(0x0cf3, 0x1010) }, | ||
71 | /* H3C Dual Band 802.11n USB Adapter */ | ||
72 | { USB_DEVICE(0x0cf3, 0x1011) }, | ||
73 | /* Cace Airpcap NX */ | ||
74 | { USB_DEVICE(0xcace, 0x0300) }, | ||
75 | /* D-Link DWA 160 A1 */ | ||
76 | { USB_DEVICE(0x07d1, 0x3c10) }, | ||
77 | /* D-Link DWA 160 A2 */ | ||
78 | { USB_DEVICE(0x07d1, 0x3a09) }, | ||
79 | /* Netgear WNA1000 */ | ||
80 | { USB_DEVICE(0x0846, 0x9040) }, | ||
81 | /* Netgear WNDA3100 */ | ||
82 | { USB_DEVICE(0x0846, 0x9010) }, | ||
83 | /* Netgear WN111 v2 */ | ||
84 | { USB_DEVICE(0x0846, 0x9001) }, | ||
85 | /* Zydas ZD1221 */ | ||
86 | { USB_DEVICE(0x0ace, 0x1221) }, | ||
87 | /* Proxim ORiNOCO 802.11n USB */ | ||
88 | { USB_DEVICE(0x1435, 0x0804) }, | ||
89 | /* WNC Generic 11n USB Dongle */ | ||
90 | { USB_DEVICE(0x1435, 0x0326) }, | ||
91 | /* ZyXEL NWD271N */ | ||
92 | { USB_DEVICE(0x0586, 0x3417) }, | ||
93 | /* Z-Com UB81 BG */ | ||
94 | { USB_DEVICE(0x0cde, 0x0023) }, | ||
95 | /* Z-Com UB82 ABG */ | ||
96 | { USB_DEVICE(0x0cde, 0x0026) }, | ||
97 | /* Sphairon Homelink 1202 */ | ||
98 | { USB_DEVICE(0x0cde, 0x0027) }, | ||
99 | /* Arcadyan WN7512 */ | ||
100 | { USB_DEVICE(0x083a, 0xf522) }, | ||
101 | /* Planex GWUS300 */ | ||
102 | { USB_DEVICE(0x2019, 0x5304) }, | ||
103 | /* IO-Data WNGDNUS2 */ | ||
104 | { USB_DEVICE(0x04bb, 0x093f) }, | ||
105 | /* AVM FRITZ!WLAN USB Stick N */ | ||
106 | { USB_DEVICE(0x057C, 0x8401) }, | ||
107 | /* NEC WL300NU-G */ | ||
108 | { USB_DEVICE(0x0409, 0x0249) }, | ||
109 | /* AVM FRITZ!WLAN USB Stick N 2.4 */ | ||
110 | { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, | ||
111 | /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */ | ||
112 | { USB_DEVICE(0x1668, 0x1200) }, | ||
113 | |||
114 | /* terminate */ | ||
115 | {} | ||
116 | }; | ||
117 | MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); | ||
118 | |||
119 | static void ar9170_usb_submit_urb(struct ar9170_usb *aru) | ||
120 | { | ||
121 | struct urb *urb; | ||
122 | unsigned long flags; | ||
123 | int err; | ||
124 | |||
125 | if (unlikely(!IS_STARTED(&aru->common))) | ||
126 | return ; | ||
127 | |||
128 | spin_lock_irqsave(&aru->tx_urb_lock, flags); | ||
129 | if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) { | ||
130 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | ||
131 | return ; | ||
132 | } | ||
133 | atomic_inc(&aru->tx_submitted_urbs); | ||
134 | |||
135 | urb = usb_get_from_anchor(&aru->tx_pending); | ||
136 | if (!urb) { | ||
137 | atomic_dec(&aru->tx_submitted_urbs); | ||
138 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | ||
139 | |||
140 | return ; | ||
141 | } | ||
142 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | ||
143 | |||
144 | aru->tx_pending_urbs--; | ||
145 | usb_anchor_urb(urb, &aru->tx_submitted); | ||
146 | |||
147 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
148 | if (unlikely(err)) { | ||
149 | if (ar9170_nag_limiter(&aru->common)) | ||
150 | dev_err(&aru->udev->dev, "submit_urb failed (%d).\n", | ||
151 | err); | ||
152 | |||
153 | usb_unanchor_urb(urb); | ||
154 | atomic_dec(&aru->tx_submitted_urbs); | ||
155 | ar9170_tx_callback(&aru->common, urb->context); | ||
156 | } | ||
157 | |||
158 | usb_free_urb(urb); | ||
159 | } | ||
160 | |||
161 | static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) | ||
162 | { | ||
163 | struct sk_buff *skb = urb->context; | ||
164 | struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | ||
165 | |||
166 | if (unlikely(!aru)) { | ||
167 | dev_kfree_skb_irq(skb); | ||
168 | return ; | ||
169 | } | ||
170 | |||
171 | atomic_dec(&aru->tx_submitted_urbs); | ||
172 | |||
173 | ar9170_tx_callback(&aru->common, skb); | ||
174 | |||
175 | ar9170_usb_submit_urb(aru); | ||
176 | } | ||
177 | |||
178 | static void ar9170_usb_tx_urb_complete(struct urb *urb) | ||
179 | { | ||
180 | } | ||
181 | |||
182 | static void ar9170_usb_irq_completed(struct urb *urb) | ||
183 | { | ||
184 | struct ar9170_usb *aru = urb->context; | ||
185 | |||
186 | switch (urb->status) { | ||
187 | /* everything is fine */ | ||
188 | case 0: | ||
189 | break; | ||
190 | |||
191 | /* disconnect */ | ||
192 | case -ENOENT: | ||
193 | case -ECONNRESET: | ||
194 | case -ENODEV: | ||
195 | case -ESHUTDOWN: | ||
196 | goto free; | ||
197 | |||
198 | default: | ||
199 | goto resubmit; | ||
200 | } | ||
201 | |||
202 | ar9170_handle_command_response(&aru->common, urb->transfer_buffer, | ||
203 | urb->actual_length); | ||
204 | |||
205 | resubmit: | ||
206 | usb_anchor_urb(urb, &aru->rx_submitted); | ||
207 | if (usb_submit_urb(urb, GFP_ATOMIC)) { | ||
208 | usb_unanchor_urb(urb); | ||
209 | goto free; | ||
210 | } | ||
211 | |||
212 | return; | ||
213 | |||
214 | free: | ||
215 | usb_free_coherent(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); | ||
216 | } | ||
217 | |||
218 | static void ar9170_usb_rx_completed(struct urb *urb) | ||
219 | { | ||
220 | struct sk_buff *skb = urb->context; | ||
221 | struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | ||
222 | int err; | ||
223 | |||
224 | if (!aru) | ||
225 | goto free; | ||
226 | |||
227 | switch (urb->status) { | ||
228 | /* everything is fine */ | ||
229 | case 0: | ||
230 | break; | ||
231 | |||
232 | /* disconnect */ | ||
233 | case -ENOENT: | ||
234 | case -ECONNRESET: | ||
235 | case -ENODEV: | ||
236 | case -ESHUTDOWN: | ||
237 | goto free; | ||
238 | |||
239 | default: | ||
240 | goto resubmit; | ||
241 | } | ||
242 | |||
243 | skb_put(skb, urb->actual_length); | ||
244 | ar9170_rx(&aru->common, skb); | ||
245 | |||
246 | resubmit: | ||
247 | skb_reset_tail_pointer(skb); | ||
248 | skb_trim(skb, 0); | ||
249 | |||
250 | usb_anchor_urb(urb, &aru->rx_submitted); | ||
251 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
252 | if (unlikely(err)) { | ||
253 | usb_unanchor_urb(urb); | ||
254 | goto free; | ||
255 | } | ||
256 | |||
257 | return ; | ||
258 | |||
259 | free: | ||
260 | dev_kfree_skb_irq(skb); | ||
261 | } | ||
262 | |||
263 | static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, | ||
264 | struct urb *urb, gfp_t gfp) | ||
265 | { | ||
266 | struct sk_buff *skb; | ||
267 | |||
268 | skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp); | ||
269 | if (!skb) | ||
270 | return -ENOMEM; | ||
271 | |||
272 | /* reserve some space for mac80211's radiotap */ | ||
273 | skb_reserve(skb, 32); | ||
274 | |||
275 | usb_fill_bulk_urb(urb, aru->udev, | ||
276 | usb_rcvbulkpipe(aru->udev, AR9170_EP_RX), | ||
277 | skb->data, min(skb_tailroom(skb), | ||
278 | AR9170_MAX_RX_BUFFER_SIZE), | ||
279 | ar9170_usb_rx_completed, skb); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) | ||
285 | { | ||
286 | struct urb *urb = NULL; | ||
287 | void *ibuf; | ||
288 | int err = -ENOMEM; | ||
289 | |||
290 | /* initialize interrupt endpoint */ | ||
291 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
292 | if (!urb) | ||
293 | goto out; | ||
294 | |||
295 | ibuf = usb_alloc_coherent(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); | ||
296 | if (!ibuf) | ||
297 | goto out; | ||
298 | |||
299 | usb_fill_int_urb(urb, aru->udev, | ||
300 | usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf, | ||
301 | 64, ar9170_usb_irq_completed, aru, 1); | ||
302 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
303 | |||
304 | usb_anchor_urb(urb, &aru->rx_submitted); | ||
305 | err = usb_submit_urb(urb, GFP_KERNEL); | ||
306 | if (err) { | ||
307 | usb_unanchor_urb(urb); | ||
308 | usb_free_coherent(aru->udev, 64, urb->transfer_buffer, | ||
309 | urb->transfer_dma); | ||
310 | } | ||
311 | |||
312 | out: | ||
313 | usb_free_urb(urb); | ||
314 | return err; | ||
315 | } | ||
316 | |||
317 | static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) | ||
318 | { | ||
319 | struct urb *urb; | ||
320 | int i; | ||
321 | int err = -EINVAL; | ||
322 | |||
323 | for (i = 0; i < AR9170_NUM_RX_URBS; i++) { | ||
324 | err = -ENOMEM; | ||
325 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
326 | if (!urb) | ||
327 | goto err_out; | ||
328 | |||
329 | err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL); | ||
330 | if (err) { | ||
331 | usb_free_urb(urb); | ||
332 | goto err_out; | ||
333 | } | ||
334 | |||
335 | usb_anchor_urb(urb, &aru->rx_submitted); | ||
336 | err = usb_submit_urb(urb, GFP_KERNEL); | ||
337 | if (err) { | ||
338 | usb_unanchor_urb(urb); | ||
339 | dev_kfree_skb_any((void *) urb->transfer_buffer); | ||
340 | usb_free_urb(urb); | ||
341 | goto err_out; | ||
342 | } | ||
343 | usb_free_urb(urb); | ||
344 | } | ||
345 | |||
346 | /* the device now waiting for a firmware. */ | ||
347 | aru->common.state = AR9170_IDLE; | ||
348 | return 0; | ||
349 | |||
350 | err_out: | ||
351 | |||
352 | usb_kill_anchored_urbs(&aru->rx_submitted); | ||
353 | return err; | ||
354 | } | ||
355 | |||
356 | static int ar9170_usb_flush(struct ar9170 *ar) | ||
357 | { | ||
358 | struct ar9170_usb *aru = (void *) ar; | ||
359 | struct urb *urb; | ||
360 | int ret, err = 0; | ||
361 | |||
362 | if (IS_STARTED(ar)) | ||
363 | aru->common.state = AR9170_IDLE; | ||
364 | |||
365 | usb_wait_anchor_empty_timeout(&aru->tx_pending, | ||
366 | msecs_to_jiffies(800)); | ||
367 | while ((urb = usb_get_from_anchor(&aru->tx_pending))) { | ||
368 | ar9170_tx_callback(&aru->common, (void *) urb->context); | ||
369 | usb_free_urb(urb); | ||
370 | } | ||
371 | |||
372 | /* lets wait a while until the tx - queues are dried out */ | ||
373 | ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, | ||
374 | msecs_to_jiffies(100)); | ||
375 | if (ret == 0) | ||
376 | err = -ETIMEDOUT; | ||
377 | |||
378 | usb_kill_anchored_urbs(&aru->tx_submitted); | ||
379 | |||
380 | if (IS_ACCEPTING_CMD(ar)) | ||
381 | aru->common.state = AR9170_STARTED; | ||
382 | |||
383 | return err; | ||
384 | } | ||
385 | |||
386 | static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) | ||
387 | { | ||
388 | int err; | ||
389 | |||
390 | aru->common.state = AR9170_UNKNOWN_STATE; | ||
391 | |||
392 | err = ar9170_usb_flush(&aru->common); | ||
393 | if (err) | ||
394 | dev_err(&aru->udev->dev, "stuck tx urbs!\n"); | ||
395 | |||
396 | usb_poison_anchored_urbs(&aru->tx_submitted); | ||
397 | usb_poison_anchored_urbs(&aru->rx_submitted); | ||
398 | } | ||
399 | |||
400 | static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, | ||
401 | unsigned int plen, void *payload, | ||
402 | unsigned int outlen, void *out) | ||
403 | { | ||
404 | struct ar9170_usb *aru = (void *) ar; | ||
405 | struct urb *urb = NULL; | ||
406 | unsigned long flags; | ||
407 | int err = -ENOMEM; | ||
408 | |||
409 | if (unlikely(!IS_ACCEPTING_CMD(ar))) | ||
410 | return -EPERM; | ||
411 | |||
412 | if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4)) | ||
413 | return -EINVAL; | ||
414 | |||
415 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
416 | if (unlikely(!urb)) | ||
417 | goto err_free; | ||
418 | |||
419 | ar->cmdbuf[0] = cpu_to_le32(plen); | ||
420 | ar->cmdbuf[0] |= cpu_to_le32(cmd << 8); | ||
421 | /* writing multiple regs fills this buffer already */ | ||
422 | if (plen && payload != (u8 *)(&ar->cmdbuf[1])) | ||
423 | memcpy(&ar->cmdbuf[1], payload, plen); | ||
424 | |||
425 | spin_lock_irqsave(&aru->common.cmdlock, flags); | ||
426 | aru->readbuf = (u8 *)out; | ||
427 | aru->readlen = outlen; | ||
428 | spin_unlock_irqrestore(&aru->common.cmdlock, flags); | ||
429 | |||
430 | usb_fill_int_urb(urb, aru->udev, | ||
431 | usb_sndintpipe(aru->udev, AR9170_EP_CMD), | ||
432 | aru->common.cmdbuf, plen + 4, | ||
433 | ar9170_usb_tx_urb_complete, NULL, 1); | ||
434 | |||
435 | usb_anchor_urb(urb, &aru->tx_submitted); | ||
436 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
437 | if (unlikely(err)) { | ||
438 | usb_unanchor_urb(urb); | ||
439 | usb_free_urb(urb); | ||
440 | goto err_unbuf; | ||
441 | } | ||
442 | usb_free_urb(urb); | ||
443 | |||
444 | err = wait_for_completion_timeout(&aru->cmd_wait, HZ); | ||
445 | if (err == 0) { | ||
446 | err = -ETIMEDOUT; | ||
447 | goto err_unbuf; | ||
448 | } | ||
449 | |||
450 | if (aru->readlen != outlen) { | ||
451 | err = -EMSGSIZE; | ||
452 | goto err_unbuf; | ||
453 | } | ||
454 | |||
455 | return 0; | ||
456 | |||
457 | err_unbuf: | ||
458 | /* Maybe the device was removed in the second we were waiting? */ | ||
459 | if (IS_STARTED(ar)) { | ||
460 | dev_err(&aru->udev->dev, "no command feedback " | ||
461 | "received (%d).\n", err); | ||
462 | |||
463 | /* provide some maybe useful debug information */ | ||
464 | print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE, | ||
465 | aru->common.cmdbuf, plen + 4); | ||
466 | dump_stack(); | ||
467 | } | ||
468 | |||
469 | /* invalidate to avoid completing the next prematurely */ | ||
470 | spin_lock_irqsave(&aru->common.cmdlock, flags); | ||
471 | aru->readbuf = NULL; | ||
472 | aru->readlen = 0; | ||
473 | spin_unlock_irqrestore(&aru->common.cmdlock, flags); | ||
474 | |||
475 | err_free: | ||
476 | |||
477 | return err; | ||
478 | } | ||
479 | |||
480 | static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) | ||
481 | { | ||
482 | struct ar9170_usb *aru = (struct ar9170_usb *) ar; | ||
483 | struct urb *urb; | ||
484 | |||
485 | if (unlikely(!IS_STARTED(ar))) { | ||
486 | /* Seriously, what were you drink... err... thinking!? */ | ||
487 | return -EPERM; | ||
488 | } | ||
489 | |||
490 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
491 | if (unlikely(!urb)) | ||
492 | return -ENOMEM; | ||
493 | |||
494 | usb_fill_bulk_urb(urb, aru->udev, | ||
495 | usb_sndbulkpipe(aru->udev, AR9170_EP_TX), | ||
496 | skb->data, skb->len, | ||
497 | ar9170_usb_tx_urb_complete_frame, skb); | ||
498 | urb->transfer_flags |= URB_ZERO_PACKET; | ||
499 | |||
500 | usb_anchor_urb(urb, &aru->tx_pending); | ||
501 | aru->tx_pending_urbs++; | ||
502 | |||
503 | usb_free_urb(urb); | ||
504 | |||
505 | ar9170_usb_submit_urb(aru); | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) | ||
510 | { | ||
511 | struct ar9170_usb *aru = (void *) ar; | ||
512 | unsigned long flags; | ||
513 | u32 in, out; | ||
514 | |||
515 | if (unlikely(!buffer)) | ||
516 | return ; | ||
517 | |||
518 | in = le32_to_cpup((__le32 *)buffer); | ||
519 | out = le32_to_cpu(ar->cmdbuf[0]); | ||
520 | |||
521 | /* mask off length byte */ | ||
522 | out &= ~0xFF; | ||
523 | |||
524 | if (aru->readlen >= 0) { | ||
525 | /* add expected length */ | ||
526 | out |= aru->readlen; | ||
527 | } else { | ||
528 | /* add obtained length */ | ||
529 | out |= in & 0xFF; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response | ||
534 | * length and we cannot predict the correct length in advance. | ||
535 | * So we only check if we provided enough space for the data. | ||
536 | */ | ||
537 | if (unlikely(out < in)) { | ||
538 | dev_warn(&aru->udev->dev, "received invalid command response " | ||
539 | "got %d bytes, instead of %d bytes " | ||
540 | "and the resp length is %d bytes\n", | ||
541 | in, out, len); | ||
542 | print_hex_dump_bytes("ar9170 invalid resp: ", | ||
543 | DUMP_PREFIX_OFFSET, buffer, len); | ||
544 | /* | ||
545 | * Do not complete, then the command times out, | ||
546 | * and we get a stack trace from there. | ||
547 | */ | ||
548 | return ; | ||
549 | } | ||
550 | |||
551 | spin_lock_irqsave(&aru->common.cmdlock, flags); | ||
552 | if (aru->readbuf && len > 0) { | ||
553 | memcpy(aru->readbuf, buffer + 4, len - 4); | ||
554 | aru->readbuf = NULL; | ||
555 | } | ||
556 | complete(&aru->cmd_wait); | ||
557 | spin_unlock_irqrestore(&aru->common.cmdlock, flags); | ||
558 | } | ||
559 | |||
560 | static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, | ||
561 | size_t len, u32 addr, bool complete) | ||
562 | { | ||
563 | int transfer, err; | ||
564 | u8 *buf = kmalloc(4096, GFP_KERNEL); | ||
565 | |||
566 | if (!buf) | ||
567 | return -ENOMEM; | ||
568 | |||
569 | while (len) { | ||
570 | transfer = min_t(int, len, 4096); | ||
571 | memcpy(buf, data, transfer); | ||
572 | |||
573 | err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), | ||
574 | 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, | ||
575 | addr >> 8, 0, buf, transfer, 1000); | ||
576 | |||
577 | if (err < 0) { | ||
578 | kfree(buf); | ||
579 | return err; | ||
580 | } | ||
581 | |||
582 | len -= transfer; | ||
583 | data += transfer; | ||
584 | addr += transfer; | ||
585 | } | ||
586 | kfree(buf); | ||
587 | |||
588 | if (complete) { | ||
589 | err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), | ||
590 | 0x31 /* FW DL COMPLETE */, | ||
591 | 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000); | ||
592 | } | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | static int ar9170_usb_reset(struct ar9170_usb *aru) | ||
598 | { | ||
599 | int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); | ||
600 | |||
601 | if (lock) { | ||
602 | ret = usb_lock_device_for_reset(aru->udev, aru->intf); | ||
603 | if (ret < 0) { | ||
604 | dev_err(&aru->udev->dev, "unable to lock device " | ||
605 | "for reset (%d).\n", ret); | ||
606 | return ret; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | ret = usb_reset_device(aru->udev); | ||
611 | if (lock) | ||
612 | usb_unlock_device(aru->udev); | ||
613 | |||
614 | /* let it rest - for a second - */ | ||
615 | msleep(1000); | ||
616 | |||
617 | return ret; | ||
618 | } | ||
619 | |||
620 | static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) | ||
621 | { | ||
622 | int err; | ||
623 | |||
624 | if (!aru->init_values) | ||
625 | goto upload_fw_start; | ||
626 | |||
627 | /* First, upload initial values to device RAM */ | ||
628 | err = ar9170_usb_upload(aru, aru->init_values->data, | ||
629 | aru->init_values->size, 0x102800, false); | ||
630 | if (err) { | ||
631 | dev_err(&aru->udev->dev, "firmware part 1 " | ||
632 | "upload failed (%d).\n", err); | ||
633 | return err; | ||
634 | } | ||
635 | |||
636 | upload_fw_start: | ||
637 | |||
638 | /* Then, upload the firmware itself and start it */ | ||
639 | return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, | ||
640 | 0x200000, true); | ||
641 | } | ||
642 | |||
643 | static int ar9170_usb_init_transport(struct ar9170_usb *aru) | ||
644 | { | ||
645 | struct ar9170 *ar = (void *) &aru->common; | ||
646 | int err; | ||
647 | |||
648 | ar9170_regwrite_begin(ar); | ||
649 | |||
650 | /* Set USB Rx stream mode MAX packet number to 2 */ | ||
651 | ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4); | ||
652 | |||
653 | /* Set USB Rx stream mode timeout to 10us */ | ||
654 | ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); | ||
655 | |||
656 | ar9170_regwrite_finish(); | ||
657 | |||
658 | err = ar9170_regwrite_result(); | ||
659 | if (err) | ||
660 | dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err); | ||
661 | |||
662 | return err; | ||
663 | } | ||
664 | |||
665 | static void ar9170_usb_stop(struct ar9170 *ar) | ||
666 | { | ||
667 | struct ar9170_usb *aru = (void *) ar; | ||
668 | int ret; | ||
669 | |||
670 | if (IS_ACCEPTING_CMD(ar)) | ||
671 | aru->common.state = AR9170_STOPPED; | ||
672 | |||
673 | ret = ar9170_usb_flush(ar); | ||
674 | if (ret) | ||
675 | dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); | ||
676 | |||
677 | usb_poison_anchored_urbs(&aru->tx_submitted); | ||
678 | |||
679 | /* | ||
680 | * Note: | ||
681 | * So far we freed all tx urbs, but we won't dare to touch any rx urbs. | ||
682 | * Else we would end up with a unresponsive device... | ||
683 | */ | ||
684 | } | ||
685 | |||
686 | static int ar9170_usb_open(struct ar9170 *ar) | ||
687 | { | ||
688 | struct ar9170_usb *aru = (void *) ar; | ||
689 | int err; | ||
690 | |||
691 | usb_unpoison_anchored_urbs(&aru->tx_submitted); | ||
692 | err = ar9170_usb_init_transport(aru); | ||
693 | if (err) { | ||
694 | usb_poison_anchored_urbs(&aru->tx_submitted); | ||
695 | return err; | ||
696 | } | ||
697 | |||
698 | aru->common.state = AR9170_IDLE; | ||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | static int ar9170_usb_init_device(struct ar9170_usb *aru) | ||
703 | { | ||
704 | int err; | ||
705 | |||
706 | err = ar9170_usb_alloc_rx_irq_urb(aru); | ||
707 | if (err) | ||
708 | goto err_out; | ||
709 | |||
710 | err = ar9170_usb_alloc_rx_bulk_urbs(aru); | ||
711 | if (err) | ||
712 | goto err_unrx; | ||
713 | |||
714 | err = ar9170_usb_upload_firmware(aru); | ||
715 | if (err) { | ||
716 | err = ar9170_echo_test(&aru->common, 0x60d43110); | ||
717 | if (err) { | ||
718 | /* force user invention, by disabling the device */ | ||
719 | err = usb_driver_set_configuration(aru->udev, -1); | ||
720 | dev_err(&aru->udev->dev, "device is in a bad state. " | ||
721 | "please reconnect it!\n"); | ||
722 | goto err_unrx; | ||
723 | } | ||
724 | } | ||
725 | |||
726 | return 0; | ||
727 | |||
728 | err_unrx: | ||
729 | ar9170_usb_cancel_urbs(aru); | ||
730 | |||
731 | err_out: | ||
732 | return err; | ||
733 | } | ||
734 | |||
735 | static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) | ||
736 | { | ||
737 | struct device *parent = aru->udev->dev.parent; | ||
738 | struct usb_device *udev; | ||
739 | |||
740 | /* | ||
741 | * Store a copy of the usb_device pointer locally. | ||
742 | * This is because device_release_driver initiates | ||
743 | * ar9170_usb_disconnect, which in turn frees our | ||
744 | * driver context (aru). | ||
745 | */ | ||
746 | udev = aru->udev; | ||
747 | |||
748 | complete(&aru->firmware_loading_complete); | ||
749 | |||
750 | /* unbind anything failed */ | ||
751 | if (parent) | ||
752 | device_lock(parent); | ||
753 | |||
754 | device_release_driver(&udev->dev); | ||
755 | if (parent) | ||
756 | device_unlock(parent); | ||
757 | |||
758 | usb_put_dev(udev); | ||
759 | } | ||
760 | |||
761 | static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) | ||
762 | { | ||
763 | struct ar9170_usb *aru = context; | ||
764 | int err; | ||
765 | |||
766 | aru->firmware = fw; | ||
767 | |||
768 | if (!fw) { | ||
769 | dev_err(&aru->udev->dev, "firmware file not found.\n"); | ||
770 | goto err_freefw; | ||
771 | } | ||
772 | |||
773 | err = ar9170_usb_init_device(aru); | ||
774 | if (err) | ||
775 | goto err_freefw; | ||
776 | |||
777 | err = ar9170_usb_open(&aru->common); | ||
778 | if (err) | ||
779 | goto err_unrx; | ||
780 | |||
781 | err = ar9170_register(&aru->common, &aru->udev->dev); | ||
782 | |||
783 | ar9170_usb_stop(&aru->common); | ||
784 | if (err) | ||
785 | goto err_unrx; | ||
786 | |||
787 | complete(&aru->firmware_loading_complete); | ||
788 | usb_put_dev(aru->udev); | ||
789 | return; | ||
790 | |||
791 | err_unrx: | ||
792 | ar9170_usb_cancel_urbs(aru); | ||
793 | |||
794 | err_freefw: | ||
795 | ar9170_usb_firmware_failed(aru); | ||
796 | } | ||
797 | |||
798 | static void ar9170_usb_firmware_inits(const struct firmware *fw, | ||
799 | void *context) | ||
800 | { | ||
801 | struct ar9170_usb *aru = context; | ||
802 | int err; | ||
803 | |||
804 | if (!fw) { | ||
805 | dev_err(&aru->udev->dev, "file with init values not found.\n"); | ||
806 | ar9170_usb_firmware_failed(aru); | ||
807 | return; | ||
808 | } | ||
809 | |||
810 | aru->init_values = fw; | ||
811 | |||
812 | /* ok so we have the init values -- get code for two-stage */ | ||
813 | |||
814 | err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", | ||
815 | &aru->udev->dev, GFP_KERNEL, aru, | ||
816 | ar9170_usb_firmware_finish); | ||
817 | if (err) | ||
818 | ar9170_usb_firmware_failed(aru); | ||
819 | } | ||
820 | |||
821 | static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) | ||
822 | { | ||
823 | struct ar9170_usb *aru = context; | ||
824 | int err; | ||
825 | |||
826 | if (fw) { | ||
827 | ar9170_usb_firmware_finish(fw, context); | ||
828 | return; | ||
829 | } | ||
830 | |||
831 | if (aru->req_one_stage_fw) { | ||
832 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
833 | "not found and is required for this device\n"); | ||
834 | ar9170_usb_firmware_failed(aru); | ||
835 | return; | ||
836 | } | ||
837 | |||
838 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
839 | "not found, trying old firmware...\n"); | ||
840 | |||
841 | err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", | ||
842 | &aru->udev->dev, GFP_KERNEL, aru, | ||
843 | ar9170_usb_firmware_inits); | ||
844 | if (err) | ||
845 | ar9170_usb_firmware_failed(aru); | ||
846 | } | ||
847 | |||
848 | static bool ar9170_requires_one_stage(const struct usb_device_id *id) | ||
849 | { | ||
850 | if (!id->driver_info) | ||
851 | return false; | ||
852 | if (id->driver_info == AR9170_REQ_FW1_ONLY) | ||
853 | return true; | ||
854 | return false; | ||
855 | } | ||
856 | |||
857 | static int ar9170_usb_probe(struct usb_interface *intf, | ||
858 | const struct usb_device_id *id) | ||
859 | { | ||
860 | struct ar9170_usb *aru; | ||
861 | struct ar9170 *ar; | ||
862 | struct usb_device *udev; | ||
863 | int err; | ||
864 | |||
865 | aru = ar9170_alloc(sizeof(*aru)); | ||
866 | if (IS_ERR(aru)) { | ||
867 | err = PTR_ERR(aru); | ||
868 | goto out; | ||
869 | } | ||
870 | |||
871 | udev = interface_to_usbdev(intf); | ||
872 | usb_get_dev(udev); | ||
873 | aru->udev = udev; | ||
874 | aru->intf = intf; | ||
875 | ar = &aru->common; | ||
876 | |||
877 | aru->req_one_stage_fw = ar9170_requires_one_stage(id); | ||
878 | |||
879 | usb_set_intfdata(intf, aru); | ||
880 | SET_IEEE80211_DEV(ar->hw, &intf->dev); | ||
881 | |||
882 | init_usb_anchor(&aru->rx_submitted); | ||
883 | init_usb_anchor(&aru->tx_pending); | ||
884 | init_usb_anchor(&aru->tx_submitted); | ||
885 | init_completion(&aru->cmd_wait); | ||
886 | init_completion(&aru->firmware_loading_complete); | ||
887 | spin_lock_init(&aru->tx_urb_lock); | ||
888 | |||
889 | aru->tx_pending_urbs = 0; | ||
890 | atomic_set(&aru->tx_submitted_urbs, 0); | ||
891 | |||
892 | aru->common.stop = ar9170_usb_stop; | ||
893 | aru->common.flush = ar9170_usb_flush; | ||
894 | aru->common.open = ar9170_usb_open; | ||
895 | aru->common.tx = ar9170_usb_tx; | ||
896 | aru->common.exec_cmd = ar9170_usb_exec_cmd; | ||
897 | aru->common.callback_cmd = ar9170_usb_callback_cmd; | ||
898 | |||
899 | #ifdef CONFIG_PM | ||
900 | udev->reset_resume = 1; | ||
901 | #endif /* CONFIG_PM */ | ||
902 | err = ar9170_usb_reset(aru); | ||
903 | if (err) | ||
904 | goto err_freehw; | ||
905 | |||
906 | usb_get_dev(aru->udev); | ||
907 | return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", | ||
908 | &aru->udev->dev, GFP_KERNEL, aru, | ||
909 | ar9170_usb_firmware_step2); | ||
910 | err_freehw: | ||
911 | usb_set_intfdata(intf, NULL); | ||
912 | usb_put_dev(udev); | ||
913 | ieee80211_free_hw(ar->hw); | ||
914 | out: | ||
915 | return err; | ||
916 | } | ||
917 | |||
918 | static void ar9170_usb_disconnect(struct usb_interface *intf) | ||
919 | { | ||
920 | struct ar9170_usb *aru = usb_get_intfdata(intf); | ||
921 | |||
922 | if (!aru) | ||
923 | return; | ||
924 | |||
925 | aru->common.state = AR9170_IDLE; | ||
926 | |||
927 | wait_for_completion(&aru->firmware_loading_complete); | ||
928 | |||
929 | ar9170_unregister(&aru->common); | ||
930 | ar9170_usb_cancel_urbs(aru); | ||
931 | |||
932 | usb_put_dev(aru->udev); | ||
933 | usb_set_intfdata(intf, NULL); | ||
934 | ieee80211_free_hw(aru->common.hw); | ||
935 | |||
936 | release_firmware(aru->init_values); | ||
937 | release_firmware(aru->firmware); | ||
938 | } | ||
939 | |||
940 | #ifdef CONFIG_PM | ||
941 | static int ar9170_suspend(struct usb_interface *intf, | ||
942 | pm_message_t message) | ||
943 | { | ||
944 | struct ar9170_usb *aru = usb_get_intfdata(intf); | ||
945 | |||
946 | if (!aru) | ||
947 | return -ENODEV; | ||
948 | |||
949 | aru->common.state = AR9170_IDLE; | ||
950 | ar9170_usb_cancel_urbs(aru); | ||
951 | |||
952 | return 0; | ||
953 | } | ||
954 | |||
955 | static int ar9170_resume(struct usb_interface *intf) | ||
956 | { | ||
957 | struct ar9170_usb *aru = usb_get_intfdata(intf); | ||
958 | int err; | ||
959 | |||
960 | if (!aru) | ||
961 | return -ENODEV; | ||
962 | |||
963 | usb_unpoison_anchored_urbs(&aru->rx_submitted); | ||
964 | usb_unpoison_anchored_urbs(&aru->tx_submitted); | ||
965 | |||
966 | err = ar9170_usb_init_device(aru); | ||
967 | if (err) | ||
968 | goto err_unrx; | ||
969 | |||
970 | err = ar9170_usb_open(&aru->common); | ||
971 | if (err) | ||
972 | goto err_unrx; | ||
973 | |||
974 | return 0; | ||
975 | |||
976 | err_unrx: | ||
977 | aru->common.state = AR9170_IDLE; | ||
978 | ar9170_usb_cancel_urbs(aru); | ||
979 | |||
980 | return err; | ||
981 | } | ||
982 | #endif /* CONFIG_PM */ | ||
983 | |||
984 | static struct usb_driver ar9170_driver = { | ||
985 | .name = "ar9170usb", | ||
986 | .probe = ar9170_usb_probe, | ||
987 | .disconnect = ar9170_usb_disconnect, | ||
988 | .id_table = ar9170_usb_ids, | ||
989 | .soft_unbind = 1, | ||
990 | #ifdef CONFIG_PM | ||
991 | .suspend = ar9170_suspend, | ||
992 | .resume = ar9170_resume, | ||
993 | .reset_resume = ar9170_resume, | ||
994 | #endif /* CONFIG_PM */ | ||
995 | }; | ||
996 | |||
997 | static int __init ar9170_init(void) | ||
998 | { | ||
999 | return usb_register(&ar9170_driver); | ||
1000 | } | ||
1001 | |||
1002 | static void __exit ar9170_exit(void) | ||
1003 | { | ||
1004 | usb_deregister(&ar9170_driver); | ||
1005 | } | ||
1006 | |||
1007 | module_init(ar9170_init); | ||
1008 | module_exit(ar9170_exit); | ||
diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h deleted file mode 100644 index 919b06046eb3..000000000000 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ /dev/null | |||
@@ -1,82 +0,0 @@ | |||
1 | /* | ||
2 | * Atheros AR9170 USB driver | ||
3 | * | ||
4 | * Driver specific definitions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, Christian Lamparter <chunkeey@web.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | #ifndef __USB_H | ||
40 | #define __USB_H | ||
41 | |||
42 | #include <linux/usb.h> | ||
43 | #include <linux/completion.h> | ||
44 | #include <linux/spinlock.h> | ||
45 | #include <linux/leds.h> | ||
46 | #include <net/cfg80211.h> | ||
47 | #include <net/mac80211.h> | ||
48 | #include <linux/firmware.h> | ||
49 | #include "eeprom.h" | ||
50 | #include "hw.h" | ||
51 | #include "ar9170.h" | ||
52 | |||
53 | #define AR9170_NUM_RX_URBS 16 | ||
54 | #define AR9170_NUM_TX_URBS 8 | ||
55 | |||
56 | struct firmware; | ||
57 | |||
58 | struct ar9170_usb { | ||
59 | struct ar9170 common; | ||
60 | struct usb_device *udev; | ||
61 | struct usb_interface *intf; | ||
62 | |||
63 | struct usb_anchor rx_submitted; | ||
64 | struct usb_anchor tx_pending; | ||
65 | struct usb_anchor tx_submitted; | ||
66 | |||
67 | bool req_one_stage_fw; | ||
68 | |||
69 | spinlock_t tx_urb_lock; | ||
70 | atomic_t tx_submitted_urbs; | ||
71 | unsigned int tx_pending_urbs; | ||
72 | |||
73 | struct completion cmd_wait; | ||
74 | struct completion firmware_loading_complete; | ||
75 | int readlen; | ||
76 | u8 *readbuf; | ||
77 | |||
78 | const struct firmware *init_values; | ||
79 | const struct firmware *firmware; | ||
80 | }; | ||
81 | |||
82 | #endif /* __USB_H */ | ||