diff options
Diffstat (limited to 'drivers/staging/ath6kl/os')
19 files changed, 14117 insertions, 0 deletions
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/drivers/staging/ath6kl/os/linux/ar6000_drv.c new file mode 100644 index 00000000000..32ee39ad00d --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/ar6000_drv.c | |||
@@ -0,0 +1,6267 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | /* | ||
25 | * This driver is a pseudo ethernet driver to access the Atheros AR6000 | ||
26 | * WLAN Device | ||
27 | */ | ||
28 | |||
29 | #include "ar6000_drv.h" | ||
30 | #include "cfg80211.h" | ||
31 | #include "htc.h" | ||
32 | #include "wmi_filter_linux.h" | ||
33 | #include "epping_test.h" | ||
34 | #include "wlan_config.h" | ||
35 | #include "ar3kconfig.h" | ||
36 | #include "ar6k_pal.h" | ||
37 | #include "AR6002/addrs.h" | ||
38 | |||
39 | |||
40 | /* LINUX_HACK_FUDGE_FACTOR -- this is used to provide a workaround for linux behavior. When | ||
41 | * the meta data was added to the header it was found that linux did not correctly provide | ||
42 | * enough headroom. However when more headroom was requested beyond what was truly needed | ||
43 | * Linux gave the requested headroom. Therefore to get the necessary headroom from Linux | ||
44 | * the driver requests more than is needed by the amount = LINUX_HACK_FUDGE_FACTOR */ | ||
45 | #define LINUX_HACK_FUDGE_FACTOR 16 | ||
46 | #define BDATA_BDADDR_OFFSET 28 | ||
47 | |||
48 | u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
49 | u8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | ||
50 | |||
51 | #ifdef DEBUG | ||
52 | |||
53 | #define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0) | ||
54 | #define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1) | ||
55 | #define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2) | ||
56 | #define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3) | ||
57 | #define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4) | ||
58 | #define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5) | ||
59 | #define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) | ||
60 | |||
61 | static struct ath_debug_mask_description driver_debug_desc[] = { | ||
62 | { ATH_DEBUG_DBG_LOG , "Target Debug Logs"}, | ||
63 | { ATH_DEBUG_WLAN_CONNECT , "WLAN connect"}, | ||
64 | { ATH_DEBUG_WLAN_SCAN , "WLAN scan"}, | ||
65 | { ATH_DEBUG_WLAN_TX , "WLAN Tx"}, | ||
66 | { ATH_DEBUG_WLAN_RX , "WLAN Rx"}, | ||
67 | { ATH_DEBUG_HTC_RAW , "HTC Raw IF tracing"}, | ||
68 | { ATH_DEBUG_HCI_BRIDGE , "HCI Bridge Setup"}, | ||
69 | { ATH_DEBUG_HCI_RECV , "HCI Recv tracing"}, | ||
70 | { ATH_DEBUG_HCI_DUMP , "HCI Packet dumps"}, | ||
71 | }; | ||
72 | |||
73 | ATH_DEBUG_INSTANTIATE_MODULE_VAR(driver, | ||
74 | "driver", | ||
75 | "Linux Driver Interface", | ||
76 | ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_WLAN_SCAN | | ||
77 | ATH_DEBUG_HCI_BRIDGE, | ||
78 | ATH_DEBUG_DESCRIPTION_COUNT(driver_debug_desc), | ||
79 | driver_debug_desc); | ||
80 | |||
81 | #endif | ||
82 | |||
83 | |||
84 | #define IS_MAC_NULL(mac) (mac[0]==0 && mac[1]==0 && mac[2]==0 && mac[3]==0 && mac[4]==0 && mac[5]==0) | ||
85 | #define IS_MAC_BCAST(mac) (*mac==0xff) | ||
86 | |||
87 | #define DESCRIPTION "Driver to access the Atheros AR600x Device, version " __stringify(__VER_MAJOR_) "." __stringify(__VER_MINOR_) "." __stringify(__VER_PATCH_) "." __stringify(__BUILD_NUMBER_) | ||
88 | |||
89 | MODULE_AUTHOR("Atheros Communications, Inc."); | ||
90 | MODULE_DESCRIPTION(DESCRIPTION); | ||
91 | MODULE_LICENSE("Dual BSD/GPL"); | ||
92 | |||
93 | #ifndef REORG_APTC_HEURISTICS | ||
94 | #undef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
95 | #endif /* REORG_APTC_HEURISTICS */ | ||
96 | |||
97 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
98 | #define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */ | ||
99 | #define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */ | ||
100 | #define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */ | ||
101 | |||
102 | typedef struct aptc_traffic_record { | ||
103 | bool timerScheduled; | ||
104 | struct timeval samplingTS; | ||
105 | unsigned long bytesReceived; | ||
106 | unsigned long bytesTransmitted; | ||
107 | } APTC_TRAFFIC_RECORD; | ||
108 | |||
109 | A_TIMER aptcTimer; | ||
110 | APTC_TRAFFIC_RECORD aptcTR; | ||
111 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
112 | |||
113 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
114 | // callbacks registered by HCI transport driver | ||
115 | struct hci_transport_callbacks ar6kHciTransCallbacks = { NULL }; | ||
116 | #endif | ||
117 | |||
118 | unsigned int processDot11Hdr = 0; | ||
119 | |||
120 | char ifname[IFNAMSIZ] = {0,}; | ||
121 | |||
122 | int wlaninitmode = WLAN_INIT_MODE_DEFAULT; | ||
123 | static bool bypasswmi; | ||
124 | unsigned int debuglevel = 0; | ||
125 | int tspecCompliance = ATHEROS_COMPLIANCE; | ||
126 | unsigned int busspeedlow = 0; | ||
127 | unsigned int onebitmode = 0; | ||
128 | unsigned int skipflash = 0; | ||
129 | unsigned int wmitimeout = 2; | ||
130 | unsigned int wlanNodeCaching = 1; | ||
131 | unsigned int enableuartprint = ENABLEUARTPRINT_DEFAULT; | ||
132 | unsigned int logWmiRawMsgs = 0; | ||
133 | unsigned int enabletimerwar = 0; | ||
134 | unsigned int num_device = 1; | ||
135 | unsigned int regscanmode; | ||
136 | unsigned int fwmode = 1; | ||
137 | unsigned int mbox_yield_limit = 99; | ||
138 | unsigned int enablerssicompensation = 0; | ||
139 | int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF; | ||
140 | int allow_trace_signal = 0; | ||
141 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
142 | unsigned int testmode =0; | ||
143 | #endif | ||
144 | |||
145 | unsigned int irqprocmode = HIF_DEVICE_IRQ_SYNC_ONLY;//HIF_DEVICE_IRQ_ASYNC_SYNC; | ||
146 | unsigned int panic_on_assert = 1; | ||
147 | unsigned int nohifscattersupport = NOHIFSCATTERSUPPORT_DEFAULT; | ||
148 | |||
149 | unsigned int setuphci = SETUPHCI_DEFAULT; | ||
150 | unsigned int loghci = 0; | ||
151 | unsigned int setupbtdev = SETUPBTDEV_DEFAULT; | ||
152 | #ifndef EXPORT_HCI_BRIDGE_INTERFACE | ||
153 | unsigned int ar3khcibaud = AR3KHCIBAUD_DEFAULT; | ||
154 | unsigned int hciuartscale = HCIUARTSCALE_DEFAULT; | ||
155 | unsigned int hciuartstep = HCIUARTSTEP_DEFAULT; | ||
156 | #endif | ||
157 | unsigned int csumOffload=0; | ||
158 | unsigned int csumOffloadTest=0; | ||
159 | unsigned int eppingtest=0; | ||
160 | unsigned int mac_addr_method; | ||
161 | unsigned int firmware_bridge; | ||
162 | |||
163 | module_param_string(ifname, ifname, sizeof(ifname), 0644); | ||
164 | module_param(wlaninitmode, int, 0644); | ||
165 | module_param(bypasswmi, bool, 0644); | ||
166 | module_param(debuglevel, uint, 0644); | ||
167 | module_param(tspecCompliance, int, 0644); | ||
168 | module_param(onebitmode, uint, 0644); | ||
169 | module_param(busspeedlow, uint, 0644); | ||
170 | module_param(skipflash, uint, 0644); | ||
171 | module_param(wmitimeout, uint, 0644); | ||
172 | module_param(wlanNodeCaching, uint, 0644); | ||
173 | module_param(logWmiRawMsgs, uint, 0644); | ||
174 | module_param(enableuartprint, uint, 0644); | ||
175 | module_param(enabletimerwar, uint, 0644); | ||
176 | module_param(fwmode, uint, 0644); | ||
177 | module_param(mbox_yield_limit, uint, 0644); | ||
178 | module_param(reduce_credit_dribble, int, 0644); | ||
179 | module_param(allow_trace_signal, int, 0644); | ||
180 | module_param(enablerssicompensation, uint, 0644); | ||
181 | module_param(processDot11Hdr, uint, 0644); | ||
182 | module_param(csumOffload, uint, 0644); | ||
183 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
184 | module_param(testmode, uint, 0644); | ||
185 | #endif | ||
186 | module_param(irqprocmode, uint, 0644); | ||
187 | module_param(nohifscattersupport, uint, 0644); | ||
188 | module_param(panic_on_assert, uint, 0644); | ||
189 | module_param(setuphci, uint, 0644); | ||
190 | module_param(loghci, uint, 0644); | ||
191 | module_param(setupbtdev, uint, 0644); | ||
192 | #ifndef EXPORT_HCI_BRIDGE_INTERFACE | ||
193 | module_param(ar3khcibaud, uint, 0644); | ||
194 | module_param(hciuartscale, uint, 0644); | ||
195 | module_param(hciuartstep, uint, 0644); | ||
196 | #endif | ||
197 | module_param(eppingtest, uint, 0644); | ||
198 | |||
199 | /* in 2.6.10 and later this is now a pointer to a uint */ | ||
200 | unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX; | ||
201 | #define mboxnum &_mboxnum | ||
202 | |||
203 | #ifdef DEBUG | ||
204 | u32 g_dbg_flags = DBG_DEFAULTS; | ||
205 | unsigned int debugflags = 0; | ||
206 | int debugdriver = 0; | ||
207 | unsigned int debughtc = 0; | ||
208 | unsigned int debugbmi = 0; | ||
209 | unsigned int debughif = 0; | ||
210 | unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0}; | ||
211 | unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0}; | ||
212 | unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0}; | ||
213 | unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0}; | ||
214 | module_param(debugflags, uint, 0644); | ||
215 | module_param(debugdriver, int, 0644); | ||
216 | module_param(debughtc, uint, 0644); | ||
217 | module_param(debugbmi, uint, 0644); | ||
218 | module_param(debughif, uint, 0644); | ||
219 | module_param_array(txcreditsavailable, uint, mboxnum, 0644); | ||
220 | module_param_array(txcreditsconsumed, uint, mboxnum, 0644); | ||
221 | module_param_array(txcreditintrenable, uint, mboxnum, 0644); | ||
222 | module_param_array(txcreditintrenableaggregate, uint, mboxnum, 0644); | ||
223 | |||
224 | #endif /* DEBUG */ | ||
225 | |||
226 | unsigned int resetok = 1; | ||
227 | unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0}; | ||
228 | unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0}; | ||
229 | unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0}; | ||
230 | unsigned int hifBusRequestNumMax = 40; | ||
231 | unsigned int war23838_disabled = 0; | ||
232 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
233 | unsigned int enableAPTCHeuristics = 1; | ||
234 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
235 | module_param_array(tx_attempt, uint, mboxnum, 0644); | ||
236 | module_param_array(tx_post, uint, mboxnum, 0644); | ||
237 | module_param_array(tx_complete, uint, mboxnum, 0644); | ||
238 | module_param(hifBusRequestNumMax, uint, 0644); | ||
239 | module_param(war23838_disabled, uint, 0644); | ||
240 | module_param(resetok, uint, 0644); | ||
241 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
242 | module_param(enableAPTCHeuristics, uint, 0644); | ||
243 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
244 | |||
245 | #ifdef BLOCK_TX_PATH_FLAG | ||
246 | int blocktx = 0; | ||
247 | module_param(blocktx, int, 0644); | ||
248 | #endif /* BLOCK_TX_PATH_FLAG */ | ||
249 | |||
250 | typedef struct user_rssi_compensation_t { | ||
251 | u16 customerID; | ||
252 | union { | ||
253 | u16 a_enable; | ||
254 | u16 bg_enable; | ||
255 | u16 enable; | ||
256 | }; | ||
257 | s16 bg_param_a; | ||
258 | s16 bg_param_b; | ||
259 | s16 a_param_a; | ||
260 | s16 a_param_b; | ||
261 | u32 reserved; | ||
262 | } USER_RSSI_CPENSATION; | ||
263 | |||
264 | static USER_RSSI_CPENSATION rssi_compensation_param; | ||
265 | |||
266 | static s16 rssi_compensation_table[96]; | ||
267 | |||
268 | int reconnect_flag = 0; | ||
269 | static ar6k_pal_config_t ar6k_pal_config_g; | ||
270 | |||
271 | /* Function declarations */ | ||
272 | static int ar6000_init_module(void); | ||
273 | static void ar6000_cleanup_module(void); | ||
274 | |||
275 | int ar6000_init(struct net_device *dev); | ||
276 | static int ar6000_open(struct net_device *dev); | ||
277 | static int ar6000_close(struct net_device *dev); | ||
278 | static void ar6000_init_control_info(struct ar6_softc *ar); | ||
279 | static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev); | ||
280 | |||
281 | void ar6000_destroy(struct net_device *dev, unsigned int unregister); | ||
282 | static void ar6000_detect_error(unsigned long ptr); | ||
283 | static void ar6000_set_multicast_list(struct net_device *dev); | ||
284 | static struct net_device_stats *ar6000_get_stats(struct net_device *dev); | ||
285 | |||
286 | static void disconnect_timer_handler(unsigned long ptr); | ||
287 | |||
288 | void read_rssi_compensation_param(struct ar6_softc *ar); | ||
289 | |||
290 | /* | ||
291 | * HTC service connection handlers | ||
292 | */ | ||
293 | static int ar6000_avail_ev(void *context, void *hif_handle); | ||
294 | |||
295 | static int ar6000_unavail_ev(void *context, void *hif_handle); | ||
296 | |||
297 | int ar6000_configure_target(struct ar6_softc *ar); | ||
298 | |||
299 | static void ar6000_target_failure(void *Instance, int Status); | ||
300 | |||
301 | static void ar6000_rx(void *Context, struct htc_packet *pPacket); | ||
302 | |||
303 | static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint); | ||
304 | |||
305 | static void ar6000_tx_complete(void *Context, struct htc_packet_queue *pPackets); | ||
306 | |||
307 | static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket); | ||
308 | |||
309 | static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num); | ||
310 | static void ar6000_deliver_frames_to_nw_stack(void * dev, void *osbuf); | ||
311 | //static void ar6000_deliver_frames_to_bt_stack(void * dev, void *osbuf); | ||
312 | |||
313 | static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length); | ||
314 | |||
315 | static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count); | ||
316 | |||
317 | static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar); | ||
318 | |||
319 | static ssize_t | ||
320 | ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj, | ||
321 | struct bin_attribute *bin_attr, | ||
322 | char *buf, loff_t pos, size_t count); | ||
323 | |||
324 | static ssize_t | ||
325 | ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj, | ||
326 | struct bin_attribute *bin_attr, | ||
327 | char *buf, loff_t pos, size_t count); | ||
328 | |||
329 | static int | ||
330 | ar6000_sysfs_bmi_init(struct ar6_softc *ar); | ||
331 | |||
332 | void ar6k_cleanup_hci_pal(struct ar6_softc *ar); | ||
333 | |||
334 | static void | ||
335 | ar6000_sysfs_bmi_deinit(struct ar6_softc *ar); | ||
336 | |||
337 | int | ||
338 | ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode); | ||
339 | |||
340 | /* | ||
341 | * Static variables | ||
342 | */ | ||
343 | |||
344 | struct net_device *ar6000_devices[MAX_AR6000]; | ||
345 | static int is_netdev_registered; | ||
346 | DECLARE_WAIT_QUEUE_HEAD(arEvent); | ||
347 | static void ar6000_cookie_init(struct ar6_softc *ar); | ||
348 | static void ar6000_cookie_cleanup(struct ar6_softc *ar); | ||
349 | static void ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie); | ||
350 | static struct ar_cookie *ar6000_alloc_cookie(struct ar6_softc *ar); | ||
351 | |||
352 | static int ar6000_reinstall_keys(struct ar6_softc *ar,u8 key_op_ctrl); | ||
353 | |||
354 | #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT | ||
355 | struct net_device *arApNetDev; | ||
356 | #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ | ||
357 | |||
358 | static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM]; | ||
359 | |||
360 | #define HOST_INTEREST_ITEM_ADDRESS(ar, item) \ | ||
361 | (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \ | ||
362 | (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0)) | ||
363 | |||
364 | |||
365 | static struct net_device_ops ar6000_netdev_ops = { | ||
366 | .ndo_init = NULL, | ||
367 | .ndo_open = ar6000_open, | ||
368 | .ndo_stop = ar6000_close, | ||
369 | .ndo_get_stats = ar6000_get_stats, | ||
370 | .ndo_start_xmit = ar6000_data_tx, | ||
371 | .ndo_set_multicast_list = ar6000_set_multicast_list, | ||
372 | }; | ||
373 | |||
374 | /* Debug log support */ | ||
375 | |||
376 | /* | ||
377 | * Flag to govern whether the debug logs should be parsed in the kernel | ||
378 | * or reported to the application. | ||
379 | */ | ||
380 | #define REPORT_DEBUG_LOGS_TO_APP | ||
381 | |||
382 | int | ||
383 | ar6000_set_host_app_area(struct ar6_softc *ar) | ||
384 | { | ||
385 | u32 address, data; | ||
386 | struct host_app_area_s host_app_area; | ||
387 | |||
388 | /* Fetch the address of the host_app_area_s instance in the host interest area */ | ||
389 | address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest)); | ||
390 | if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != 0) { | ||
391 | return A_ERROR; | ||
392 | } | ||
393 | address = TARG_VTOP(ar->arTargetType, data); | ||
394 | host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION; | ||
395 | if (ar6000_WriteDataDiag(ar->arHifDevice, address, | ||
396 | (u8 *)&host_app_area, | ||
397 | sizeof(struct host_app_area_s)) != 0) | ||
398 | { | ||
399 | return A_ERROR; | ||
400 | } | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | u32 dbglog_get_debug_hdr_ptr(struct ar6_softc *ar) | ||
406 | { | ||
407 | u32 param; | ||
408 | u32 address; | ||
409 | int status; | ||
410 | |||
411 | address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr)); | ||
412 | if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address, | ||
413 | (u8 *)¶m, 4)) != 0) | ||
414 | { | ||
415 | param = 0; | ||
416 | } | ||
417 | |||
418 | return param; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * The dbglog module has been initialized. Its ok to access the relevant | ||
423 | * data stuctures over the diagnostic window. | ||
424 | */ | ||
425 | void | ||
426 | ar6000_dbglog_init_done(struct ar6_softc *ar) | ||
427 | { | ||
428 | ar->dbglog_init_done = true; | ||
429 | } | ||
430 | |||
431 | u32 dbglog_get_debug_fragment(s8 *datap, u32 len, u32 limit) | ||
432 | { | ||
433 | s32 *buffer; | ||
434 | u32 count; | ||
435 | u32 numargs; | ||
436 | u32 length; | ||
437 | u32 fraglen; | ||
438 | |||
439 | count = fraglen = 0; | ||
440 | buffer = (s32 *)datap; | ||
441 | length = (limit >> 2); | ||
442 | |||
443 | if (len <= limit) { | ||
444 | fraglen = len; | ||
445 | } else { | ||
446 | while (count < length) { | ||
447 | numargs = DBGLOG_GET_NUMARGS(buffer[count]); | ||
448 | fraglen = (count << 2); | ||
449 | count += numargs + 1; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | return fraglen; | ||
454 | } | ||
455 | |||
456 | void | ||
457 | dbglog_parse_debug_logs(s8 *datap, u32 len) | ||
458 | { | ||
459 | s32 *buffer; | ||
460 | u32 count; | ||
461 | u32 timestamp; | ||
462 | u32 debugid; | ||
463 | u32 moduleid; | ||
464 | u32 numargs; | ||
465 | u32 length; | ||
466 | |||
467 | count = 0; | ||
468 | buffer = (s32 *)datap; | ||
469 | length = (len >> 2); | ||
470 | while (count < length) { | ||
471 | debugid = DBGLOG_GET_DBGID(buffer[count]); | ||
472 | moduleid = DBGLOG_GET_MODULEID(buffer[count]); | ||
473 | numargs = DBGLOG_GET_NUMARGS(buffer[count]); | ||
474 | timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]); | ||
475 | switch (numargs) { | ||
476 | case 0: | ||
477 | AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d)\n", moduleid, debugid, timestamp)); | ||
478 | break; | ||
479 | |||
480 | case 1: | ||
481 | AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x\n", moduleid, debugid, | ||
482 | timestamp, buffer[count+1])); | ||
483 | break; | ||
484 | |||
485 | case 2: | ||
486 | AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid, | ||
487 | timestamp, buffer[count+1], buffer[count+2])); | ||
488 | break; | ||
489 | |||
490 | default: | ||
491 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid args: %d\n", numargs)); | ||
492 | } | ||
493 | count += numargs + 1; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | int | ||
498 | ar6000_dbglog_get_debug_logs(struct ar6_softc *ar) | ||
499 | { | ||
500 | u32 data[8]; /* Should be able to accommodate struct dbglog_buf_s */ | ||
501 | u32 address; | ||
502 | u32 length; | ||
503 | u32 dropped; | ||
504 | u32 firstbuf; | ||
505 | u32 debug_hdr_ptr; | ||
506 | |||
507 | if (!ar->dbglog_init_done) return A_ERROR; | ||
508 | |||
509 | |||
510 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
511 | |||
512 | if (ar->dbgLogFetchInProgress) { | ||
513 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
514 | return A_EBUSY; | ||
515 | } | ||
516 | |||
517 | /* block out others */ | ||
518 | ar->dbgLogFetchInProgress = true; | ||
519 | |||
520 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
521 | |||
522 | debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar); | ||
523 | printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr); | ||
524 | |||
525 | /* Get the contents of the ring buffer */ | ||
526 | if (debug_hdr_ptr) { | ||
527 | address = TARG_VTOP(ar->arTargetType, debug_hdr_ptr); | ||
528 | length = 4 /* sizeof(dbuf) */ + 4 /* sizeof(dropped) */; | ||
529 | A_MEMZERO(data, sizeof(data)); | ||
530 | ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)data, length); | ||
531 | address = TARG_VTOP(ar->arTargetType, data[0] /* dbuf */); | ||
532 | firstbuf = address; | ||
533 | dropped = data[1]; /* dropped */ | ||
534 | length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */; | ||
535 | A_MEMZERO(data, sizeof(data)); | ||
536 | ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)&data, length); | ||
537 | |||
538 | do { | ||
539 | address = TARG_VTOP(ar->arTargetType, data[1] /* buffer*/); | ||
540 | length = data[3]; /* length */ | ||
541 | if ((length) && (length <= data[2] /* bufsize*/)) { | ||
542 | /* Rewind the index if it is about to overrun the buffer */ | ||
543 | if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) { | ||
544 | ar->log_cnt = 0; | ||
545 | } | ||
546 | if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address, | ||
547 | (u8 *)&ar->log_buffer[ar->log_cnt], length)) | ||
548 | { | ||
549 | break; | ||
550 | } | ||
551 | ar6000_dbglog_event(ar, dropped, (s8 *)&ar->log_buffer[ar->log_cnt], length); | ||
552 | ar->log_cnt += length; | ||
553 | } else { | ||
554 | AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("Length: %d (Total size: %d)\n", | ||
555 | data[3], data[2])); | ||
556 | } | ||
557 | |||
558 | address = TARG_VTOP(ar->arTargetType, data[0] /* next */); | ||
559 | length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */; | ||
560 | A_MEMZERO(data, sizeof(data)); | ||
561 | if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address, | ||
562 | (u8 *)&data, length)) | ||
563 | { | ||
564 | break; | ||
565 | } | ||
566 | |||
567 | } while (address != firstbuf); | ||
568 | } | ||
569 | |||
570 | ar->dbgLogFetchInProgress = false; | ||
571 | |||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | void | ||
576 | ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped, | ||
577 | s8 *buffer, u32 length) | ||
578 | { | ||
579 | #ifdef REPORT_DEBUG_LOGS_TO_APP | ||
580 | #define MAX_WIRELESS_EVENT_SIZE 252 | ||
581 | /* | ||
582 | * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages. | ||
583 | * There seems to be a limitation on the length of message that could be | ||
584 | * transmitted to the user app via this mechanism. | ||
585 | */ | ||
586 | u32 send, sent; | ||
587 | |||
588 | sent = 0; | ||
589 | send = dbglog_get_debug_fragment(&buffer[sent], length - sent, | ||
590 | MAX_WIRELESS_EVENT_SIZE); | ||
591 | while (send) { | ||
592 | sent += send; | ||
593 | send = dbglog_get_debug_fragment(&buffer[sent], length - sent, | ||
594 | MAX_WIRELESS_EVENT_SIZE); | ||
595 | } | ||
596 | #else | ||
597 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Dropped logs: 0x%x\nDebug info length: %d\n", | ||
598 | dropped, length)); | ||
599 | |||
600 | /* Interpret the debug logs */ | ||
601 | dbglog_parse_debug_logs((s8 *)buffer, length); | ||
602 | #endif /* REPORT_DEBUG_LOGS_TO_APP */ | ||
603 | } | ||
604 | |||
605 | |||
606 | static int __init | ||
607 | ar6000_init_module(void) | ||
608 | { | ||
609 | static int probed = 0; | ||
610 | int r; | ||
611 | OSDRV_CALLBACKS osdrvCallbacks; | ||
612 | |||
613 | a_module_debug_support_init(); | ||
614 | |||
615 | #ifdef DEBUG | ||
616 | /* check for debug mask overrides */ | ||
617 | if (debughtc != 0) { | ||
618 | ATH_DEBUG_SET_DEBUG_MASK(htc,debughtc); | ||
619 | } | ||
620 | if (debugbmi != 0) { | ||
621 | ATH_DEBUG_SET_DEBUG_MASK(bmi,debugbmi); | ||
622 | } | ||
623 | if (debughif != 0) { | ||
624 | ATH_DEBUG_SET_DEBUG_MASK(hif,debughif); | ||
625 | } | ||
626 | if (debugdriver != 0) { | ||
627 | ATH_DEBUG_SET_DEBUG_MASK(driver,debugdriver); | ||
628 | } | ||
629 | |||
630 | #endif | ||
631 | |||
632 | A_REGISTER_MODULE_DEBUG_INFO(driver); | ||
633 | |||
634 | A_MEMZERO(&osdrvCallbacks,sizeof(osdrvCallbacks)); | ||
635 | osdrvCallbacks.deviceInsertedHandler = ar6000_avail_ev; | ||
636 | osdrvCallbacks.deviceRemovedHandler = ar6000_unavail_ev; | ||
637 | #ifdef CONFIG_PM | ||
638 | osdrvCallbacks.deviceSuspendHandler = ar6000_suspend_ev; | ||
639 | osdrvCallbacks.deviceResumeHandler = ar6000_resume_ev; | ||
640 | osdrvCallbacks.devicePowerChangeHandler = ar6000_power_change_ev; | ||
641 | #endif | ||
642 | |||
643 | #ifdef DEBUG | ||
644 | /* Set the debug flags if specified at load time */ | ||
645 | if(debugflags != 0) | ||
646 | { | ||
647 | g_dbg_flags = debugflags; | ||
648 | } | ||
649 | #endif | ||
650 | |||
651 | if (probed) { | ||
652 | return -ENODEV; | ||
653 | } | ||
654 | probed++; | ||
655 | |||
656 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
657 | memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD)); | ||
658 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
659 | |||
660 | r = HIFInit(&osdrvCallbacks); | ||
661 | if (r) | ||
662 | return r; | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static void __exit | ||
668 | ar6000_cleanup_module(void) | ||
669 | { | ||
670 | int i = 0; | ||
671 | struct net_device *ar6000_netdev; | ||
672 | |||
673 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
674 | /* Delete the Adaptive Power Control timer */ | ||
675 | if (timer_pending(&aptcTimer)) { | ||
676 | del_timer_sync(&aptcTimer); | ||
677 | } | ||
678 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
679 | |||
680 | for (i=0; i < MAX_AR6000; i++) { | ||
681 | if (ar6000_devices[i] != NULL) { | ||
682 | ar6000_netdev = ar6000_devices[i]; | ||
683 | ar6000_devices[i] = NULL; | ||
684 | ar6000_destroy(ar6000_netdev, 1); | ||
685 | } | ||
686 | } | ||
687 | |||
688 | HIFShutDownDevice(NULL); | ||
689 | |||
690 | a_module_debug_support_cleanup(); | ||
691 | |||
692 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_cleanup: success\n")); | ||
693 | } | ||
694 | |||
695 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
696 | void | ||
697 | aptcTimerHandler(unsigned long arg) | ||
698 | { | ||
699 | u32 numbytes; | ||
700 | u32 throughput; | ||
701 | struct ar6_softc *ar; | ||
702 | int status; | ||
703 | |||
704 | ar = (struct ar6_softc *)arg; | ||
705 | A_ASSERT(ar != NULL); | ||
706 | A_ASSERT(!timer_pending(&aptcTimer)); | ||
707 | |||
708 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
709 | |||
710 | /* Get the number of bytes transferred */ | ||
711 | numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; | ||
712 | aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; | ||
713 | |||
714 | /* Calculate and decide based on throughput thresholds */ | ||
715 | throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */ | ||
716 | if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) { | ||
717 | /* Enable Sleep and delete the timer */ | ||
718 | A_ASSERT(ar->arWmiReady == true); | ||
719 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
720 | status = wmi_powermode_cmd(ar->arWmi, REC_POWER); | ||
721 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
722 | A_ASSERT(status == 0); | ||
723 | aptcTR.timerScheduled = false; | ||
724 | } else { | ||
725 | A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); | ||
726 | } | ||
727 | |||
728 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
729 | } | ||
730 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
731 | |||
732 | static void | ||
733 | ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num) | ||
734 | { | ||
735 | void * osbuf; | ||
736 | |||
737 | while(num) { | ||
738 | if((osbuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE))) { | ||
739 | A_NETBUF_ENQUEUE(q, osbuf); | ||
740 | } else { | ||
741 | break; | ||
742 | } | ||
743 | num--; | ||
744 | } | ||
745 | |||
746 | if(num) { | ||
747 | A_PRINTF("%s(), allocation of netbuf failed", __func__); | ||
748 | } | ||
749 | } | ||
750 | |||
751 | static struct bin_attribute bmi_attr = { | ||
752 | .attr = {.name = "bmi", .mode = 0600}, | ||
753 | .read = ar6000_sysfs_bmi_read, | ||
754 | .write = ar6000_sysfs_bmi_write, | ||
755 | }; | ||
756 | |||
757 | static ssize_t | ||
758 | ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj, | ||
759 | struct bin_attribute *bin_attr, | ||
760 | char *buf, loff_t pos, size_t count) | ||
761 | { | ||
762 | int index; | ||
763 | struct ar6_softc *ar; | ||
764 | struct hif_device_os_device_info *osDevInfo; | ||
765 | |||
766 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", (u32)count)); | ||
767 | for (index=0; index < MAX_AR6000; index++) { | ||
768 | ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]); | ||
769 | osDevInfo = &ar->osDevInfo; | ||
770 | if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) { | ||
771 | break; | ||
772 | } | ||
773 | } | ||
774 | |||
775 | if (index == MAX_AR6000) return 0; | ||
776 | |||
777 | if ((BMIRawRead(ar->arHifDevice, (u8*)buf, count, true)) != 0) { | ||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | return count; | ||
782 | } | ||
783 | |||
784 | static ssize_t | ||
785 | ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj, | ||
786 | struct bin_attribute *bin_attr, | ||
787 | char *buf, loff_t pos, size_t count) | ||
788 | { | ||
789 | int index; | ||
790 | struct ar6_softc *ar; | ||
791 | struct hif_device_os_device_info *osDevInfo; | ||
792 | |||
793 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", (u32)count)); | ||
794 | for (index=0; index < MAX_AR6000; index++) { | ||
795 | ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]); | ||
796 | osDevInfo = &ar->osDevInfo; | ||
797 | if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) { | ||
798 | break; | ||
799 | } | ||
800 | } | ||
801 | |||
802 | if (index == MAX_AR6000) return 0; | ||
803 | |||
804 | if ((BMIRawWrite(ar->arHifDevice, (u8*)buf, count)) != 0) { | ||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | return count; | ||
809 | } | ||
810 | |||
811 | static int | ||
812 | ar6000_sysfs_bmi_init(struct ar6_softc *ar) | ||
813 | { | ||
814 | int status; | ||
815 | |||
816 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Creating sysfs entry\n")); | ||
817 | A_MEMZERO(&ar->osDevInfo, sizeof(struct hif_device_os_device_info)); | ||
818 | |||
819 | /* Get the underlying OS device */ | ||
820 | status = HIFConfigureDevice(ar->arHifDevice, | ||
821 | HIF_DEVICE_GET_OS_DEVICE, | ||
822 | &ar->osDevInfo, | ||
823 | sizeof(struct hif_device_os_device_info)); | ||
824 | |||
825 | if (status) { | ||
826 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failed to get OS device info from HIF\n")); | ||
827 | return A_ERROR; | ||
828 | } | ||
829 | |||
830 | /* Create a bmi entry in the sysfs filesystem */ | ||
831 | if ((sysfs_create_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr)) < 0) | ||
832 | { | ||
833 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to create entry for bmi in sysfs filesystem\n")); | ||
834 | return A_ERROR; | ||
835 | } | ||
836 | |||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | static void | ||
841 | ar6000_sysfs_bmi_deinit(struct ar6_softc *ar) | ||
842 | { | ||
843 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Deleting sysfs entry\n")); | ||
844 | |||
845 | sysfs_remove_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr); | ||
846 | } | ||
847 | |||
848 | #define bmifn(fn) do { \ | ||
849 | if ((fn) < 0) { \ | ||
850 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); \ | ||
851 | return A_ERROR; \ | ||
852 | } \ | ||
853 | } while(0) | ||
854 | |||
855 | #ifdef SOFTMAC_FILE_USED | ||
856 | #define AR6002_MAC_ADDRESS_OFFSET 0x0A | ||
857 | #define AR6003_MAC_ADDRESS_OFFSET 0x16 | ||
858 | static | ||
859 | void calculate_crc(u32 TargetType, u8 *eeprom_data) | ||
860 | { | ||
861 | u16 *ptr_crc; | ||
862 | u16 *ptr16_eeprom; | ||
863 | u16 checksum; | ||
864 | u32 i; | ||
865 | u32 eeprom_size; | ||
866 | |||
867 | if (TargetType == TARGET_TYPE_AR6001) | ||
868 | { | ||
869 | eeprom_size = 512; | ||
870 | ptr_crc = (u16 *)eeprom_data; | ||
871 | } | ||
872 | else if (TargetType == TARGET_TYPE_AR6003) | ||
873 | { | ||
874 | eeprom_size = 1024; | ||
875 | ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04); | ||
876 | } | ||
877 | else | ||
878 | { | ||
879 | eeprom_size = 768; | ||
880 | ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04); | ||
881 | } | ||
882 | |||
883 | |||
884 | // Clear the crc | ||
885 | *ptr_crc = 0; | ||
886 | |||
887 | // Recalculate new CRC | ||
888 | checksum = 0; | ||
889 | ptr16_eeprom = (u16 *)eeprom_data; | ||
890 | for (i = 0;i < eeprom_size; i += 2) | ||
891 | { | ||
892 | checksum = checksum ^ (*ptr16_eeprom); | ||
893 | ptr16_eeprom++; | ||
894 | } | ||
895 | checksum = 0xFFFF ^ checksum; | ||
896 | *ptr_crc = checksum; | ||
897 | } | ||
898 | |||
899 | static void | ||
900 | ar6000_softmac_update(struct ar6_softc *ar, u8 *eeprom_data, size_t size) | ||
901 | { | ||
902 | const char *source = "random generated"; | ||
903 | const struct firmware *softmac_entry; | ||
904 | u8 *ptr_mac; | ||
905 | switch (ar->arTargetType) { | ||
906 | case TARGET_TYPE_AR6002: | ||
907 | ptr_mac = (u8 *)((u8 *)eeprom_data + AR6002_MAC_ADDRESS_OFFSET); | ||
908 | break; | ||
909 | case TARGET_TYPE_AR6003: | ||
910 | ptr_mac = (u8 *)((u8 *)eeprom_data + AR6003_MAC_ADDRESS_OFFSET); | ||
911 | break; | ||
912 | default: | ||
913 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Target Type\n")); | ||
914 | return; | ||
915 | } | ||
916 | printk(KERN_DEBUG "MAC from EEPROM %pM\n", ptr_mac); | ||
917 | |||
918 | /* create a random MAC in case we cannot read file from system */ | ||
919 | ptr_mac[0] = 0; | ||
920 | ptr_mac[1] = 0x03; | ||
921 | ptr_mac[2] = 0x7F; | ||
922 | ptr_mac[3] = random32() & 0xff; | ||
923 | ptr_mac[4] = random32() & 0xff; | ||
924 | ptr_mac[5] = random32() & 0xff; | ||
925 | if ((A_REQUEST_FIRMWARE(&softmac_entry, "softmac", ((struct device *)ar->osDevInfo.pOSDevice))) == 0) | ||
926 | { | ||
927 | char *macbuf = A_MALLOC_NOWAIT(softmac_entry->size+1); | ||
928 | if (macbuf) { | ||
929 | unsigned int softmac[6]; | ||
930 | memcpy(macbuf, softmac_entry->data, softmac_entry->size); | ||
931 | macbuf[softmac_entry->size] = '\0'; | ||
932 | if (sscanf(macbuf, "%02x:%02x:%02x:%02x:%02x:%02x", | ||
933 | &softmac[0], &softmac[1], &softmac[2], | ||
934 | &softmac[3], &softmac[4], &softmac[5])==6) { | ||
935 | int i; | ||
936 | for (i=0; i<6; ++i) { | ||
937 | ptr_mac[i] = softmac[i] & 0xff; | ||
938 | } | ||
939 | source = "softmac file"; | ||
940 | } | ||
941 | kfree(macbuf); | ||
942 | } | ||
943 | A_RELEASE_FIRMWARE(softmac_entry); | ||
944 | } | ||
945 | printk(KERN_DEBUG "MAC from %s %pM\n", source, ptr_mac); | ||
946 | calculate_crc(ar->arTargetType, eeprom_data); | ||
947 | } | ||
948 | #endif /* SOFTMAC_FILE_USED */ | ||
949 | |||
950 | static int | ||
951 | ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, bool compressed) | ||
952 | { | ||
953 | int status; | ||
954 | const char *filename; | ||
955 | const struct firmware *fw_entry; | ||
956 | u32 fw_entry_size; | ||
957 | u8 **buf; | ||
958 | size_t *buf_len; | ||
959 | |||
960 | switch (file) { | ||
961 | case AR6K_OTP_FILE: | ||
962 | buf = &ar->fw_otp; | ||
963 | buf_len = &ar->fw_otp_len; | ||
964 | if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { | ||
965 | filename = AR6003_REV1_OTP_FILE; | ||
966 | } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
967 | filename = AR6003_REV2_OTP_FILE; | ||
968 | } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { | ||
969 | filename = AR6003_REV3_OTP_FILE; | ||
970 | } else { | ||
971 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); | ||
972 | return A_ERROR; | ||
973 | } | ||
974 | break; | ||
975 | |||
976 | case AR6K_FIRMWARE_FILE: | ||
977 | buf = &ar->fw; | ||
978 | buf_len = &ar->fw_len; | ||
979 | if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { | ||
980 | filename = AR6003_REV1_FIRMWARE_FILE; | ||
981 | } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
982 | filename = AR6003_REV2_FIRMWARE_FILE; | ||
983 | } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { | ||
984 | filename = AR6003_REV3_FIRMWARE_FILE; | ||
985 | } else { | ||
986 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); | ||
987 | return A_ERROR; | ||
988 | } | ||
989 | |||
990 | if (eppingtest) { | ||
991 | bypasswmi = true; | ||
992 | if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { | ||
993 | filename = AR6003_REV1_EPPING_FIRMWARE_FILE; | ||
994 | } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
995 | filename = AR6003_REV2_EPPING_FIRMWARE_FILE; | ||
996 | } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { | ||
997 | filename = AR6003_REV3_EPPING_FIRMWARE_FILE; | ||
998 | } else { | ||
999 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("eppingtest : unsupported firmware revision: %d\n", | ||
1000 | ar->arVersion.target_ver)); | ||
1001 | return A_ERROR; | ||
1002 | } | ||
1003 | compressed = false; | ||
1004 | } | ||
1005 | |||
1006 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
1007 | if(testmode) { | ||
1008 | if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { | ||
1009 | filename = AR6003_REV1_TCMD_FIRMWARE_FILE; | ||
1010 | } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
1011 | filename = AR6003_REV2_TCMD_FIRMWARE_FILE; | ||
1012 | } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { | ||
1013 | filename = AR6003_REV3_TCMD_FIRMWARE_FILE; | ||
1014 | } else { | ||
1015 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); | ||
1016 | return A_ERROR; | ||
1017 | } | ||
1018 | compressed = false; | ||
1019 | } | ||
1020 | #endif | ||
1021 | #ifdef HTC_RAW_INTERFACE | ||
1022 | if (!eppingtest && bypasswmi) { | ||
1023 | if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { | ||
1024 | filename = AR6003_REV1_ART_FIRMWARE_FILE; | ||
1025 | } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
1026 | filename = AR6003_REV2_ART_FIRMWARE_FILE; | ||
1027 | } else { | ||
1028 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); | ||
1029 | return A_ERROR; | ||
1030 | } | ||
1031 | compressed = false; | ||
1032 | } | ||
1033 | #endif | ||
1034 | break; | ||
1035 | |||
1036 | case AR6K_PATCH_FILE: | ||
1037 | buf = &ar->fw_patch; | ||
1038 | buf_len = &ar->fw_patch_len; | ||
1039 | if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { | ||
1040 | filename = AR6003_REV1_PATCH_FILE; | ||
1041 | } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
1042 | filename = AR6003_REV2_PATCH_FILE; | ||
1043 | } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { | ||
1044 | filename = AR6003_REV3_PATCH_FILE; | ||
1045 | } else { | ||
1046 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); | ||
1047 | return A_ERROR; | ||
1048 | } | ||
1049 | break; | ||
1050 | |||
1051 | case AR6K_BOARD_DATA_FILE: | ||
1052 | buf = &ar->fw_data; | ||
1053 | buf_len = &ar->fw_data_len; | ||
1054 | if (ar->arVersion.target_ver == AR6003_REV1_VERSION) { | ||
1055 | filename = AR6003_REV1_BOARD_DATA_FILE; | ||
1056 | } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
1057 | filename = AR6003_REV2_BOARD_DATA_FILE; | ||
1058 | } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) { | ||
1059 | filename = AR6003_REV3_BOARD_DATA_FILE; | ||
1060 | } else { | ||
1061 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver)); | ||
1062 | return A_ERROR; | ||
1063 | } | ||
1064 | break; | ||
1065 | |||
1066 | default: | ||
1067 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown file type: %d\n", file)); | ||
1068 | return A_ERROR; | ||
1069 | } | ||
1070 | |||
1071 | if (*buf == NULL) { | ||
1072 | if ((A_REQUEST_FIRMWARE(&fw_entry, filename, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) { | ||
1073 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to get %s\n", filename)); | ||
1074 | return A_ENOENT; | ||
1075 | } | ||
1076 | |||
1077 | *buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); | ||
1078 | *buf_len = fw_entry->size; | ||
1079 | A_RELEASE_FIRMWARE(fw_entry); | ||
1080 | } | ||
1081 | |||
1082 | #ifdef SOFTMAC_FILE_USED | ||
1083 | if (file==AR6K_BOARD_DATA_FILE && *buf_len) { | ||
1084 | ar6000_softmac_update(ar, *buf, *buf_len); | ||
1085 | } | ||
1086 | #endif | ||
1087 | |||
1088 | |||
1089 | fw_entry_size = *buf_len; | ||
1090 | |||
1091 | /* Load extended board data for AR6003 */ | ||
1092 | if ((file==AR6K_BOARD_DATA_FILE) && *buf) { | ||
1093 | u32 board_ext_address; | ||
1094 | u32 board_ext_data_size; | ||
1095 | u32 board_data_size; | ||
1096 | |||
1097 | board_ext_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_EXT_DATA_SZ : \ | ||
1098 | (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_EXT_DATA_SZ : 0)); | ||
1099 | |||
1100 | board_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_DATA_SZ : \ | ||
1101 | (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_DATA_SZ : 0)); | ||
1102 | |||
1103 | /* Determine where in Target RAM to write Board Data */ | ||
1104 | bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), (u8 *)&board_ext_address, 4)); | ||
1105 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board extended Data download address: 0x%x\n", board_ext_address)); | ||
1106 | |||
1107 | /* check whether the target has allocated memory for extended board data and file contains extended board data */ | ||
1108 | if ((board_ext_address) && (*buf_len == (board_data_size + board_ext_data_size))) { | ||
1109 | u32 param; | ||
1110 | |||
1111 | status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(*buf + board_data_size), board_ext_data_size); | ||
1112 | |||
1113 | if (status) { | ||
1114 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); | ||
1115 | return A_ERROR; | ||
1116 | } | ||
1117 | |||
1118 | /* Record the fact that extended board Data IS initialized */ | ||
1119 | param = (board_ext_data_size << 16) | 1; | ||
1120 | bmifn(BMIWriteMemory(ar->arHifDevice, | ||
1121 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data_config), | ||
1122 | (unsigned char *)¶m, 4)); | ||
1123 | } | ||
1124 | fw_entry_size = board_data_size; | ||
1125 | } | ||
1126 | |||
1127 | if (compressed) { | ||
1128 | status = BMIFastDownload(ar->arHifDevice, address, *buf, fw_entry_size); | ||
1129 | } else { | ||
1130 | status = BMIWriteMemory(ar->arHifDevice, address, *buf, fw_entry_size); | ||
1131 | } | ||
1132 | |||
1133 | if (status) { | ||
1134 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); | ||
1135 | return A_ERROR; | ||
1136 | } | ||
1137 | |||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | int | ||
1142 | ar6000_update_bdaddr(struct ar6_softc *ar) | ||
1143 | { | ||
1144 | |||
1145 | if (setupbtdev != 0) { | ||
1146 | u32 address; | ||
1147 | |||
1148 | if (BMIReadMemory(ar->arHifDevice, | ||
1149 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4) != 0) | ||
1150 | { | ||
1151 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for hi_board_data failed\n")); | ||
1152 | return A_ERROR; | ||
1153 | } | ||
1154 | |||
1155 | if (BMIReadMemory(ar->arHifDevice, address + BDATA_BDADDR_OFFSET, (u8 *)ar->bdaddr, 6) != 0) | ||
1156 | { | ||
1157 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for BD address failed\n")); | ||
1158 | return A_ERROR; | ||
1159 | } | ||
1160 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BDADDR 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", ar->bdaddr[0], | ||
1161 | ar->bdaddr[1], ar->bdaddr[2], ar->bdaddr[3], | ||
1162 | ar->bdaddr[4], ar->bdaddr[5])); | ||
1163 | } | ||
1164 | |||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | int | ||
1169 | ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode) | ||
1170 | { | ||
1171 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Requesting device specific configuration\n")); | ||
1172 | |||
1173 | if (mode == WLAN_INIT_MODE_UDEV) { | ||
1174 | char version[16]; | ||
1175 | const struct firmware *fw_entry; | ||
1176 | |||
1177 | /* Get config using udev through a script in user space */ | ||
1178 | sprintf(version, "%2.2x", ar->arVersion.target_ver); | ||
1179 | if ((A_REQUEST_FIRMWARE(&fw_entry, version, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) | ||
1180 | { | ||
1181 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get configuration for target version: %s\n", version)); | ||
1182 | return A_ERROR; | ||
1183 | } | ||
1184 | |||
1185 | A_RELEASE_FIRMWARE(fw_entry); | ||
1186 | } else { | ||
1187 | /* The config is contained within the driver itself */ | ||
1188 | int status; | ||
1189 | u32 param, options, sleep, address; | ||
1190 | |||
1191 | /* Temporarily disable system sleep */ | ||
1192 | address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; | ||
1193 | bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); | ||
1194 | options = param; | ||
1195 | param |= AR6K_OPTION_SLEEP_DISABLE; | ||
1196 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1197 | |||
1198 | address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; | ||
1199 | bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); | ||
1200 | sleep = param; | ||
1201 | param |= WLAN_SYSTEM_SLEEP_DISABLE_SET(1); | ||
1202 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1203 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("old options: %d, old sleep: %d\n", options, sleep)); | ||
1204 | |||
1205 | if (ar->arTargetType == TARGET_TYPE_AR6003) { | ||
1206 | /* Program analog PLL register */ | ||
1207 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, ANALOG_INTF_BASE_ADDRESS + 0x284, 0xF9104001)); | ||
1208 | /* Run at 80/88MHz by default */ | ||
1209 | param = CPU_CLOCK_STANDARD_SET(1); | ||
1210 | } else { | ||
1211 | /* Run at 40/44MHz by default */ | ||
1212 | param = CPU_CLOCK_STANDARD_SET(0); | ||
1213 | } | ||
1214 | address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS; | ||
1215 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1216 | |||
1217 | param = 0; | ||
1218 | if (ar->arTargetType == TARGET_TYPE_AR6002) { | ||
1219 | bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)¶m, 4)); | ||
1220 | } | ||
1221 | |||
1222 | /* LPO_CAL.ENABLE = 1 if no external clk is detected */ | ||
1223 | if (param != 1) { | ||
1224 | address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS; | ||
1225 | param = LPO_CAL_ENABLE_SET(1); | ||
1226 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1227 | } | ||
1228 | |||
1229 | /* Venus2.0: Lower SDIO pad drive strength, | ||
1230 | * temporary WAR to avoid SDIO CRC error */ | ||
1231 | if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
1232 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6K: Temporary WAR to avoid SDIO CRC error\n")); | ||
1233 | param = 0x20; | ||
1234 | address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; | ||
1235 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1236 | |||
1237 | address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS; | ||
1238 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1239 | |||
1240 | address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS; | ||
1241 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1242 | |||
1243 | address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS; | ||
1244 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1245 | } | ||
1246 | |||
1247 | #ifdef FORCE_INTERNAL_CLOCK | ||
1248 | /* Ignore external clock, if any, and force use of internal clock */ | ||
1249 | if (ar->arTargetType == TARGET_TYPE_AR6003) { | ||
1250 | /* hi_ext_clk_detected = 0 */ | ||
1251 | param = 0; | ||
1252 | bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)¶m, 4)); | ||
1253 | |||
1254 | /* CLOCK_CONTROL &= ~LF_CLK32 */ | ||
1255 | address = RTC_BASE_ADDRESS + CLOCK_CONTROL_ADDRESS; | ||
1256 | bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); | ||
1257 | param &= (~CLOCK_CONTROL_LF_CLK32_SET(1)); | ||
1258 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1259 | } | ||
1260 | #endif /* FORCE_INTERNAL_CLOCK */ | ||
1261 | |||
1262 | /* Transfer Board Data from Target EEPROM to Target RAM */ | ||
1263 | if (ar->arTargetType == TARGET_TYPE_AR6003) { | ||
1264 | /* Determine where in Target RAM to write Board Data */ | ||
1265 | bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4)); | ||
1266 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board Data download address: 0x%x\n", address)); | ||
1267 | |||
1268 | /* Write EEPROM data to Target RAM */ | ||
1269 | if ((ar6000_transfer_bin_file(ar, AR6K_BOARD_DATA_FILE, address, false)) != 0) { | ||
1270 | return A_ERROR; | ||
1271 | } | ||
1272 | |||
1273 | /* Record the fact that Board Data IS initialized */ | ||
1274 | param = 1; | ||
1275 | bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data_initialized), (u8 *)¶m, 4)); | ||
1276 | |||
1277 | /* Transfer One time Programmable data */ | ||
1278 | AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver); | ||
1279 | if (ar->arVersion.target_ver == AR6003_REV3_VERSION) | ||
1280 | address = 0x1234; | ||
1281 | status = ar6000_transfer_bin_file(ar, AR6K_OTP_FILE, address, true); | ||
1282 | if (status == 0) { | ||
1283 | /* Execute the OTP code */ | ||
1284 | param = 0; | ||
1285 | AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver); | ||
1286 | bmifn(BMIExecute(ar->arHifDevice, address, ¶m)); | ||
1287 | } else if (status != A_ENOENT) { | ||
1288 | return A_ERROR; | ||
1289 | } | ||
1290 | } else { | ||
1291 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Programming of board data for chip %d not supported\n", ar->arTargetType)); | ||
1292 | return A_ERROR; | ||
1293 | } | ||
1294 | |||
1295 | /* Download Target firmware */ | ||
1296 | AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver); | ||
1297 | if (ar->arVersion.target_ver == AR6003_REV3_VERSION) | ||
1298 | address = 0x1234; | ||
1299 | if ((ar6000_transfer_bin_file(ar, AR6K_FIRMWARE_FILE, address, true)) != 0) { | ||
1300 | return A_ERROR; | ||
1301 | } | ||
1302 | |||
1303 | /* Set starting address for firmware */ | ||
1304 | AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver); | ||
1305 | bmifn(BMISetAppStart(ar->arHifDevice, address)); | ||
1306 | |||
1307 | if(ar->arTargetType == TARGET_TYPE_AR6003) { | ||
1308 | AR6K_DATASET_PATCH_ADDRESS(address, ar->arVersion.target_ver); | ||
1309 | if ((ar6000_transfer_bin_file(ar, AR6K_PATCH_FILE, | ||
1310 | address, false)) != 0) | ||
1311 | return A_ERROR; | ||
1312 | param = address; | ||
1313 | bmifn(BMIWriteMemory(ar->arHifDevice, | ||
1314 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_dset_list_head), | ||
1315 | (unsigned char *)¶m, 4)); | ||
1316 | } | ||
1317 | |||
1318 | /* Restore system sleep */ | ||
1319 | address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; | ||
1320 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, sleep)); | ||
1321 | |||
1322 | address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; | ||
1323 | param = options | 0x20; | ||
1324 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1325 | |||
1326 | if (ar->arTargetType == TARGET_TYPE_AR6003) { | ||
1327 | /* Configure GPIO AR6003 UART */ | ||
1328 | #ifndef CONFIG_AR600x_DEBUG_UART_TX_PIN | ||
1329 | #define CONFIG_AR600x_DEBUG_UART_TX_PIN 8 | ||
1330 | #endif | ||
1331 | param = CONFIG_AR600x_DEBUG_UART_TX_PIN; | ||
1332 | bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbg_uart_txpin), (u8 *)¶m, 4)); | ||
1333 | |||
1334 | #if (CONFIG_AR600x_DEBUG_UART_TX_PIN == 23) | ||
1335 | { | ||
1336 | address = GPIO_BASE_ADDRESS + CLOCK_GPIO_ADDRESS; | ||
1337 | bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); | ||
1338 | param |= CLOCK_GPIO_BT_CLK_OUT_EN_SET(1); | ||
1339 | bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); | ||
1340 | } | ||
1341 | #endif | ||
1342 | |||
1343 | /* Configure GPIO for BT Reset */ | ||
1344 | #ifdef ATH6KL_CONFIG_GPIO_BT_RESET | ||
1345 | #define CONFIG_AR600x_BT_RESET_PIN 0x16 | ||
1346 | param = CONFIG_AR600x_BT_RESET_PIN; | ||
1347 | bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_support_pins), (u8 *)¶m, 4)); | ||
1348 | #endif /* ATH6KL_CONFIG_GPIO_BT_RESET */ | ||
1349 | |||
1350 | /* Configure UART flow control polarity */ | ||
1351 | #ifndef CONFIG_ATH6KL_BT_UART_FC_POLARITY | ||
1352 | #define CONFIG_ATH6KL_BT_UART_FC_POLARITY 0 | ||
1353 | #endif | ||
1354 | |||
1355 | #if (CONFIG_ATH6KL_BT_UART_FC_POLARITY == 1) | ||
1356 | if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
1357 | param = ((CONFIG_ATH6KL_BT_UART_FC_POLARITY << 1) & 0x2); | ||
1358 | bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_pwr_mgmt_params), (u8 *)¶m, 4)); | ||
1359 | } | ||
1360 | #endif /* CONFIG_ATH6KL_BT_UART_FC_POLARITY */ | ||
1361 | } | ||
1362 | |||
1363 | #ifdef HTC_RAW_INTERFACE | ||
1364 | if (!eppingtest && bypasswmi) { | ||
1365 | /* Don't run BMIDone for ART mode and force resetok=0 */ | ||
1366 | resetok = 0; | ||
1367 | msleep(1000); | ||
1368 | } | ||
1369 | #endif /* HTC_RAW_INTERFACE */ | ||
1370 | } | ||
1371 | |||
1372 | return 0; | ||
1373 | } | ||
1374 | |||
1375 | int | ||
1376 | ar6000_configure_target(struct ar6_softc *ar) | ||
1377 | { | ||
1378 | u32 param; | ||
1379 | if (enableuartprint) { | ||
1380 | param = 1; | ||
1381 | if (BMIWriteMemory(ar->arHifDevice, | ||
1382 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable), | ||
1383 | (u8 *)¶m, | ||
1384 | 4)!= 0) | ||
1385 | { | ||
1386 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enableuartprint failed \n")); | ||
1387 | return A_ERROR; | ||
1388 | } | ||
1389 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Serial console prints enabled\n")); | ||
1390 | } | ||
1391 | |||
1392 | /* Tell target which HTC version it is used*/ | ||
1393 | param = HTC_PROTOCOL_VERSION; | ||
1394 | if (BMIWriteMemory(ar->arHifDevice, | ||
1395 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest), | ||
1396 | (u8 *)¶m, | ||
1397 | 4)!= 0) | ||
1398 | { | ||
1399 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for htc version failed \n")); | ||
1400 | return A_ERROR; | ||
1401 | } | ||
1402 | |||
1403 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
1404 | if(testmode) { | ||
1405 | ar->arTargetMode = AR6000_TCMD_MODE; | ||
1406 | }else { | ||
1407 | ar->arTargetMode = AR6000_WLAN_MODE; | ||
1408 | } | ||
1409 | #endif | ||
1410 | if (enabletimerwar) { | ||
1411 | u32 param; | ||
1412 | |||
1413 | if (BMIReadMemory(ar->arHifDevice, | ||
1414 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), | ||
1415 | (u8 *)¶m, | ||
1416 | 4)!= 0) | ||
1417 | { | ||
1418 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for enabletimerwar failed \n")); | ||
1419 | return A_ERROR; | ||
1420 | } | ||
1421 | |||
1422 | param |= HI_OPTION_TIMER_WAR; | ||
1423 | |||
1424 | if (BMIWriteMemory(ar->arHifDevice, | ||
1425 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), | ||
1426 | (u8 *)¶m, | ||
1427 | 4) != 0) | ||
1428 | { | ||
1429 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enabletimerwar failed \n")); | ||
1430 | return A_ERROR; | ||
1431 | } | ||
1432 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Timer WAR enabled\n")); | ||
1433 | } | ||
1434 | |||
1435 | /* set the firmware mode to STA/IBSS/AP */ | ||
1436 | { | ||
1437 | u32 param; | ||
1438 | |||
1439 | if (BMIReadMemory(ar->arHifDevice, | ||
1440 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), | ||
1441 | (u8 *)¶m, | ||
1442 | 4)!= 0) | ||
1443 | { | ||
1444 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for setting fwmode failed \n")); | ||
1445 | return A_ERROR; | ||
1446 | } | ||
1447 | |||
1448 | param |= (num_device << HI_OPTION_NUM_DEV_SHIFT); | ||
1449 | param |= (fwmode << HI_OPTION_FW_MODE_SHIFT); | ||
1450 | param |= (mac_addr_method << HI_OPTION_MAC_ADDR_METHOD_SHIFT); | ||
1451 | param |= (firmware_bridge << HI_OPTION_FW_BRIDGE_SHIFT); | ||
1452 | |||
1453 | |||
1454 | if (BMIWriteMemory(ar->arHifDevice, | ||
1455 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), | ||
1456 | (u8 *)¶m, | ||
1457 | 4) != 0) | ||
1458 | { | ||
1459 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for setting fwmode failed \n")); | ||
1460 | return A_ERROR; | ||
1461 | } | ||
1462 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n")); | ||
1463 | } | ||
1464 | |||
1465 | #ifdef ATH6KL_DISABLE_TARGET_DBGLOGS | ||
1466 | { | ||
1467 | u32 param; | ||
1468 | |||
1469 | if (BMIReadMemory(ar->arHifDevice, | ||
1470 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), | ||
1471 | (u8 *)¶m, | ||
1472 | 4)!= 0) | ||
1473 | { | ||
1474 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for disabling debug logs failed\n")); | ||
1475 | return A_ERROR; | ||
1476 | } | ||
1477 | |||
1478 | param |= HI_OPTION_DISABLE_DBGLOG; | ||
1479 | |||
1480 | if (BMIWriteMemory(ar->arHifDevice, | ||
1481 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), | ||
1482 | (u8 *)¶m, | ||
1483 | 4) != 0) | ||
1484 | { | ||
1485 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for HI_OPTION_DISABLE_DBGLOG\n")); | ||
1486 | return A_ERROR; | ||
1487 | } | ||
1488 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n")); | ||
1489 | } | ||
1490 | #endif /* ATH6KL_DISABLE_TARGET_DBGLOGS */ | ||
1491 | |||
1492 | /* | ||
1493 | * Hardcode the address use for the extended board data | ||
1494 | * Ideally this should be pre-allocate by the OS at boot time | ||
1495 | * But since it is a new feature and board data is loaded | ||
1496 | * at init time, we have to workaround this from host. | ||
1497 | * It is difficult to patch the firmware boot code, | ||
1498 | * but possible in theory. | ||
1499 | */ | ||
1500 | |||
1501 | if (ar->arTargetType == TARGET_TYPE_AR6003) { | ||
1502 | u32 ramReservedSz; | ||
1503 | if (ar->arVersion.target_ver == AR6003_REV2_VERSION) { | ||
1504 | param = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; | ||
1505 | ramReservedSz = AR6003_REV2_RAM_RESERVE_SIZE; | ||
1506 | } else { | ||
1507 | param = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; | ||
1508 | ramReservedSz = AR6003_REV3_RAM_RESERVE_SIZE; | ||
1509 | } | ||
1510 | if (BMIWriteMemory(ar->arHifDevice, | ||
1511 | HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), | ||
1512 | (u8 *)¶m, 4) != 0) { | ||
1513 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
1514 | ("BMIWriteMemory for " | ||
1515 | "hi_board_ext_data failed\n")); | ||
1516 | return A_ERROR; | ||
1517 | } | ||
1518 | if (BMIWriteMemory(ar->arHifDevice, | ||
1519 | HOST_INTEREST_ITEM_ADDRESS(ar, | ||
1520 | hi_end_RAM_reserve_sz), | ||
1521 | (u8 *)&ramReservedSz, 4) != 0) { | ||
1522 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR , | ||
1523 | ("BMIWriteMemory for " | ||
1524 | "hi_end_RAM_reserve_sz failed\n")); | ||
1525 | return A_ERROR; | ||
1526 | } | ||
1527 | } | ||
1528 | |||
1529 | /* since BMIInit is called in the driver layer, we have to set the block | ||
1530 | * size here for the target */ | ||
1531 | |||
1532 | if (ar6000_set_htc_params(ar->arHifDevice, ar->arTargetType, | ||
1533 | mbox_yield_limit, 0)) { | ||
1534 | /* use default number of control buffers */ | ||
1535 | return A_ERROR; | ||
1536 | } | ||
1537 | |||
1538 | if (setupbtdev != 0) { | ||
1539 | if (ar6000_set_hci_bridge_flags(ar->arHifDevice, | ||
1540 | ar->arTargetType, | ||
1541 | setupbtdev)) { | ||
1542 | return A_ERROR; | ||
1543 | } | ||
1544 | } | ||
1545 | return 0; | ||
1546 | } | ||
1547 | |||
1548 | static void | ||
1549 | init_netdev(struct net_device *dev, char *name) | ||
1550 | { | ||
1551 | dev->netdev_ops = &ar6000_netdev_ops; | ||
1552 | dev->watchdog_timeo = AR6000_TX_TIMEOUT; | ||
1553 | |||
1554 | /* | ||
1555 | * We need the OS to provide us with more headroom in order to | ||
1556 | * perform dix to 802.3, WMI header encap, and the HTC header | ||
1557 | */ | ||
1558 | if (processDot11Hdr) { | ||
1559 | dev->hard_header_len = sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX_HACK_FUDGE_FACTOR; | ||
1560 | } else { | ||
1561 | dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) + | ||
1562 | sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX_HACK_FUDGE_FACTOR; | ||
1563 | } | ||
1564 | |||
1565 | if (name[0]) | ||
1566 | { | ||
1567 | strcpy(dev->name, name); | ||
1568 | } | ||
1569 | |||
1570 | #ifdef CONFIG_CHECKSUM_OFFLOAD | ||
1571 | if(csumOffload){ | ||
1572 | dev->features |= NETIF_F_IP_CSUM; /*advertise kernel capability to do TCP/UDP CSUM offload for IPV4*/ | ||
1573 | } | ||
1574 | #endif | ||
1575 | |||
1576 | return; | ||
1577 | } | ||
1578 | |||
1579 | static int __ath6kl_init_netdev(struct net_device *dev) | ||
1580 | { | ||
1581 | int r; | ||
1582 | |||
1583 | rtnl_lock(); | ||
1584 | r = ar6000_init(dev); | ||
1585 | rtnl_unlock(); | ||
1586 | |||
1587 | if (r) { | ||
1588 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_init\n")); | ||
1589 | return r; | ||
1590 | } | ||
1591 | |||
1592 | return 0; | ||
1593 | } | ||
1594 | |||
1595 | #ifdef HTC_RAW_INTERFACE | ||
1596 | static int ath6kl_init_netdev_wmi(struct net_device *dev) | ||
1597 | { | ||
1598 | if (!eppingtest && bypasswmi) | ||
1599 | return 0; | ||
1600 | |||
1601 | return __ath6kl_init_netdev(dev); | ||
1602 | } | ||
1603 | #else | ||
1604 | static int ath6kl_init_netdev_wmi(struct net_device *dev) | ||
1605 | { | ||
1606 | return __ath6kl_init_netdev(dev); | ||
1607 | } | ||
1608 | #endif | ||
1609 | |||
1610 | static int ath6kl_init_netdev(struct ar6_softc *ar) | ||
1611 | { | ||
1612 | int r; | ||
1613 | |||
1614 | r = ar6000_sysfs_bmi_get_config(ar, wlaninitmode); | ||
1615 | if (r) { | ||
1616 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
1617 | ("ar6000_avail: " | ||
1618 | "ar6000_sysfs_bmi_get_config failed\n")); | ||
1619 | return r; | ||
1620 | } | ||
1621 | |||
1622 | return ath6kl_init_netdev_wmi(ar->arNetDev); | ||
1623 | } | ||
1624 | |||
1625 | /* | ||
1626 | * HTC Event handlers | ||
1627 | */ | ||
1628 | static int | ||
1629 | ar6000_avail_ev(void *context, void *hif_handle) | ||
1630 | { | ||
1631 | int i; | ||
1632 | struct net_device *dev; | ||
1633 | void *ar_netif; | ||
1634 | struct ar6_softc *ar; | ||
1635 | int device_index = 0; | ||
1636 | struct htc_init_info htcInfo; | ||
1637 | struct wireless_dev *wdev; | ||
1638 | int r = 0; | ||
1639 | struct hif_device_os_device_info osDevInfo; | ||
1640 | |||
1641 | memset(&osDevInfo, 0, sizeof(osDevInfo)); | ||
1642 | if (HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_OS_DEVICE, | ||
1643 | &osDevInfo, sizeof(osDevInfo))) { | ||
1644 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Failed to get OS device instance\n", __func__)); | ||
1645 | return A_ERROR; | ||
1646 | } | ||
1647 | |||
1648 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_available\n")); | ||
1649 | |||
1650 | for (i=0; i < MAX_AR6000; i++) { | ||
1651 | if (ar6000_devices[i] == NULL) { | ||
1652 | break; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | if (i == MAX_AR6000) { | ||
1657 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_available: max devices reached\n")); | ||
1658 | return A_ERROR; | ||
1659 | } | ||
1660 | |||
1661 | /* Save this. It gives a bit better readability especially since */ | ||
1662 | /* we use another local "i" variable below. */ | ||
1663 | device_index = i; | ||
1664 | |||
1665 | wdev = ar6k_cfg80211_init(osDevInfo.pOSDevice); | ||
1666 | if (IS_ERR(wdev)) { | ||
1667 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ar6k_cfg80211_init failed\n", __func__)); | ||
1668 | return A_ERROR; | ||
1669 | } | ||
1670 | ar_netif = wdev_priv(wdev); | ||
1671 | |||
1672 | if (ar_netif == NULL) { | ||
1673 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Can't allocate ar6k priv memory\n", __func__)); | ||
1674 | return A_ERROR; | ||
1675 | } | ||
1676 | |||
1677 | A_MEMZERO(ar_netif, sizeof(struct ar6_softc)); | ||
1678 | ar = (struct ar6_softc *)ar_netif; | ||
1679 | |||
1680 | ar->wdev = wdev; | ||
1681 | wdev->iftype = NL80211_IFTYPE_STATION; | ||
1682 | |||
1683 | dev = alloc_netdev_mq(0, "wlan%d", ether_setup, 1); | ||
1684 | if (!dev) { | ||
1685 | printk(KERN_CRIT "AR6K: no memory for network device instance\n"); | ||
1686 | ar6k_cfg80211_deinit(ar); | ||
1687 | return A_ERROR; | ||
1688 | } | ||
1689 | |||
1690 | dev->ieee80211_ptr = wdev; | ||
1691 | SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); | ||
1692 | wdev->netdev = dev; | ||
1693 | ar->arNetworkType = INFRA_NETWORK; | ||
1694 | ar->smeState = SME_DISCONNECTED; | ||
1695 | ar->arAutoAuthStage = AUTH_IDLE; | ||
1696 | |||
1697 | init_netdev(dev, ifname); | ||
1698 | |||
1699 | |||
1700 | ar->arNetDev = dev; | ||
1701 | ar->arHifDevice = hif_handle; | ||
1702 | ar->arWlanState = WLAN_ENABLED; | ||
1703 | ar->arDeviceIndex = device_index; | ||
1704 | |||
1705 | ar->arWlanPowerState = WLAN_POWER_STATE_ON; | ||
1706 | ar->arWlanOff = false; /* We are in ON state */ | ||
1707 | #ifdef CONFIG_PM | ||
1708 | ar->arWowState = WLAN_WOW_STATE_NONE; | ||
1709 | ar->arBTOff = true; /* BT chip assumed to be OFF */ | ||
1710 | ar->arBTSharing = WLAN_CONFIG_BT_SHARING; | ||
1711 | ar->arWlanOffConfig = WLAN_CONFIG_WLAN_OFF; | ||
1712 | ar->arSuspendConfig = WLAN_CONFIG_PM_SUSPEND; | ||
1713 | ar->arWow2Config = WLAN_CONFIG_PM_WOW2; | ||
1714 | #endif /* CONFIG_PM */ | ||
1715 | |||
1716 | A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev); | ||
1717 | ar->arHBChallengeResp.seqNum = 0; | ||
1718 | ar->arHBChallengeResp.outstanding = false; | ||
1719 | ar->arHBChallengeResp.missCnt = 0; | ||
1720 | ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT; | ||
1721 | ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT; | ||
1722 | |||
1723 | ar6000_init_control_info(ar); | ||
1724 | init_waitqueue_head(&arEvent); | ||
1725 | sema_init(&ar->arSem, 1); | ||
1726 | ar->bIsDestroyProgress = false; | ||
1727 | |||
1728 | INIT_HTC_PACKET_QUEUE(&ar->amsdu_rx_buffer_queue); | ||
1729 | |||
1730 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
1731 | A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar); | ||
1732 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
1733 | |||
1734 | A_INIT_TIMER(&ar->disconnect_timer, disconnect_timer_handler, dev); | ||
1735 | |||
1736 | BMIInit(); | ||
1737 | |||
1738 | ar6000_sysfs_bmi_init(ar); | ||
1739 | |||
1740 | { | ||
1741 | struct bmi_target_info targ_info; | ||
1742 | |||
1743 | r = BMIGetTargetInfo(ar->arHifDevice, &targ_info); | ||
1744 | if (r) | ||
1745 | goto avail_ev_failed; | ||
1746 | |||
1747 | ar->arVersion.target_ver = targ_info.target_ver; | ||
1748 | ar->arTargetType = targ_info.target_type; | ||
1749 | wdev->wiphy->hw_version = targ_info.target_ver; | ||
1750 | } | ||
1751 | |||
1752 | r = ar6000_configure_target(ar); | ||
1753 | if (r) | ||
1754 | goto avail_ev_failed; | ||
1755 | |||
1756 | A_MEMZERO(&htcInfo,sizeof(htcInfo)); | ||
1757 | htcInfo.pContext = ar; | ||
1758 | htcInfo.TargetFailure = ar6000_target_failure; | ||
1759 | |||
1760 | ar->arHtcTarget = HTCCreate(ar->arHifDevice,&htcInfo); | ||
1761 | |||
1762 | if (!ar->arHtcTarget) { | ||
1763 | r = -ENOMEM; | ||
1764 | goto avail_ev_failed; | ||
1765 | } | ||
1766 | |||
1767 | spin_lock_init(&ar->arLock); | ||
1768 | |||
1769 | #ifdef WAPI_ENABLE | ||
1770 | ar->arWapiEnable = 0; | ||
1771 | #endif | ||
1772 | |||
1773 | |||
1774 | if(csumOffload){ | ||
1775 | /*if external frame work is also needed, change and use an extended rxMetaVerion*/ | ||
1776 | ar->rxMetaVersion=WMI_META_VERSION_2; | ||
1777 | } | ||
1778 | |||
1779 | ar->aggr_cntxt = aggr_init(ar6000_alloc_netbufs); | ||
1780 | if (!ar->aggr_cntxt) { | ||
1781 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize aggr.\n", __func__)); | ||
1782 | r = -ENOMEM; | ||
1783 | goto avail_ev_failed; | ||
1784 | } | ||
1785 | |||
1786 | aggr_register_rx_dispatcher(ar->aggr_cntxt, (void *)dev, ar6000_deliver_frames_to_nw_stack); | ||
1787 | |||
1788 | HIFClaimDevice(ar->arHifDevice, ar); | ||
1789 | |||
1790 | /* We only register the device in the global list if we succeed. */ | ||
1791 | /* If the device is in the global list, it will be destroyed */ | ||
1792 | /* when the module is unloaded. */ | ||
1793 | ar6000_devices[device_index] = dev; | ||
1794 | |||
1795 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("BMI enabled: %d\n", wlaninitmode)); | ||
1796 | if ((wlaninitmode == WLAN_INIT_MODE_UDEV) || | ||
1797 | (wlaninitmode == WLAN_INIT_MODE_DRV)) { | ||
1798 | r = ath6kl_init_netdev(ar); | ||
1799 | if (r) | ||
1800 | goto avail_ev_failed; | ||
1801 | } | ||
1802 | |||
1803 | /* This runs the init function if registered */ | ||
1804 | r = register_netdev(dev); | ||
1805 | if (r) { | ||
1806 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: register_netdev failed\n")); | ||
1807 | ar6000_destroy(dev, 0); | ||
1808 | return r; | ||
1809 | } | ||
1810 | |||
1811 | is_netdev_registered = 1; | ||
1812 | |||
1813 | #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT | ||
1814 | arApNetDev = NULL; | ||
1815 | #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ | ||
1816 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_avail: name=%s hifdevice=0x%lx, dev=0x%lx (%d), ar=0x%lx\n", | ||
1817 | dev->name, (unsigned long)ar->arHifDevice, (unsigned long)dev, device_index, | ||
1818 | (unsigned long)ar)); | ||
1819 | |||
1820 | avail_ev_failed : | ||
1821 | if (r) | ||
1822 | ar6000_sysfs_bmi_deinit(ar); | ||
1823 | |||
1824 | return r; | ||
1825 | } | ||
1826 | |||
1827 | static void ar6000_target_failure(void *Instance, int Status) | ||
1828 | { | ||
1829 | struct ar6_softc *ar = (struct ar6_softc *)Instance; | ||
1830 | WMI_TARGET_ERROR_REPORT_EVENT errEvent; | ||
1831 | static bool sip = false; | ||
1832 | |||
1833 | if (Status != 0) { | ||
1834 | |||
1835 | printk(KERN_ERR "ar6000_target_failure: target asserted \n"); | ||
1836 | |||
1837 | if (timer_pending(&ar->arHBChallengeResp.timer)) { | ||
1838 | A_UNTIMEOUT(&ar->arHBChallengeResp.timer); | ||
1839 | } | ||
1840 | |||
1841 | /* try dumping target assertion information (if any) */ | ||
1842 | ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType); | ||
1843 | |||
1844 | /* | ||
1845 | * Fetch the logs from the target via the diagnostic | ||
1846 | * window. | ||
1847 | */ | ||
1848 | ar6000_dbglog_get_debug_logs(ar); | ||
1849 | |||
1850 | /* Report the error only once */ | ||
1851 | if (!sip) { | ||
1852 | sip = true; | ||
1853 | errEvent.errorVal = WMI_TARGET_COM_ERR | | ||
1854 | WMI_TARGET_FATAL_ERR; | ||
1855 | } | ||
1856 | } | ||
1857 | } | ||
1858 | |||
1859 | static int | ||
1860 | ar6000_unavail_ev(void *context, void *hif_handle) | ||
1861 | { | ||
1862 | struct ar6_softc *ar = (struct ar6_softc *)context; | ||
1863 | /* NULL out it's entry in the global list */ | ||
1864 | ar6000_devices[ar->arDeviceIndex] = NULL; | ||
1865 | ar6000_destroy(ar->arNetDev, 1); | ||
1866 | |||
1867 | return 0; | ||
1868 | } | ||
1869 | |||
1870 | void | ||
1871 | ar6000_restart_endpoint(struct net_device *dev) | ||
1872 | { | ||
1873 | int status = 0; | ||
1874 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
1875 | |||
1876 | BMIInit(); | ||
1877 | do { | ||
1878 | if ( (status=ar6000_configure_target(ar))!= 0) | ||
1879 | break; | ||
1880 | if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != 0) | ||
1881 | { | ||
1882 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_bmi_get_config failed\n")); | ||
1883 | break; | ||
1884 | } | ||
1885 | rtnl_lock(); | ||
1886 | status = (ar6000_init(dev)==0) ? 0 : A_ERROR; | ||
1887 | rtnl_unlock(); | ||
1888 | |||
1889 | if (status) { | ||
1890 | break; | ||
1891 | } | ||
1892 | if (ar->arSsidLen && ar->arWlanState == WLAN_ENABLED) { | ||
1893 | ar6000_connect_to_ap(ar); | ||
1894 | } | ||
1895 | } while (0); | ||
1896 | |||
1897 | if (status== 0) { | ||
1898 | return; | ||
1899 | } | ||
1900 | |||
1901 | ar6000_devices[ar->arDeviceIndex] = NULL; | ||
1902 | ar6000_destroy(ar->arNetDev, 1); | ||
1903 | } | ||
1904 | |||
1905 | void | ||
1906 | ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs) | ||
1907 | { | ||
1908 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
1909 | |||
1910 | /* Stop the transmit queues */ | ||
1911 | netif_stop_queue(dev); | ||
1912 | |||
1913 | /* Disable the target and the interrupts associated with it */ | ||
1914 | if (ar->arWmiReady == true) | ||
1915 | { | ||
1916 | if (!bypasswmi) | ||
1917 | { | ||
1918 | bool disconnectIssued; | ||
1919 | |||
1920 | disconnectIssued = (ar->arConnected) || (ar->arConnectPending); | ||
1921 | ar6000_disconnect(ar); | ||
1922 | if (!keepprofile) { | ||
1923 | ar6000_init_profile_info(ar); | ||
1924 | } | ||
1925 | |||
1926 | A_UNTIMEOUT(&ar->disconnect_timer); | ||
1927 | |||
1928 | if (getdbglogs) { | ||
1929 | ar6000_dbglog_get_debug_logs(ar); | ||
1930 | } | ||
1931 | |||
1932 | ar->arWmiReady = false; | ||
1933 | wmi_shutdown(ar->arWmi); | ||
1934 | ar->arWmiEnabled = false; | ||
1935 | ar->arWmi = NULL; | ||
1936 | /* | ||
1937 | * After wmi_shudown all WMI events will be dropped. | ||
1938 | * We need to cleanup the buffers allocated in AP mode | ||
1939 | * and give disconnect notification to stack, which usually | ||
1940 | * happens in the disconnect_event. | ||
1941 | * Simulate the disconnect_event by calling the function directly. | ||
1942 | * Sometimes disconnect_event will be received when the debug logs | ||
1943 | * are collected. | ||
1944 | */ | ||
1945 | if (disconnectIssued) { | ||
1946 | if(ar->arNetworkType & AP_NETWORK) { | ||
1947 | ar6000_disconnect_event(ar, DISCONNECT_CMD, bcast_mac, 0, NULL, 0); | ||
1948 | } else { | ||
1949 | ar6000_disconnect_event(ar, DISCONNECT_CMD, ar->arBssid, 0, NULL, 0); | ||
1950 | } | ||
1951 | } | ||
1952 | ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; | ||
1953 | ar->user_key_ctrl = 0; | ||
1954 | } | ||
1955 | |||
1956 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI stopped\n", __func__)); | ||
1957 | } | ||
1958 | else | ||
1959 | { | ||
1960 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI not ready 0x%lx 0x%lx\n", | ||
1961 | __func__, (unsigned long) ar, (unsigned long) ar->arWmi)); | ||
1962 | |||
1963 | /* Shut down WMI if we have started it */ | ||
1964 | if(ar->arWmiEnabled == true) | ||
1965 | { | ||
1966 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Shut down WMI\n", __func__)); | ||
1967 | wmi_shutdown(ar->arWmi); | ||
1968 | ar->arWmiEnabled = false; | ||
1969 | ar->arWmi = NULL; | ||
1970 | } | ||
1971 | } | ||
1972 | |||
1973 | if (ar->arHtcTarget != NULL) { | ||
1974 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
1975 | if (NULL != ar6kHciTransCallbacks.cleanupTransport) { | ||
1976 | ar6kHciTransCallbacks.cleanupTransport(NULL); | ||
1977 | } | ||
1978 | #else | ||
1979 | // FIXME: workaround to reset BT's UART baud rate to default | ||
1980 | if (NULL != ar->exitCallback) { | ||
1981 | struct ar3k_config_info ar3kconfig; | ||
1982 | int status; | ||
1983 | |||
1984 | A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig)); | ||
1985 | ar6000_set_default_ar3kconfig(ar, (void *)&ar3kconfig); | ||
1986 | status = ar->exitCallback(&ar3kconfig); | ||
1987 | if (0 != status) { | ||
1988 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to reset AR3K baud rate! \n")); | ||
1989 | } | ||
1990 | } | ||
1991 | // END workaround | ||
1992 | if (setuphci) | ||
1993 | ar6000_cleanup_hci(ar); | ||
1994 | #endif | ||
1995 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Shutting down HTC .... \n")); | ||
1996 | /* stop HTC */ | ||
1997 | HTCStop(ar->arHtcTarget); | ||
1998 | } | ||
1999 | |||
2000 | if (resetok) { | ||
2001 | /* try to reset the device if we can | ||
2002 | * The driver may have been configure NOT to reset the target during | ||
2003 | * a debug session */ | ||
2004 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Attempting to reset target on instance destroy.... \n")); | ||
2005 | if (ar->arHifDevice != NULL) { | ||
2006 | bool coldReset = (ar->arTargetType == TARGET_TYPE_AR6003) ? true: false; | ||
2007 | ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, coldReset); | ||
2008 | } | ||
2009 | } else { | ||
2010 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Host does not want target reset. \n")); | ||
2011 | } | ||
2012 | /* Done with cookies */ | ||
2013 | ar6000_cookie_cleanup(ar); | ||
2014 | |||
2015 | /* cleanup any allocated AMSDU buffers */ | ||
2016 | ar6000_cleanup_amsdu_rxbufs(ar); | ||
2017 | } | ||
2018 | /* | ||
2019 | * We need to differentiate between the surprise and planned removal of the | ||
2020 | * device because of the following consideration: | ||
2021 | * - In case of surprise removal, the hcd already frees up the pending | ||
2022 | * for the device and hence there is no need to unregister the function | ||
2023 | * driver inorder to get these requests. For planned removal, the function | ||
2024 | * driver has to explicitly unregister itself to have the hcd return all the | ||
2025 | * pending requests before the data structures for the devices are freed up. | ||
2026 | * Note that as per the current implementation, the function driver will | ||
2027 | * end up releasing all the devices since there is no API to selectively | ||
2028 | * release a particular device. | ||
2029 | * - Certain commands issued to the target can be skipped for surprise | ||
2030 | * removal since they will anyway not go through. | ||
2031 | */ | ||
2032 | void | ||
2033 | ar6000_destroy(struct net_device *dev, unsigned int unregister) | ||
2034 | { | ||
2035 | struct ar6_softc *ar; | ||
2036 | |||
2037 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("+ar6000_destroy \n")); | ||
2038 | |||
2039 | if((dev == NULL) || ((ar = ar6k_priv(dev)) == NULL)) | ||
2040 | { | ||
2041 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): Failed to get device structure.\n", __func__)); | ||
2042 | return; | ||
2043 | } | ||
2044 | |||
2045 | ar->bIsDestroyProgress = true; | ||
2046 | |||
2047 | if (down_interruptible(&ar->arSem)) { | ||
2048 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): down_interruptible failed \n", __func__)); | ||
2049 | return; | ||
2050 | } | ||
2051 | |||
2052 | if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) { | ||
2053 | /* only stop endpoint if we are not stop it in suspend_ev */ | ||
2054 | ar6000_stop_endpoint(dev, false, true); | ||
2055 | } | ||
2056 | |||
2057 | ar->arWlanState = WLAN_DISABLED; | ||
2058 | if (ar->arHtcTarget != NULL) { | ||
2059 | /* destroy HTC */ | ||
2060 | HTCDestroy(ar->arHtcTarget); | ||
2061 | } | ||
2062 | if (ar->arHifDevice != NULL) { | ||
2063 | /*release the device so we do not get called back on remove incase we | ||
2064 | * we're explicity destroyed by module unload */ | ||
2065 | HIFReleaseDevice(ar->arHifDevice); | ||
2066 | HIFShutDownDevice(ar->arHifDevice); | ||
2067 | } | ||
2068 | aggr_module_destroy(ar->aggr_cntxt); | ||
2069 | |||
2070 | /* Done with cookies */ | ||
2071 | ar6000_cookie_cleanup(ar); | ||
2072 | |||
2073 | /* cleanup any allocated AMSDU buffers */ | ||
2074 | ar6000_cleanup_amsdu_rxbufs(ar); | ||
2075 | |||
2076 | ar6000_sysfs_bmi_deinit(ar); | ||
2077 | |||
2078 | /* Cleanup BMI */ | ||
2079 | BMICleanup(); | ||
2080 | |||
2081 | /* Clear the tx counters */ | ||
2082 | memset(tx_attempt, 0, sizeof(tx_attempt)); | ||
2083 | memset(tx_post, 0, sizeof(tx_post)); | ||
2084 | memset(tx_complete, 0, sizeof(tx_complete)); | ||
2085 | |||
2086 | #ifdef HTC_RAW_INTERFACE | ||
2087 | if (ar->arRawHtc) { | ||
2088 | kfree(ar->arRawHtc); | ||
2089 | ar->arRawHtc = NULL; | ||
2090 | } | ||
2091 | #endif | ||
2092 | /* Free up the device data structure */ | ||
2093 | if (unregister && is_netdev_registered) { | ||
2094 | unregister_netdev(dev); | ||
2095 | is_netdev_registered = 0; | ||
2096 | } | ||
2097 | free_netdev(dev); | ||
2098 | |||
2099 | ar6k_cfg80211_deinit(ar); | ||
2100 | |||
2101 | #ifdef CONFIG_AP_VIRTUL_ADAPTER_SUPPORT | ||
2102 | ar6000_remove_ap_interface(); | ||
2103 | #endif /*CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ | ||
2104 | |||
2105 | kfree(ar->fw_otp); | ||
2106 | kfree(ar->fw); | ||
2107 | kfree(ar->fw_patch); | ||
2108 | kfree(ar->fw_data); | ||
2109 | |||
2110 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("-ar6000_destroy \n")); | ||
2111 | } | ||
2112 | |||
2113 | static void disconnect_timer_handler(unsigned long ptr) | ||
2114 | { | ||
2115 | struct net_device *dev = (struct net_device *)ptr; | ||
2116 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
2117 | |||
2118 | A_UNTIMEOUT(&ar->disconnect_timer); | ||
2119 | |||
2120 | ar6000_init_profile_info(ar); | ||
2121 | ar6000_disconnect(ar); | ||
2122 | } | ||
2123 | |||
2124 | static void ar6000_detect_error(unsigned long ptr) | ||
2125 | { | ||
2126 | struct net_device *dev = (struct net_device *)ptr; | ||
2127 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
2128 | WMI_TARGET_ERROR_REPORT_EVENT errEvent; | ||
2129 | |||
2130 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
2131 | |||
2132 | if (ar->arHBChallengeResp.outstanding) { | ||
2133 | ar->arHBChallengeResp.missCnt++; | ||
2134 | } else { | ||
2135 | ar->arHBChallengeResp.missCnt = 0; | ||
2136 | } | ||
2137 | |||
2138 | if (ar->arHBChallengeResp.missCnt > ar->arHBChallengeResp.missThres) { | ||
2139 | /* Send Error Detect event to the application layer and do not reschedule the error detection module timer */ | ||
2140 | ar->arHBChallengeResp.missCnt = 0; | ||
2141 | ar->arHBChallengeResp.seqNum = 0; | ||
2142 | errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR; | ||
2143 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
2144 | return; | ||
2145 | } | ||
2146 | |||
2147 | /* Generate the sequence number for the next challenge */ | ||
2148 | ar->arHBChallengeResp.seqNum++; | ||
2149 | ar->arHBChallengeResp.outstanding = true; | ||
2150 | |||
2151 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
2152 | |||
2153 | /* Send the challenge on the control channel */ | ||
2154 | if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != 0) { | ||
2155 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to send heart beat challenge\n")); | ||
2156 | } | ||
2157 | |||
2158 | |||
2159 | /* Reschedule the timer for the next challenge */ | ||
2160 | A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0); | ||
2161 | } | ||
2162 | |||
2163 | void ar6000_init_profile_info(struct ar6_softc *ar) | ||
2164 | { | ||
2165 | ar->arSsidLen = 0; | ||
2166 | A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); | ||
2167 | |||
2168 | switch(fwmode) { | ||
2169 | case HI_OPTION_FW_MODE_IBSS: | ||
2170 | ar->arNetworkType = ar->arNextMode = ADHOC_NETWORK; | ||
2171 | break; | ||
2172 | case HI_OPTION_FW_MODE_BSS_STA: | ||
2173 | ar->arNetworkType = ar->arNextMode = INFRA_NETWORK; | ||
2174 | break; | ||
2175 | case HI_OPTION_FW_MODE_AP: | ||
2176 | ar->arNetworkType = ar->arNextMode = AP_NETWORK; | ||
2177 | break; | ||
2178 | } | ||
2179 | |||
2180 | ar->arDot11AuthMode = OPEN_AUTH; | ||
2181 | ar->arAuthMode = NONE_AUTH; | ||
2182 | ar->arPairwiseCrypto = NONE_CRYPT; | ||
2183 | ar->arPairwiseCryptoLen = 0; | ||
2184 | ar->arGroupCrypto = NONE_CRYPT; | ||
2185 | ar->arGroupCryptoLen = 0; | ||
2186 | A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); | ||
2187 | A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); | ||
2188 | A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); | ||
2189 | ar->arBssChannel = 0; | ||
2190 | } | ||
2191 | |||
2192 | static void | ||
2193 | ar6000_init_control_info(struct ar6_softc *ar) | ||
2194 | { | ||
2195 | ar->arWmiEnabled = false; | ||
2196 | ar6000_init_profile_info(ar); | ||
2197 | ar->arDefTxKeyIndex = 0; | ||
2198 | A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); | ||
2199 | ar->arChannelHint = 0; | ||
2200 | ar->arListenIntervalT = A_DEFAULT_LISTEN_INTERVAL; | ||
2201 | ar->arListenIntervalB = 0; | ||
2202 | ar->arVersion.host_ver = AR6K_SW_VERSION; | ||
2203 | ar->arRssi = 0; | ||
2204 | ar->arTxPwr = 0; | ||
2205 | ar->arTxPwrSet = false; | ||
2206 | ar->arSkipScan = 0; | ||
2207 | ar->arBeaconInterval = 0; | ||
2208 | ar->arBitRate = 0; | ||
2209 | ar->arMaxRetries = 0; | ||
2210 | ar->arWmmEnabled = true; | ||
2211 | ar->intra_bss = 1; | ||
2212 | ar->scan_triggered = 0; | ||
2213 | A_MEMZERO(&ar->scParams, sizeof(ar->scParams)); | ||
2214 | ar->scParams.shortScanRatio = WMI_SHORTSCANRATIO_DEFAULT; | ||
2215 | ar->scParams.scanCtrlFlags = DEFAULT_SCAN_CTRL_FLAGS; | ||
2216 | |||
2217 | /* Initialize the AP mode state info */ | ||
2218 | { | ||
2219 | u8 ctr; | ||
2220 | A_MEMZERO((u8 *)ar->sta_list, AP_MAX_NUM_STA * sizeof(sta_t)); | ||
2221 | |||
2222 | /* init the Mutexes */ | ||
2223 | A_MUTEX_INIT(&ar->mcastpsqLock); | ||
2224 | |||
2225 | /* Init the PS queues */ | ||
2226 | for (ctr=0; ctr < AP_MAX_NUM_STA ; ctr++) { | ||
2227 | A_MUTEX_INIT(&ar->sta_list[ctr].psqLock); | ||
2228 | A_NETBUF_QUEUE_INIT(&ar->sta_list[ctr].psq); | ||
2229 | } | ||
2230 | |||
2231 | ar->ap_profile_flag = 0; | ||
2232 | A_NETBUF_QUEUE_INIT(&ar->mcastpsq); | ||
2233 | |||
2234 | memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); | ||
2235 | ar->ap_wmode = DEF_AP_WMODE_G; | ||
2236 | ar->ap_dtim_period = DEF_AP_DTIM; | ||
2237 | ar->ap_beacon_interval = DEF_BEACON_INTERVAL; | ||
2238 | } | ||
2239 | } | ||
2240 | |||
2241 | static int | ||
2242 | ar6000_open(struct net_device *dev) | ||
2243 | { | ||
2244 | unsigned long flags; | ||
2245 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
2246 | |||
2247 | spin_lock_irqsave(&ar->arLock, flags); | ||
2248 | |||
2249 | if(ar->arWlanState == WLAN_DISABLED) { | ||
2250 | ar->arWlanState = WLAN_ENABLED; | ||
2251 | } | ||
2252 | |||
2253 | if( ar->arConnected || bypasswmi) { | ||
2254 | netif_carrier_on(dev); | ||
2255 | /* Wake up the queues */ | ||
2256 | netif_wake_queue(dev); | ||
2257 | } | ||
2258 | else | ||
2259 | netif_carrier_off(dev); | ||
2260 | |||
2261 | spin_unlock_irqrestore(&ar->arLock, flags); | ||
2262 | return 0; | ||
2263 | } | ||
2264 | |||
2265 | static int | ||
2266 | ar6000_close(struct net_device *dev) | ||
2267 | { | ||
2268 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
2269 | netif_stop_queue(dev); | ||
2270 | |||
2271 | ar6000_disconnect(ar); | ||
2272 | |||
2273 | if(ar->arWmiReady == true) { | ||
2274 | if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, | ||
2275 | 0, 0, 0, 0, 0, 0, 0, 0) != 0) { | ||
2276 | return -EIO; | ||
2277 | } | ||
2278 | ar->arWlanState = WLAN_DISABLED; | ||
2279 | } | ||
2280 | ar6k_cfg80211_scanComplete_event(ar, A_ECANCELED); | ||
2281 | |||
2282 | return 0; | ||
2283 | } | ||
2284 | |||
2285 | /* connect to a service */ | ||
2286 | static int ar6000_connectservice(struct ar6_softc *ar, | ||
2287 | struct htc_service_connect_req *pConnect, | ||
2288 | char *pDesc) | ||
2289 | { | ||
2290 | int status; | ||
2291 | struct htc_service_connect_resp response; | ||
2292 | |||
2293 | do { | ||
2294 | |||
2295 | A_MEMZERO(&response,sizeof(response)); | ||
2296 | |||
2297 | status = HTCConnectService(ar->arHtcTarget, | ||
2298 | pConnect, | ||
2299 | &response); | ||
2300 | |||
2301 | if (status) { | ||
2302 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Failed to connect to %s service status:%d \n", | ||
2303 | pDesc, status)); | ||
2304 | break; | ||
2305 | } | ||
2306 | switch (pConnect->ServiceID) { | ||
2307 | case WMI_CONTROL_SVC : | ||
2308 | if (ar->arWmiEnabled) { | ||
2309 | /* set control endpoint for WMI use */ | ||
2310 | wmi_set_control_ep(ar->arWmi, response.Endpoint); | ||
2311 | } | ||
2312 | /* save EP for fast lookup */ | ||
2313 | ar->arControlEp = response.Endpoint; | ||
2314 | break; | ||
2315 | case WMI_DATA_BE_SVC : | ||
2316 | arSetAc2EndpointIDMap(ar, WMM_AC_BE, response.Endpoint); | ||
2317 | break; | ||
2318 | case WMI_DATA_BK_SVC : | ||
2319 | arSetAc2EndpointIDMap(ar, WMM_AC_BK, response.Endpoint); | ||
2320 | break; | ||
2321 | case WMI_DATA_VI_SVC : | ||
2322 | arSetAc2EndpointIDMap(ar, WMM_AC_VI, response.Endpoint); | ||
2323 | break; | ||
2324 | case WMI_DATA_VO_SVC : | ||
2325 | arSetAc2EndpointIDMap(ar, WMM_AC_VO, response.Endpoint); | ||
2326 | break; | ||
2327 | default: | ||
2328 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ServiceID not mapped %d\n", pConnect->ServiceID)); | ||
2329 | status = A_EINVAL; | ||
2330 | break; | ||
2331 | } | ||
2332 | |||
2333 | } while (false); | ||
2334 | |||
2335 | return status; | ||
2336 | } | ||
2337 | |||
2338 | void ar6000_TxDataCleanup(struct ar6_softc *ar) | ||
2339 | { | ||
2340 | /* flush all the data (non-control) streams | ||
2341 | * we only flush packets that are tagged as data, we leave any control packets that | ||
2342 | * were in the TX queues alone */ | ||
2343 | HTCFlushEndpoint(ar->arHtcTarget, | ||
2344 | arAc2EndpointID(ar, WMM_AC_BE), | ||
2345 | AR6K_DATA_PKT_TAG); | ||
2346 | HTCFlushEndpoint(ar->arHtcTarget, | ||
2347 | arAc2EndpointID(ar, WMM_AC_BK), | ||
2348 | AR6K_DATA_PKT_TAG); | ||
2349 | HTCFlushEndpoint(ar->arHtcTarget, | ||
2350 | arAc2EndpointID(ar, WMM_AC_VI), | ||
2351 | AR6K_DATA_PKT_TAG); | ||
2352 | HTCFlushEndpoint(ar->arHtcTarget, | ||
2353 | arAc2EndpointID(ar, WMM_AC_VO), | ||
2354 | AR6K_DATA_PKT_TAG); | ||
2355 | } | ||
2356 | |||
2357 | HTC_ENDPOINT_ID | ||
2358 | ar6000_ac2_endpoint_id ( void * devt, u8 ac) | ||
2359 | { | ||
2360 | struct ar6_softc *ar = (struct ar6_softc *) devt; | ||
2361 | return(arAc2EndpointID(ar, ac)); | ||
2362 | } | ||
2363 | |||
2364 | u8 ar6000_endpoint_id2_ac(void * devt, HTC_ENDPOINT_ID ep ) | ||
2365 | { | ||
2366 | struct ar6_softc *ar = (struct ar6_softc *) devt; | ||
2367 | return(arEndpoint2Ac(ar, ep )); | ||
2368 | } | ||
2369 | |||
2370 | #if defined(CONFIG_ATH6KL_ENABLE_COEXISTENCE) | ||
2371 | static int ath6kl_config_btcoex_params(struct ar6_softc *ar) | ||
2372 | { | ||
2373 | int r; | ||
2374 | WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD sbcb_cmd; | ||
2375 | WMI_SET_BTCOEX_FE_ANT_CMD sbfa_cmd; | ||
2376 | |||
2377 | /* Configure the type of BT collocated with WLAN */ | ||
2378 | memset(&sbcb_cmd, 0, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)); | ||
2379 | sbcb_cmd.btcoexCoLocatedBTdev = ATH6KL_BT_DEV; | ||
2380 | |||
2381 | r = wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &sbcb_cmd); | ||
2382 | |||
2383 | if (r) { | ||
2384 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
2385 | ("Unable to set collocated BT type\n")); | ||
2386 | return r; | ||
2387 | } | ||
2388 | |||
2389 | /* Configure the type of BT collocated with WLAN */ | ||
2390 | memset(&sbfa_cmd, 0, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)); | ||
2391 | |||
2392 | sbfa_cmd.btcoexFeAntType = ATH6KL_BT_ANTENNA; | ||
2393 | |||
2394 | r = wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &sbfa_cmd); | ||
2395 | if (r) { | ||
2396 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
2397 | ("Unable to set fornt end antenna configuration\n")); | ||
2398 | return r; | ||
2399 | } | ||
2400 | |||
2401 | return 0; | ||
2402 | } | ||
2403 | #else | ||
2404 | static int ath6kl_config_btcoex_params(struct ar6_softc *ar) | ||
2405 | { | ||
2406 | return 0; | ||
2407 | } | ||
2408 | #endif /* CONFIG_ATH6KL_ENABLE_COEXISTENCE */ | ||
2409 | |||
2410 | /* | ||
2411 | * This function applies WLAN specific configuration defined in wlan_config.h | ||
2412 | */ | ||
2413 | int ar6000_target_config_wlan_params(struct ar6_softc *ar) | ||
2414 | { | ||
2415 | int status = 0; | ||
2416 | |||
2417 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
2418 | if (ar->arTargetMode != AR6000_WLAN_MODE) { | ||
2419 | return 0; | ||
2420 | } | ||
2421 | #endif /* CONFIG_HOST_TCMD_SUPPORT */ | ||
2422 | |||
2423 | /* | ||
2424 | * configure the device for rx dot11 header rules 0,0 are the default values | ||
2425 | * therefore this command can be skipped if the inputs are 0,FALSE,FALSE.Required | ||
2426 | * if checksum offload is needed. Set RxMetaVersion to 2 | ||
2427 | */ | ||
2428 | if ((wmi_set_rx_frame_format_cmd(ar->arWmi,ar->rxMetaVersion, processDot11Hdr, processDot11Hdr)) != 0) { | ||
2429 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the rx frame format.\n")); | ||
2430 | status = A_ERROR; | ||
2431 | } | ||
2432 | |||
2433 | status = ath6kl_config_btcoex_params(ar); | ||
2434 | if (status) | ||
2435 | return status; | ||
2436 | |||
2437 | #if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN | ||
2438 | if ((wmi_pmparams_cmd(ar->arWmi, 0, 1, 0, 0, 1, IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) { | ||
2439 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power save fail event policy\n")); | ||
2440 | status = A_ERROR; | ||
2441 | } | ||
2442 | #endif | ||
2443 | |||
2444 | #if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP | ||
2445 | if ((wmi_set_lpreamble_cmd(ar->arWmi, 0, WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) { | ||
2446 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set barker preamble policy\n")); | ||
2447 | status = A_ERROR; | ||
2448 | } | ||
2449 | #endif | ||
2450 | |||
2451 | if ((wmi_set_keepalive_cmd(ar->arWmi, WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) != 0) { | ||
2452 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set keep alive interval\n")); | ||
2453 | status = A_ERROR; | ||
2454 | } | ||
2455 | |||
2456 | #if WLAN_CONFIG_DISABLE_11N | ||
2457 | { | ||
2458 | WMI_SET_HT_CAP_CMD htCap; | ||
2459 | |||
2460 | memset(&htCap, 0, sizeof(WMI_SET_HT_CAP_CMD)); | ||
2461 | htCap.band = 0; | ||
2462 | if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) { | ||
2463 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n")); | ||
2464 | status = A_ERROR; | ||
2465 | } | ||
2466 | |||
2467 | htCap.band = 1; | ||
2468 | if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) { | ||
2469 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n")); | ||
2470 | status = A_ERROR; | ||
2471 | } | ||
2472 | } | ||
2473 | #endif /* WLAN_CONFIG_DISABLE_11N */ | ||
2474 | |||
2475 | #ifdef ATH6K_CONFIG_OTA_MODE | ||
2476 | if ((wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER)) != 0) { | ||
2477 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power mode \n")); | ||
2478 | status = A_ERROR; | ||
2479 | } | ||
2480 | #endif | ||
2481 | |||
2482 | if ((wmi_disctimeout_cmd(ar->arWmi, WLAN_CONFIG_DISCONNECT_TIMEOUT)) != 0) { | ||
2483 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set disconnect timeout \n")); | ||
2484 | status = A_ERROR; | ||
2485 | } | ||
2486 | |||
2487 | #if WLAN_CONFIG_DISABLE_TX_BURSTING | ||
2488 | if ((wmi_set_wmm_txop(ar->arWmi, WMI_TXOP_DISABLED)) != 0) { | ||
2489 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set txop bursting \n")); | ||
2490 | status = A_ERROR; | ||
2491 | } | ||
2492 | #endif | ||
2493 | |||
2494 | return status; | ||
2495 | } | ||
2496 | |||
2497 | /* This function does one time initialization for the lifetime of the device */ | ||
2498 | int ar6000_init(struct net_device *dev) | ||
2499 | { | ||
2500 | struct ar6_softc *ar; | ||
2501 | int status; | ||
2502 | s32 timeleft; | ||
2503 | s16 i; | ||
2504 | int ret = 0; | ||
2505 | |||
2506 | if((ar = ar6k_priv(dev)) == NULL) | ||
2507 | { | ||
2508 | return -EIO; | ||
2509 | } | ||
2510 | |||
2511 | if (wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) { | ||
2512 | |||
2513 | ar6000_update_bdaddr(ar); | ||
2514 | |||
2515 | if (enablerssicompensation) { | ||
2516 | ar6000_copy_cust_data_from_target(ar->arHifDevice, ar->arTargetType); | ||
2517 | read_rssi_compensation_param(ar); | ||
2518 | for (i=-95; i<=0; i++) { | ||
2519 | rssi_compensation_table[0-i] = rssi_compensation_calc(ar,i); | ||
2520 | } | ||
2521 | } | ||
2522 | } | ||
2523 | |||
2524 | dev_hold(dev); | ||
2525 | rtnl_unlock(); | ||
2526 | |||
2527 | /* Do we need to finish the BMI phase */ | ||
2528 | if ((wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) && | ||
2529 | (BMIDone(ar->arHifDevice) != 0)) | ||
2530 | { | ||
2531 | ret = -EIO; | ||
2532 | goto ar6000_init_done; | ||
2533 | } | ||
2534 | |||
2535 | if (!bypasswmi) | ||
2536 | { | ||
2537 | #if 0 /* TBDXXX */ | ||
2538 | if (ar->arVersion.host_ver != ar->arVersion.target_ver) { | ||
2539 | A_PRINTF("WARNING: Host version 0x%x does not match Target " | ||
2540 | " version 0x%x!\n", | ||
2541 | ar->arVersion.host_ver, ar->arVersion.target_ver); | ||
2542 | } | ||
2543 | #endif | ||
2544 | |||
2545 | /* Indicate that WMI is enabled (although not ready yet) */ | ||
2546 | ar->arWmiEnabled = true; | ||
2547 | if ((ar->arWmi = wmi_init((void *) ar)) == NULL) | ||
2548 | { | ||
2549 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize WMI.\n", __func__)); | ||
2550 | ret = -EIO; | ||
2551 | goto ar6000_init_done; | ||
2552 | } | ||
2553 | |||
2554 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Got WMI @ 0x%lx.\n", __func__, | ||
2555 | (unsigned long) ar->arWmi)); | ||
2556 | } | ||
2557 | |||
2558 | do { | ||
2559 | struct htc_service_connect_req connect; | ||
2560 | |||
2561 | /* the reason we have to wait for the target here is that the driver layer | ||
2562 | * has to init BMI in order to set the host block size, | ||
2563 | */ | ||
2564 | status = HTCWaitTarget(ar->arHtcTarget); | ||
2565 | |||
2566 | if (status) { | ||
2567 | break; | ||
2568 | } | ||
2569 | |||
2570 | A_MEMZERO(&connect,sizeof(connect)); | ||
2571 | /* meta data is unused for now */ | ||
2572 | connect.pMetaData = NULL; | ||
2573 | connect.MetaDataLength = 0; | ||
2574 | /* these fields are the same for all service endpoints */ | ||
2575 | connect.EpCallbacks.pContext = ar; | ||
2576 | connect.EpCallbacks.EpTxCompleteMultiple = ar6000_tx_complete; | ||
2577 | connect.EpCallbacks.EpRecv = ar6000_rx; | ||
2578 | connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill; | ||
2579 | connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full; | ||
2580 | /* set the max queue depth so that our ar6000_tx_queue_full handler gets called. | ||
2581 | * Linux has the peculiarity of not providing flow control between the | ||
2582 | * NIC and the network stack. There is no API to indicate that a TX packet | ||
2583 | * was sent which could provide some back pressure to the network stack. | ||
2584 | * Under linux you would have to wait till the network stack consumed all sk_buffs | ||
2585 | * before any back-flow kicked in. Which isn't very friendly. | ||
2586 | * So we have to manage this ourselves */ | ||
2587 | connect.MaxSendQueueDepth = MAX_DEFAULT_SEND_QUEUE_DEPTH; | ||
2588 | connect.EpCallbacks.RecvRefillWaterMark = AR6000_MAX_RX_BUFFERS / 4; /* set to 25 % */ | ||
2589 | if (0 == connect.EpCallbacks.RecvRefillWaterMark) { | ||
2590 | connect.EpCallbacks.RecvRefillWaterMark++; | ||
2591 | } | ||
2592 | /* connect to control service */ | ||
2593 | connect.ServiceID = WMI_CONTROL_SVC; | ||
2594 | status = ar6000_connectservice(ar, | ||
2595 | &connect, | ||
2596 | "WMI CONTROL"); | ||
2597 | if (status) { | ||
2598 | break; | ||
2599 | } | ||
2600 | |||
2601 | connect.LocalConnectionFlags |= HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING; | ||
2602 | /* limit the HTC message size on the send path, although we can receive A-MSDU frames of | ||
2603 | * 4K, we will only send ethernet-sized (802.3) frames on the send path. */ | ||
2604 | connect.MaxSendMsgSize = WMI_MAX_TX_DATA_FRAME_LENGTH; | ||
2605 | |||
2606 | /* to reduce the amount of committed memory for larger A_MSDU frames, use the recv-alloc threshold | ||
2607 | * mechanism for larger packets */ | ||
2608 | connect.EpCallbacks.RecvAllocThreshold = AR6000_BUFFER_SIZE; | ||
2609 | connect.EpCallbacks.EpRecvAllocThresh = ar6000_alloc_amsdu_rxbuf; | ||
2610 | |||
2611 | /* for the remaining data services set the connection flag to reduce dribbling, | ||
2612 | * if configured to do so */ | ||
2613 | if (reduce_credit_dribble) { | ||
2614 | connect.ConnectionFlags |= HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE; | ||
2615 | /* the credit dribble trigger threshold is (reduce_credit_dribble - 1) for a value | ||
2616 | * of 0-3 */ | ||
2617 | connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK; | ||
2618 | connect.ConnectionFlags |= | ||
2619 | ((u16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK; | ||
2620 | } | ||
2621 | /* connect to best-effort service */ | ||
2622 | connect.ServiceID = WMI_DATA_BE_SVC; | ||
2623 | |||
2624 | status = ar6000_connectservice(ar, | ||
2625 | &connect, | ||
2626 | "WMI DATA BE"); | ||
2627 | if (status) { | ||
2628 | break; | ||
2629 | } | ||
2630 | |||
2631 | /* connect to back-ground | ||
2632 | * map this to WMI LOW_PRI */ | ||
2633 | connect.ServiceID = WMI_DATA_BK_SVC; | ||
2634 | status = ar6000_connectservice(ar, | ||
2635 | &connect, | ||
2636 | "WMI DATA BK"); | ||
2637 | if (status) { | ||
2638 | break; | ||
2639 | } | ||
2640 | |||
2641 | /* connect to Video service, map this to | ||
2642 | * to HI PRI */ | ||
2643 | connect.ServiceID = WMI_DATA_VI_SVC; | ||
2644 | status = ar6000_connectservice(ar, | ||
2645 | &connect, | ||
2646 | "WMI DATA VI"); | ||
2647 | if (status) { | ||
2648 | break; | ||
2649 | } | ||
2650 | |||
2651 | /* connect to VO service, this is currently not | ||
2652 | * mapped to a WMI priority stream due to historical reasons. | ||
2653 | * WMI originally defined 3 priorities over 3 mailboxes | ||
2654 | * We can change this when WMI is reworked so that priorities are not | ||
2655 | * dependent on mailboxes */ | ||
2656 | connect.ServiceID = WMI_DATA_VO_SVC; | ||
2657 | status = ar6000_connectservice(ar, | ||
2658 | &connect, | ||
2659 | "WMI DATA VO"); | ||
2660 | if (status) { | ||
2661 | break; | ||
2662 | } | ||
2663 | |||
2664 | A_ASSERT(arAc2EndpointID(ar,WMM_AC_BE) != 0); | ||
2665 | A_ASSERT(arAc2EndpointID(ar,WMM_AC_BK) != 0); | ||
2666 | A_ASSERT(arAc2EndpointID(ar,WMM_AC_VI) != 0); | ||
2667 | A_ASSERT(arAc2EndpointID(ar,WMM_AC_VO) != 0); | ||
2668 | |||
2669 | /* setup access class priority mappings */ | ||
2670 | ar->arAcStreamPriMap[WMM_AC_BK] = 0; /* lowest */ | ||
2671 | ar->arAcStreamPriMap[WMM_AC_BE] = 1; /* */ | ||
2672 | ar->arAcStreamPriMap[WMM_AC_VI] = 2; /* */ | ||
2673 | ar->arAcStreamPriMap[WMM_AC_VO] = 3; /* highest */ | ||
2674 | |||
2675 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
2676 | if (setuphci && (NULL != ar6kHciTransCallbacks.setupTransport)) { | ||
2677 | struct hci_transport_misc_handles hciHandles; | ||
2678 | |||
2679 | hciHandles.netDevice = ar->arNetDev; | ||
2680 | hciHandles.hifDevice = ar->arHifDevice; | ||
2681 | hciHandles.htcHandle = ar->arHtcTarget; | ||
2682 | status = (int)(ar6kHciTransCallbacks.setupTransport(&hciHandles)); | ||
2683 | } | ||
2684 | #else | ||
2685 | if (setuphci) { | ||
2686 | /* setup HCI */ | ||
2687 | status = ar6000_setup_hci(ar); | ||
2688 | } | ||
2689 | #endif | ||
2690 | |||
2691 | } while (false); | ||
2692 | |||
2693 | if (status) { | ||
2694 | ret = -EIO; | ||
2695 | goto ar6000_init_done; | ||
2696 | } | ||
2697 | |||
2698 | if (regscanmode) { | ||
2699 | u32 param; | ||
2700 | |||
2701 | if (BMIReadMemory(ar->arHifDevice, | ||
2702 | HOST_INTEREST_ITEM_ADDRESS(ar, | ||
2703 | hi_option_flag), | ||
2704 | (u8 *)¶m, | ||
2705 | 4) != 0) { | ||
2706 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
2707 | ("BMIReadMemory forsetting " | ||
2708 | "regscanmode failed\n")); | ||
2709 | return A_ERROR; | ||
2710 | } | ||
2711 | |||
2712 | if (regscanmode == 1) | ||
2713 | param |= HI_OPTION_SKIP_REG_SCAN; | ||
2714 | else if (regscanmode == 2) | ||
2715 | param |= HI_OPTION_INIT_REG_SCAN; | ||
2716 | |||
2717 | if (BMIWriteMemory(ar->arHifDevice, | ||
2718 | HOST_INTEREST_ITEM_ADDRESS(ar, | ||
2719 | hi_option_flag), | ||
2720 | (u8 *)¶m, | ||
2721 | 4) != 0) { | ||
2722 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
2723 | ("BMIWriteMemory forsetting " | ||
2724 | "regscanmode failed\n")); | ||
2725 | return A_ERROR; | ||
2726 | } | ||
2727 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Regulatory scan mode set\n")); | ||
2728 | } | ||
2729 | |||
2730 | /* | ||
2731 | * give our connected endpoints some buffers | ||
2732 | */ | ||
2733 | |||
2734 | ar6000_rx_refill(ar, ar->arControlEp); | ||
2735 | ar6000_rx_refill(ar, arAc2EndpointID(ar,WMM_AC_BE)); | ||
2736 | |||
2737 | /* | ||
2738 | * We will post the receive buffers only for SPE or endpoint ping testing so we are | ||
2739 | * making it conditional on the 'bypasswmi' flag. | ||
2740 | */ | ||
2741 | if (bypasswmi) { | ||
2742 | ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_BK)); | ||
2743 | ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VI)); | ||
2744 | ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VO)); | ||
2745 | } | ||
2746 | |||
2747 | /* allocate some buffers that handle larger AMSDU frames */ | ||
2748 | ar6000_refill_amsdu_rxbufs(ar,AR6000_MAX_AMSDU_RX_BUFFERS); | ||
2749 | |||
2750 | /* setup credit distribution */ | ||
2751 | ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo); | ||
2752 | |||
2753 | /* Since cookies are used for HTC transports, they should be */ | ||
2754 | /* initialized prior to enabling HTC. */ | ||
2755 | ar6000_cookie_init(ar); | ||
2756 | |||
2757 | /* start HTC */ | ||
2758 | status = HTCStart(ar->arHtcTarget); | ||
2759 | |||
2760 | if (status) { | ||
2761 | if (ar->arWmiEnabled == true) { | ||
2762 | wmi_shutdown(ar->arWmi); | ||
2763 | ar->arWmiEnabled = false; | ||
2764 | ar->arWmi = NULL; | ||
2765 | } | ||
2766 | ar6000_cookie_cleanup(ar); | ||
2767 | ret = -EIO; | ||
2768 | goto ar6000_init_done; | ||
2769 | } | ||
2770 | |||
2771 | if (!bypasswmi) { | ||
2772 | /* Wait for Wmi event to be ready */ | ||
2773 | timeleft = wait_event_interruptible_timeout(arEvent, | ||
2774 | (ar->arWmiReady == true), wmitimeout * HZ); | ||
2775 | |||
2776 | if (ar->arVersion.abi_ver != AR6K_ABI_VERSION) { | ||
2777 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ABI Version mismatch: Host(0x%x), Target(0x%x)\n", AR6K_ABI_VERSION, ar->arVersion.abi_ver)); | ||
2778 | #ifndef ATH6K_SKIP_ABI_VERSION_CHECK | ||
2779 | ret = -EIO; | ||
2780 | goto ar6000_init_done; | ||
2781 | #endif /* ATH6K_SKIP_ABI_VERSION_CHECK */ | ||
2782 | } | ||
2783 | |||
2784 | if(!timeleft || signal_pending(current)) | ||
2785 | { | ||
2786 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI is not ready or wait was interrupted\n")); | ||
2787 | ret = -EIO; | ||
2788 | goto ar6000_init_done; | ||
2789 | } | ||
2790 | |||
2791 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() WMI is ready\n", __func__)); | ||
2792 | |||
2793 | /* Communicate the wmi protocol verision to the target */ | ||
2794 | if ((ar6000_set_host_app_area(ar)) != 0) { | ||
2795 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the host app area\n")); | ||
2796 | } | ||
2797 | ar6000_target_config_wlan_params(ar); | ||
2798 | } | ||
2799 | |||
2800 | ar->arNumDataEndPts = 1; | ||
2801 | |||
2802 | if (bypasswmi) { | ||
2803 | /* for tests like endpoint ping, the MAC address needs to be non-zero otherwise | ||
2804 | * the data path through a raw socket is disabled */ | ||
2805 | dev->dev_addr[0] = 0x00; | ||
2806 | dev->dev_addr[1] = 0x01; | ||
2807 | dev->dev_addr[2] = 0x02; | ||
2808 | dev->dev_addr[3] = 0xAA; | ||
2809 | dev->dev_addr[4] = 0xBB; | ||
2810 | dev->dev_addr[5] = 0xCC; | ||
2811 | } | ||
2812 | |||
2813 | ar6000_init_done: | ||
2814 | rtnl_lock(); | ||
2815 | dev_put(dev); | ||
2816 | |||
2817 | return ret; | ||
2818 | } | ||
2819 | |||
2820 | |||
2821 | void | ||
2822 | ar6000_bitrate_rx(void *devt, s32 rateKbps) | ||
2823 | { | ||
2824 | struct ar6_softc *ar = (struct ar6_softc *)devt; | ||
2825 | |||
2826 | ar->arBitRate = rateKbps; | ||
2827 | wake_up(&arEvent); | ||
2828 | } | ||
2829 | |||
2830 | void | ||
2831 | ar6000_ratemask_rx(void *devt, u32 ratemask) | ||
2832 | { | ||
2833 | struct ar6_softc *ar = (struct ar6_softc *)devt; | ||
2834 | |||
2835 | ar->arRateMask = ratemask; | ||
2836 | wake_up(&arEvent); | ||
2837 | } | ||
2838 | |||
2839 | void | ||
2840 | ar6000_txPwr_rx(void *devt, u8 txPwr) | ||
2841 | { | ||
2842 | struct ar6_softc *ar = (struct ar6_softc *)devt; | ||
2843 | |||
2844 | ar->arTxPwr = txPwr; | ||
2845 | wake_up(&arEvent); | ||
2846 | } | ||
2847 | |||
2848 | |||
2849 | void | ||
2850 | ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList) | ||
2851 | { | ||
2852 | struct ar6_softc *ar = (struct ar6_softc *)devt; | ||
2853 | |||
2854 | memcpy(ar->arChannelList, chanList, numChan * sizeof (u16)); | ||
2855 | ar->arNumChannels = numChan; | ||
2856 | |||
2857 | wake_up(&arEvent); | ||
2858 | } | ||
2859 | |||
2860 | u8 ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, u32 *mapNo) | ||
2861 | { | ||
2862 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
2863 | u8 *datap; | ||
2864 | ATH_MAC_HDR *macHdr; | ||
2865 | u32 i, eptMap; | ||
2866 | |||
2867 | (*mapNo) = 0; | ||
2868 | datap = A_NETBUF_DATA(skb); | ||
2869 | macHdr = (ATH_MAC_HDR *)(datap + sizeof(WMI_DATA_HDR)); | ||
2870 | if (IEEE80211_IS_MULTICAST(macHdr->dstMac)) { | ||
2871 | return ENDPOINT_2; | ||
2872 | } | ||
2873 | |||
2874 | eptMap = -1; | ||
2875 | for (i = 0; i < ar->arNodeNum; i ++) { | ||
2876 | if (IEEE80211_ADDR_EQ(macHdr->dstMac, ar->arNodeMap[i].macAddress)) { | ||
2877 | (*mapNo) = i + 1; | ||
2878 | ar->arNodeMap[i].txPending ++; | ||
2879 | return ar->arNodeMap[i].epId; | ||
2880 | } | ||
2881 | |||
2882 | if ((eptMap == -1) && !ar->arNodeMap[i].txPending) { | ||
2883 | eptMap = i; | ||
2884 | } | ||
2885 | } | ||
2886 | |||
2887 | if (eptMap == -1) { | ||
2888 | eptMap = ar->arNodeNum; | ||
2889 | ar->arNodeNum ++; | ||
2890 | A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM); | ||
2891 | } | ||
2892 | |||
2893 | memcpy(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN); | ||
2894 | |||
2895 | for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) { | ||
2896 | if (!ar->arTxPending[i]) { | ||
2897 | ar->arNodeMap[eptMap].epId = i; | ||
2898 | break; | ||
2899 | } | ||
2900 | // No free endpoint is available, start redistribution on the inuse endpoints. | ||
2901 | if (i == ENDPOINT_5) { | ||
2902 | ar->arNodeMap[eptMap].epId = ar->arNexEpId; | ||
2903 | ar->arNexEpId ++; | ||
2904 | if (ar->arNexEpId > ENDPOINT_5) { | ||
2905 | ar->arNexEpId = ENDPOINT_2; | ||
2906 | } | ||
2907 | } | ||
2908 | } | ||
2909 | |||
2910 | (*mapNo) = eptMap + 1; | ||
2911 | ar->arNodeMap[eptMap].txPending ++; | ||
2912 | |||
2913 | return ar->arNodeMap[eptMap].epId; | ||
2914 | } | ||
2915 | |||
2916 | #ifdef DEBUG | ||
2917 | static void ar6000_dump_skb(struct sk_buff *skb) | ||
2918 | { | ||
2919 | u_char *ch; | ||
2920 | for (ch = A_NETBUF_DATA(skb); | ||
2921 | (unsigned long)ch < ((unsigned long)A_NETBUF_DATA(skb) + | ||
2922 | A_NETBUF_LEN(skb)); ch++) | ||
2923 | { | ||
2924 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("%2.2x ", *ch)); | ||
2925 | } | ||
2926 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("\n")); | ||
2927 | } | ||
2928 | #endif | ||
2929 | |||
2930 | #ifdef HTC_TEST_SEND_PKTS | ||
2931 | static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *skb); | ||
2932 | #endif | ||
2933 | |||
2934 | static int | ||
2935 | ar6000_data_tx(struct sk_buff *skb, struct net_device *dev) | ||
2936 | { | ||
2937 | #define AC_NOT_MAPPED 99 | ||
2938 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
2939 | u8 ac = AC_NOT_MAPPED; | ||
2940 | HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; | ||
2941 | u32 mapNo = 0; | ||
2942 | int len; | ||
2943 | struct ar_cookie *cookie; | ||
2944 | bool checkAdHocPsMapping = false,bMoreData = false; | ||
2945 | HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; | ||
2946 | u8 dot11Hdr = processDot11Hdr; | ||
2947 | #ifdef CONFIG_PM | ||
2948 | if (ar->arWowState != WLAN_WOW_STATE_NONE) { | ||
2949 | A_NETBUF_FREE(skb); | ||
2950 | return 0; | ||
2951 | } | ||
2952 | #endif /* CONFIG_PM */ | ||
2953 | |||
2954 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_data_tx start - skb=0x%lx, data=0x%lx, len=0x%x\n", | ||
2955 | (unsigned long)skb, (unsigned long)A_NETBUF_DATA(skb), | ||
2956 | A_NETBUF_LEN(skb))); | ||
2957 | |||
2958 | /* If target is not associated */ | ||
2959 | if( (!ar->arConnected && !bypasswmi) | ||
2960 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
2961 | /* TCMD doesn't support any data, free the buf and return */ | ||
2962 | || (ar->arTargetMode == AR6000_TCMD_MODE) | ||
2963 | #endif | ||
2964 | ) { | ||
2965 | A_NETBUF_FREE(skb); | ||
2966 | return 0; | ||
2967 | } | ||
2968 | |||
2969 | do { | ||
2970 | |||
2971 | if (ar->arWmiReady == false && bypasswmi == 0) { | ||
2972 | break; | ||
2973 | } | ||
2974 | |||
2975 | #ifdef BLOCK_TX_PATH_FLAG | ||
2976 | if (blocktx) { | ||
2977 | break; | ||
2978 | } | ||
2979 | #endif /* BLOCK_TX_PATH_FLAG */ | ||
2980 | |||
2981 | /* AP mode Power save processing */ | ||
2982 | /* If the dst STA is in sleep state, queue the pkt in its PS queue */ | ||
2983 | |||
2984 | if (ar->arNetworkType == AP_NETWORK) { | ||
2985 | ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); | ||
2986 | sta_t *conn = NULL; | ||
2987 | |||
2988 | /* If the dstMac is a Multicast address & atleast one of the | ||
2989 | * associated STA is in PS mode, then queue the pkt to the | ||
2990 | * mcastq | ||
2991 | */ | ||
2992 | if (IEEE80211_IS_MULTICAST(datap->dstMac)) { | ||
2993 | u8 ctr=0; | ||
2994 | bool qMcast=false; | ||
2995 | |||
2996 | |||
2997 | for (ctr=0; ctr<AP_MAX_NUM_STA; ctr++) { | ||
2998 | if (STA_IS_PWR_SLEEP((&ar->sta_list[ctr]))) { | ||
2999 | qMcast = true; | ||
3000 | } | ||
3001 | } | ||
3002 | if(qMcast) { | ||
3003 | |||
3004 | /* If this transmit is not because of a Dtim Expiry q it */ | ||
3005 | if (ar->DTIMExpired == false) { | ||
3006 | bool isMcastqEmpty = false; | ||
3007 | |||
3008 | A_MUTEX_LOCK(&ar->mcastpsqLock); | ||
3009 | isMcastqEmpty = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq); | ||
3010 | A_NETBUF_ENQUEUE(&ar->mcastpsq, skb); | ||
3011 | A_MUTEX_UNLOCK(&ar->mcastpsqLock); | ||
3012 | |||
3013 | /* If this is the first Mcast pkt getting queued | ||
3014 | * indicate to the target to set the BitmapControl LSB | ||
3015 | * of the TIM IE. | ||
3016 | */ | ||
3017 | if (isMcastqEmpty) { | ||
3018 | wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 1); | ||
3019 | } | ||
3020 | return 0; | ||
3021 | } else { | ||
3022 | /* This transmit is because of Dtim expiry. Determine if | ||
3023 | * MoreData bit has to be set. | ||
3024 | */ | ||
3025 | A_MUTEX_LOCK(&ar->mcastpsqLock); | ||
3026 | if(!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { | ||
3027 | bMoreData = true; | ||
3028 | } | ||
3029 | A_MUTEX_UNLOCK(&ar->mcastpsqLock); | ||
3030 | } | ||
3031 | } | ||
3032 | } else { | ||
3033 | conn = ieee80211_find_conn(ar, datap->dstMac); | ||
3034 | if (conn) { | ||
3035 | if (STA_IS_PWR_SLEEP(conn)) { | ||
3036 | /* If this transmit is not because of a PsPoll q it*/ | ||
3037 | if (!STA_IS_PS_POLLED(conn)) { | ||
3038 | bool isPsqEmpty = false; | ||
3039 | /* Queue the frames if the STA is sleeping */ | ||
3040 | A_MUTEX_LOCK(&conn->psqLock); | ||
3041 | isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); | ||
3042 | A_NETBUF_ENQUEUE(&conn->psq, skb); | ||
3043 | A_MUTEX_UNLOCK(&conn->psqLock); | ||
3044 | |||
3045 | /* If this is the first pkt getting queued | ||
3046 | * for this STA, update the PVB for this STA | ||
3047 | */ | ||
3048 | if (isPsqEmpty) { | ||
3049 | wmi_set_pvb_cmd(ar->arWmi, conn->aid, 1); | ||
3050 | } | ||
3051 | |||
3052 | return 0; | ||
3053 | } else { | ||
3054 | /* This tx is because of a PsPoll. Determine if | ||
3055 | * MoreData bit has to be set | ||
3056 | */ | ||
3057 | A_MUTEX_LOCK(&conn->psqLock); | ||
3058 | if (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) { | ||
3059 | bMoreData = true; | ||
3060 | } | ||
3061 | A_MUTEX_UNLOCK(&conn->psqLock); | ||
3062 | } | ||
3063 | } | ||
3064 | } else { | ||
3065 | |||
3066 | /* non existent STA. drop the frame */ | ||
3067 | A_NETBUF_FREE(skb); | ||
3068 | return 0; | ||
3069 | } | ||
3070 | } | ||
3071 | } | ||
3072 | |||
3073 | if (ar->arWmiEnabled) { | ||
3074 | u8 csumStart=0; | ||
3075 | u8 csumDest=0; | ||
3076 | u8 csum=skb->ip_summed; | ||
3077 | if(csumOffload && (csum==CHECKSUM_PARTIAL)){ | ||
3078 | csumStart = (skb->head + skb->csum_start - skb_network_header(skb) + | ||
3079 | sizeof(ATH_LLC_SNAP_HDR)); | ||
3080 | csumDest=skb->csum_offset+csumStart; | ||
3081 | } | ||
3082 | if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len - LINUX_HACK_FUDGE_FACTOR) { | ||
3083 | struct sk_buff *newbuf; | ||
3084 | |||
3085 | /* | ||
3086 | * We really should have gotten enough headroom but sometimes | ||
3087 | * we still get packets with not enough headroom. Copy the packet. | ||
3088 | */ | ||
3089 | len = A_NETBUF_LEN(skb); | ||
3090 | newbuf = A_NETBUF_ALLOC(len); | ||
3091 | if (newbuf == NULL) { | ||
3092 | break; | ||
3093 | } | ||
3094 | A_NETBUF_PUT(newbuf, len); | ||
3095 | memcpy(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len); | ||
3096 | A_NETBUF_FREE(skb); | ||
3097 | skb = newbuf; | ||
3098 | /* fall through and assemble header */ | ||
3099 | } | ||
3100 | |||
3101 | if (dot11Hdr) { | ||
3102 | if (wmi_dot11_hdr_add(ar->arWmi,skb,ar->arNetworkType) != 0) { | ||
3103 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx-wmi_dot11_hdr_add failed\n")); | ||
3104 | break; | ||
3105 | } | ||
3106 | } else { | ||
3107 | if (wmi_dix_2_dot3(ar->arWmi, skb) != 0) { | ||
3108 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_dix_2_dot3 failed\n")); | ||
3109 | break; | ||
3110 | } | ||
3111 | } | ||
3112 | if(csumOffload && (csum ==CHECKSUM_PARTIAL)){ | ||
3113 | WMI_TX_META_V2 metaV2; | ||
3114 | metaV2.csumStart =csumStart; | ||
3115 | metaV2.csumDest = csumDest; | ||
3116 | metaV2.csumFlags = 0x1;/*instruct target to calculate checksum*/ | ||
3117 | if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr, | ||
3118 | WMI_META_VERSION_2,&metaV2) != 0) { | ||
3119 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n")); | ||
3120 | break; | ||
3121 | } | ||
3122 | |||
3123 | } | ||
3124 | else | ||
3125 | { | ||
3126 | if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,0,NULL) != 0) { | ||
3127 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n")); | ||
3128 | break; | ||
3129 | } | ||
3130 | } | ||
3131 | |||
3132 | |||
3133 | if ((ar->arNetworkType == ADHOC_NETWORK) && | ||
3134 | ar->arIbssPsEnable && ar->arConnected) { | ||
3135 | /* flag to check adhoc mapping once we take the lock below: */ | ||
3136 | checkAdHocPsMapping = true; | ||
3137 | |||
3138 | } else { | ||
3139 | /* get the stream mapping */ | ||
3140 | ac = wmi_implicit_create_pstream(ar->arWmi, skb, 0, ar->arWmmEnabled); | ||
3141 | } | ||
3142 | |||
3143 | } else { | ||
3144 | EPPING_HEADER *eppingHdr; | ||
3145 | |||
3146 | eppingHdr = A_NETBUF_DATA(skb); | ||
3147 | |||
3148 | if (IS_EPPING_PACKET(eppingHdr)) { | ||
3149 | /* the stream ID is mapped to an access class */ | ||
3150 | ac = eppingHdr->StreamNo_h; | ||
3151 | /* some EPPING packets cannot be dropped no matter what access class it was | ||
3152 | * sent on. We can change the packet tag to guarantee it will not get dropped */ | ||
3153 | if (IS_EPING_PACKET_NO_DROP(eppingHdr)) { | ||
3154 | htc_tag = AR6K_CONTROL_PKT_TAG; | ||
3155 | } | ||
3156 | |||
3157 | if (ac == HCI_TRANSPORT_STREAM_NUM) { | ||
3158 | /* pass this to HCI */ | ||
3159 | #ifndef EXPORT_HCI_BRIDGE_INTERFACE | ||
3160 | if (!hci_test_send(ar,skb)) { | ||
3161 | return 0; | ||
3162 | } | ||
3163 | #endif | ||
3164 | /* set AC to discard this skb */ | ||
3165 | ac = AC_NOT_MAPPED; | ||
3166 | } else { | ||
3167 | /* a quirk of linux, the payload of the frame is 32-bit aligned and thus the addition | ||
3168 | * of the HTC header will mis-align the start of the HTC frame, so we add some | ||
3169 | * padding which will be stripped off in the target */ | ||
3170 | if (EPPING_ALIGNMENT_PAD > 0) { | ||
3171 | A_NETBUF_PUSH(skb, EPPING_ALIGNMENT_PAD); | ||
3172 | } | ||
3173 | } | ||
3174 | |||
3175 | } else { | ||
3176 | /* not a ping packet, drop it */ | ||
3177 | ac = AC_NOT_MAPPED; | ||
3178 | } | ||
3179 | } | ||
3180 | |||
3181 | } while (false); | ||
3182 | |||
3183 | /* did we succeed ? */ | ||
3184 | if ((ac == AC_NOT_MAPPED) && !checkAdHocPsMapping) { | ||
3185 | /* cleanup and exit */ | ||
3186 | A_NETBUF_FREE(skb); | ||
3187 | AR6000_STAT_INC(ar, tx_dropped); | ||
3188 | AR6000_STAT_INC(ar, tx_aborted_errors); | ||
3189 | return 0; | ||
3190 | } | ||
3191 | |||
3192 | cookie = NULL; | ||
3193 | |||
3194 | /* take the lock to protect driver data */ | ||
3195 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
3196 | |||
3197 | do { | ||
3198 | |||
3199 | if (checkAdHocPsMapping) { | ||
3200 | eid = ar6000_ibss_map_epid(skb, dev, &mapNo); | ||
3201 | }else { | ||
3202 | eid = arAc2EndpointID (ar, ac); | ||
3203 | } | ||
3204 | /* validate that the endpoint is connected */ | ||
3205 | if (eid == 0 || eid == ENDPOINT_UNUSED ) { | ||
3206 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" eid %d is NOT mapped!\n", eid)); | ||
3207 | break; | ||
3208 | } | ||
3209 | /* allocate resource for this packet */ | ||
3210 | cookie = ar6000_alloc_cookie(ar); | ||
3211 | |||
3212 | if (cookie != NULL) { | ||
3213 | /* update counts while the lock is held */ | ||
3214 | ar->arTxPending[eid]++; | ||
3215 | ar->arTotalTxDataPending++; | ||
3216 | } | ||
3217 | |||
3218 | } while (false); | ||
3219 | |||
3220 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
3221 | |||
3222 | if (cookie != NULL) { | ||
3223 | cookie->arc_bp[0] = (unsigned long)skb; | ||
3224 | cookie->arc_bp[1] = mapNo; | ||
3225 | SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, | ||
3226 | cookie, | ||
3227 | A_NETBUF_DATA(skb), | ||
3228 | A_NETBUF_LEN(skb), | ||
3229 | eid, | ||
3230 | htc_tag); | ||
3231 | |||
3232 | #ifdef DEBUG | ||
3233 | if (debugdriver >= 3) { | ||
3234 | ar6000_dump_skb(skb); | ||
3235 | } | ||
3236 | #endif | ||
3237 | #ifdef HTC_TEST_SEND_PKTS | ||
3238 | DoHTCSendPktsTest(ar,mapNo,eid,skb); | ||
3239 | #endif | ||
3240 | /* HTC interface is asynchronous, if this fails, cleanup will happen in | ||
3241 | * the ar6000_tx_complete callback */ | ||
3242 | HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); | ||
3243 | } else { | ||
3244 | /* no packet to send, cleanup */ | ||
3245 | A_NETBUF_FREE(skb); | ||
3246 | AR6000_STAT_INC(ar, tx_dropped); | ||
3247 | AR6000_STAT_INC(ar, tx_aborted_errors); | ||
3248 | } | ||
3249 | |||
3250 | return 0; | ||
3251 | } | ||
3252 | |||
3253 | int | ||
3254 | ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev) | ||
3255 | { | ||
3256 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
3257 | struct ar_cookie *cookie; | ||
3258 | HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; | ||
3259 | |||
3260 | cookie = NULL; | ||
3261 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
3262 | |||
3263 | /* For now we send ACL on BE endpoint: We can also have a dedicated EP */ | ||
3264 | eid = arAc2EndpointID (ar, 0); | ||
3265 | /* allocate resource for this packet */ | ||
3266 | cookie = ar6000_alloc_cookie(ar); | ||
3267 | |||
3268 | if (cookie != NULL) { | ||
3269 | /* update counts while the lock is held */ | ||
3270 | ar->arTxPending[eid]++; | ||
3271 | ar->arTotalTxDataPending++; | ||
3272 | } | ||
3273 | |||
3274 | |||
3275 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
3276 | |||
3277 | if (cookie != NULL) { | ||
3278 | cookie->arc_bp[0] = (unsigned long)skb; | ||
3279 | cookie->arc_bp[1] = 0; | ||
3280 | SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, | ||
3281 | cookie, | ||
3282 | A_NETBUF_DATA(skb), | ||
3283 | A_NETBUF_LEN(skb), | ||
3284 | eid, | ||
3285 | AR6K_DATA_PKT_TAG); | ||
3286 | |||
3287 | /* HTC interface is asynchronous, if this fails, cleanup will happen in | ||
3288 | * the ar6000_tx_complete callback */ | ||
3289 | HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); | ||
3290 | } else { | ||
3291 | /* no packet to send, cleanup */ | ||
3292 | A_NETBUF_FREE(skb); | ||
3293 | AR6000_STAT_INC(ar, tx_dropped); | ||
3294 | AR6000_STAT_INC(ar, tx_aborted_errors); | ||
3295 | } | ||
3296 | return 0; | ||
3297 | } | ||
3298 | |||
3299 | |||
3300 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
3301 | static void | ||
3302 | tvsub(register struct timeval *out, register struct timeval *in) | ||
3303 | { | ||
3304 | if((out->tv_usec -= in->tv_usec) < 0) { | ||
3305 | out->tv_sec--; | ||
3306 | out->tv_usec += 1000000; | ||
3307 | } | ||
3308 | out->tv_sec -= in->tv_sec; | ||
3309 | } | ||
3310 | |||
3311 | void | ||
3312 | applyAPTCHeuristics(struct ar6_softc *ar) | ||
3313 | { | ||
3314 | u32 duration; | ||
3315 | u32 numbytes; | ||
3316 | u32 throughput; | ||
3317 | struct timeval ts; | ||
3318 | int status; | ||
3319 | |||
3320 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
3321 | |||
3322 | if ((enableAPTCHeuristics) && (!aptcTR.timerScheduled)) { | ||
3323 | do_gettimeofday(&ts); | ||
3324 | tvsub(&ts, &aptcTR.samplingTS); | ||
3325 | duration = ts.tv_sec * 1000 + ts.tv_usec / 1000; /* ms */ | ||
3326 | numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; | ||
3327 | |||
3328 | if (duration > APTC_TRAFFIC_SAMPLING_INTERVAL) { | ||
3329 | /* Initialize the time stamp and byte count */ | ||
3330 | aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; | ||
3331 | do_gettimeofday(&aptcTR.samplingTS); | ||
3332 | |||
3333 | /* Calculate and decide based on throughput thresholds */ | ||
3334 | throughput = ((numbytes * 8) / duration); | ||
3335 | if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) { | ||
3336 | /* Disable Sleep and schedule a timer */ | ||
3337 | A_ASSERT(ar->arWmiReady == true); | ||
3338 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
3339 | status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER); | ||
3340 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
3341 | A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); | ||
3342 | aptcTR.timerScheduled = true; | ||
3343 | } | ||
3344 | } | ||
3345 | } | ||
3346 | |||
3347 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
3348 | } | ||
3349 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
3350 | |||
3351 | static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket) | ||
3352 | { | ||
3353 | struct ar6_softc *ar = (struct ar6_softc *)Context; | ||
3354 | HTC_SEND_FULL_ACTION action = HTC_SEND_FULL_KEEP; | ||
3355 | bool stopNet = false; | ||
3356 | HTC_ENDPOINT_ID Endpoint = HTC_GET_ENDPOINT_FROM_PKT(pPacket); | ||
3357 | |||
3358 | do { | ||
3359 | |||
3360 | if (bypasswmi) { | ||
3361 | int accessClass; | ||
3362 | |||
3363 | if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) { | ||
3364 | /* don't drop special control packets */ | ||
3365 | break; | ||
3366 | } | ||
3367 | |||
3368 | accessClass = arEndpoint2Ac(ar,Endpoint); | ||
3369 | /* for endpoint ping testing drop Best Effort and Background */ | ||
3370 | if ((accessClass == WMM_AC_BE) || (accessClass == WMM_AC_BK)) { | ||
3371 | action = HTC_SEND_FULL_DROP; | ||
3372 | stopNet = false; | ||
3373 | } else { | ||
3374 | /* keep but stop the netqueues */ | ||
3375 | stopNet = true; | ||
3376 | } | ||
3377 | break; | ||
3378 | } | ||
3379 | |||
3380 | if (Endpoint == ar->arControlEp) { | ||
3381 | /* under normal WMI if this is getting full, then something is running rampant | ||
3382 | * the host should not be exhausting the WMI queue with too many commands | ||
3383 | * the only exception to this is during testing using endpointping */ | ||
3384 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
3385 | /* set flag to handle subsequent messages */ | ||
3386 | ar->arWMIControlEpFull = true; | ||
3387 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
3388 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI Control Endpoint is FULL!!! \n")); | ||
3389 | /* no need to stop the network */ | ||
3390 | stopNet = false; | ||
3391 | break; | ||
3392 | } | ||
3393 | |||
3394 | /* if we get here, we are dealing with data endpoints getting full */ | ||
3395 | |||
3396 | if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) { | ||
3397 | /* don't drop control packets issued on ANY data endpoint */ | ||
3398 | break; | ||
3399 | } | ||
3400 | |||
3401 | if (ar->arNetworkType == ADHOC_NETWORK) { | ||
3402 | /* in adhoc mode, we cannot differentiate traffic priorities so there is no need to | ||
3403 | * continue, however we should stop the network */ | ||
3404 | stopNet = true; | ||
3405 | break; | ||
3406 | } | ||
3407 | /* the last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for the highest | ||
3408 | * active stream */ | ||
3409 | if (ar->arAcStreamPriMap[arEndpoint2Ac(ar,Endpoint)] < ar->arHiAcStreamActivePri && | ||
3410 | ar->arCookieCount <= MAX_HI_COOKIE_NUM) { | ||
3411 | /* this stream's priority is less than the highest active priority, we | ||
3412 | * give preference to the highest priority stream by directing | ||
3413 | * HTC to drop the packet that overflowed */ | ||
3414 | action = HTC_SEND_FULL_DROP; | ||
3415 | /* since we are dropping packets, no need to stop the network */ | ||
3416 | stopNet = false; | ||
3417 | break; | ||
3418 | } | ||
3419 | |||
3420 | } while (false); | ||
3421 | |||
3422 | if (stopNet) { | ||
3423 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
3424 | ar->arNetQueueStopped = true; | ||
3425 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
3426 | /* one of the data endpoints queues is getting full..need to stop network stack | ||
3427 | * the queue will resume in ar6000_tx_complete() */ | ||
3428 | netif_stop_queue(ar->arNetDev); | ||
3429 | } | ||
3430 | |||
3431 | return action; | ||
3432 | } | ||
3433 | |||
3434 | |||
3435 | static void | ||
3436 | ar6000_tx_complete(void *Context, struct htc_packet_queue *pPacketQueue) | ||
3437 | { | ||
3438 | struct ar6_softc *ar = (struct ar6_softc *)Context; | ||
3439 | u32 mapNo = 0; | ||
3440 | int status; | ||
3441 | struct ar_cookie * ar_cookie; | ||
3442 | HTC_ENDPOINT_ID eid; | ||
3443 | bool wakeEvent = false; | ||
3444 | struct sk_buff_head skb_queue; | ||
3445 | struct htc_packet *pPacket; | ||
3446 | struct sk_buff *pktSkb; | ||
3447 | bool flushing = false; | ||
3448 | |||
3449 | skb_queue_head_init(&skb_queue); | ||
3450 | |||
3451 | /* lock the driver as we update internal state */ | ||
3452 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
3453 | |||
3454 | /* reap completed packets */ | ||
3455 | while (!HTC_QUEUE_EMPTY(pPacketQueue)) { | ||
3456 | |||
3457 | pPacket = HTC_PACKET_DEQUEUE(pPacketQueue); | ||
3458 | |||
3459 | ar_cookie = (struct ar_cookie *)pPacket->pPktContext; | ||
3460 | A_ASSERT(ar_cookie); | ||
3461 | |||
3462 | status = pPacket->Status; | ||
3463 | pktSkb = (struct sk_buff *)ar_cookie->arc_bp[0]; | ||
3464 | eid = pPacket->Endpoint; | ||
3465 | mapNo = ar_cookie->arc_bp[1]; | ||
3466 | |||
3467 | A_ASSERT(pktSkb); | ||
3468 | A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(pktSkb)); | ||
3469 | |||
3470 | /* add this to the list, use faster non-lock API */ | ||
3471 | __skb_queue_tail(&skb_queue,pktSkb); | ||
3472 | |||
3473 | if (!status) { | ||
3474 | A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(pktSkb)); | ||
3475 | } | ||
3476 | |||
3477 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_tx_complete skb=0x%lx data=0x%lx len=0x%x eid=%d ", | ||
3478 | (unsigned long)pktSkb, (unsigned long)pPacket->pBuffer, | ||
3479 | pPacket->ActualLength, | ||
3480 | eid)); | ||
3481 | |||
3482 | ar->arTxPending[eid]--; | ||
3483 | |||
3484 | if ((eid != ar->arControlEp) || bypasswmi) { | ||
3485 | ar->arTotalTxDataPending--; | ||
3486 | } | ||
3487 | |||
3488 | if (eid == ar->arControlEp) | ||
3489 | { | ||
3490 | if (ar->arWMIControlEpFull) { | ||
3491 | /* since this packet completed, the WMI EP is no longer full */ | ||
3492 | ar->arWMIControlEpFull = false; | ||
3493 | } | ||
3494 | |||
3495 | if (ar->arTxPending[eid] == 0) { | ||
3496 | wakeEvent = true; | ||
3497 | } | ||
3498 | } | ||
3499 | |||
3500 | if (status) { | ||
3501 | if (status == A_ECANCELED) { | ||
3502 | /* a packet was flushed */ | ||
3503 | flushing = true; | ||
3504 | } | ||
3505 | AR6000_STAT_INC(ar, tx_errors); | ||
3506 | if (status != A_NO_RESOURCE) { | ||
3507 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() -TX ERROR, status: 0x%x\n", __func__, | ||
3508 | status)); | ||
3509 | } | ||
3510 | } else { | ||
3511 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("OK\n")); | ||
3512 | flushing = false; | ||
3513 | AR6000_STAT_INC(ar, tx_packets); | ||
3514 | ar->arNetStats.tx_bytes += A_NETBUF_LEN(pktSkb); | ||
3515 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
3516 | aptcTR.bytesTransmitted += a_netbuf_to_len(pktSkb); | ||
3517 | applyAPTCHeuristics(ar); | ||
3518 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
3519 | } | ||
3520 | |||
3521 | // TODO this needs to be looked at | ||
3522 | if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable | ||
3523 | && (eid != ar->arControlEp) && mapNo) | ||
3524 | { | ||
3525 | mapNo --; | ||
3526 | ar->arNodeMap[mapNo].txPending --; | ||
3527 | |||
3528 | if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) { | ||
3529 | u32 i; | ||
3530 | for (i = ar->arNodeNum; i > 0; i --) { | ||
3531 | if (!ar->arNodeMap[i - 1].txPending) { | ||
3532 | A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping)); | ||
3533 | ar->arNodeNum --; | ||
3534 | } else { | ||
3535 | break; | ||
3536 | } | ||
3537 | } | ||
3538 | } | ||
3539 | } | ||
3540 | |||
3541 | ar6000_free_cookie(ar, ar_cookie); | ||
3542 | |||
3543 | if (ar->arNetQueueStopped) { | ||
3544 | ar->arNetQueueStopped = false; | ||
3545 | } | ||
3546 | } | ||
3547 | |||
3548 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
3549 | |||
3550 | /* lock is released, we can freely call other kernel APIs */ | ||
3551 | |||
3552 | /* free all skbs in our local list */ | ||
3553 | while (!skb_queue_empty(&skb_queue)) { | ||
3554 | /* use non-lock version */ | ||
3555 | pktSkb = __skb_dequeue(&skb_queue); | ||
3556 | A_NETBUF_FREE(pktSkb); | ||
3557 | } | ||
3558 | |||
3559 | if ((ar->arConnected == true) || bypasswmi) { | ||
3560 | if (!flushing) { | ||
3561 | /* don't wake the queue if we are flushing, other wise it will just | ||
3562 | * keep queueing packets, which will keep failing */ | ||
3563 | netif_wake_queue(ar->arNetDev); | ||
3564 | } | ||
3565 | } | ||
3566 | |||
3567 | if (wakeEvent) { | ||
3568 | wake_up(&arEvent); | ||
3569 | } | ||
3570 | |||
3571 | } | ||
3572 | |||
3573 | sta_t * | ||
3574 | ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr) | ||
3575 | { | ||
3576 | sta_t *conn = NULL; | ||
3577 | u8 i, max_conn; | ||
3578 | |||
3579 | switch(ar->arNetworkType) { | ||
3580 | case AP_NETWORK: | ||
3581 | max_conn = AP_MAX_NUM_STA; | ||
3582 | break; | ||
3583 | default: | ||
3584 | max_conn=0; | ||
3585 | break; | ||
3586 | } | ||
3587 | |||
3588 | for (i = 0; i < max_conn; i++) { | ||
3589 | if (IEEE80211_ADDR_EQ(node_addr, ar->sta_list[i].mac)) { | ||
3590 | conn = &ar->sta_list[i]; | ||
3591 | break; | ||
3592 | } | ||
3593 | } | ||
3594 | |||
3595 | return conn; | ||
3596 | } | ||
3597 | |||
3598 | sta_t *ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid) | ||
3599 | { | ||
3600 | sta_t *conn = NULL; | ||
3601 | u8 ctr; | ||
3602 | |||
3603 | for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { | ||
3604 | if (ar->sta_list[ctr].aid == aid) { | ||
3605 | conn = &ar->sta_list[ctr]; | ||
3606 | break; | ||
3607 | } | ||
3608 | } | ||
3609 | return conn; | ||
3610 | } | ||
3611 | |||
3612 | /* | ||
3613 | * Receive event handler. This is called by HTC when a packet is received | ||
3614 | */ | ||
3615 | int pktcount; | ||
3616 | static void | ||
3617 | ar6000_rx(void *Context, struct htc_packet *pPacket) | ||
3618 | { | ||
3619 | struct ar6_softc *ar = (struct ar6_softc *)Context; | ||
3620 | struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext; | ||
3621 | int minHdrLen; | ||
3622 | u8 containsDot11Hdr = 0; | ||
3623 | int status = pPacket->Status; | ||
3624 | HTC_ENDPOINT_ID ept = pPacket->Endpoint; | ||
3625 | |||
3626 | A_ASSERT((status) || | ||
3627 | (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN))); | ||
3628 | |||
3629 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx ar=0x%lx eid=%d, skb=0x%lx, data=0x%lx, len=0x%x status:%d", | ||
3630 | (unsigned long)ar, ept, (unsigned long)skb, (unsigned long)pPacket->pBuffer, | ||
3631 | pPacket->ActualLength, status)); | ||
3632 | if (status) { | ||
3633 | if (status != A_ECANCELED) { | ||
3634 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("RX ERR (%d) \n",status)); | ||
3635 | } | ||
3636 | } | ||
3637 | |||
3638 | /* take lock to protect buffer counts | ||
3639 | * and adaptive power throughput state */ | ||
3640 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
3641 | |||
3642 | if (!status) { | ||
3643 | AR6000_STAT_INC(ar, rx_packets); | ||
3644 | ar->arNetStats.rx_bytes += pPacket->ActualLength; | ||
3645 | #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL | ||
3646 | aptcTR.bytesReceived += a_netbuf_to_len(skb); | ||
3647 | applyAPTCHeuristics(ar); | ||
3648 | #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ | ||
3649 | |||
3650 | A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN); | ||
3651 | A_NETBUF_PULL(skb, HTC_HEADER_LEN); | ||
3652 | |||
3653 | #ifdef DEBUG | ||
3654 | if (debugdriver >= 2) { | ||
3655 | ar6000_dump_skb(skb); | ||
3656 | } | ||
3657 | #endif /* DEBUG */ | ||
3658 | } | ||
3659 | |||
3660 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
3661 | |||
3662 | skb->dev = ar->arNetDev; | ||
3663 | if (status) { | ||
3664 | AR6000_STAT_INC(ar, rx_errors); | ||
3665 | A_NETBUF_FREE(skb); | ||
3666 | } else if (ar->arWmiEnabled == true) { | ||
3667 | if (ept == ar->arControlEp) { | ||
3668 | /* | ||
3669 | * this is a wmi control msg | ||
3670 | */ | ||
3671 | #ifdef CONFIG_PM | ||
3672 | ar6000_check_wow_status(ar, skb, true); | ||
3673 | #endif /* CONFIG_PM */ | ||
3674 | wmi_control_rx(ar->arWmi, skb); | ||
3675 | } else { | ||
3676 | WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb); | ||
3677 | bool is_amsdu; | ||
3678 | u8 tid; | ||
3679 | |||
3680 | /* | ||
3681 | * This check can be removed if after a while we do not | ||
3682 | * see the warning. For now we leave it to ensure | ||
3683 | * we drop these frames accordingly in case the | ||
3684 | * target generates them for some reason. These | ||
3685 | * were used for an internal PAL but that's not | ||
3686 | * used or supported anymore. These frames should | ||
3687 | * not come up from the target. | ||
3688 | */ | ||
3689 | if (WARN_ON(WMI_DATA_HDR_GET_DATA_TYPE(dhdr) == | ||
3690 | WMI_DATA_HDR_DATA_TYPE_ACL)) { | ||
3691 | AR6000_STAT_INC(ar, rx_errors); | ||
3692 | A_NETBUF_FREE(skb); | ||
3693 | return; | ||
3694 | } | ||
3695 | |||
3696 | #ifdef CONFIG_PM | ||
3697 | ar6000_check_wow_status(ar, NULL, false); | ||
3698 | #endif /* CONFIG_PM */ | ||
3699 | /* | ||
3700 | * this is a wmi data packet | ||
3701 | */ | ||
3702 | // NWF | ||
3703 | |||
3704 | if (processDot11Hdr) { | ||
3705 | minHdrLen = sizeof(WMI_DATA_HDR) + sizeof(struct ieee80211_frame) + sizeof(ATH_LLC_SNAP_HDR); | ||
3706 | } else { | ||
3707 | minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + | ||
3708 | sizeof(ATH_LLC_SNAP_HDR); | ||
3709 | } | ||
3710 | |||
3711 | /* In the case of AP mode we may receive NULL data frames | ||
3712 | * that do not have LLC hdr. They are 16 bytes in size. | ||
3713 | * Allow these frames in the AP mode. | ||
3714 | * ACL data frames don't follow ethernet frame bounds for | ||
3715 | * min length | ||
3716 | */ | ||
3717 | if (ar->arNetworkType != AP_NETWORK && | ||
3718 | ((pPacket->ActualLength < minHdrLen) || | ||
3719 | (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_SIZE))) | ||
3720 | { | ||
3721 | /* | ||
3722 | * packet is too short or too long | ||
3723 | */ | ||
3724 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("TOO SHORT or TOO LONG\n")); | ||
3725 | AR6000_STAT_INC(ar, rx_errors); | ||
3726 | AR6000_STAT_INC(ar, rx_length_errors); | ||
3727 | A_NETBUF_FREE(skb); | ||
3728 | } else { | ||
3729 | u16 seq_no; | ||
3730 | u8 meta_type; | ||
3731 | |||
3732 | #if 0 | ||
3733 | /* Access RSSI values here */ | ||
3734 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("RSSI %d\n", | ||
3735 | ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi)); | ||
3736 | #endif | ||
3737 | /* Get the Power save state of the STA */ | ||
3738 | if (ar->arNetworkType == AP_NETWORK) { | ||
3739 | sta_t *conn = NULL; | ||
3740 | u8 psState=0,prevPsState; | ||
3741 | ATH_MAC_HDR *datap=NULL; | ||
3742 | u16 offset; | ||
3743 | |||
3744 | meta_type = WMI_DATA_HDR_GET_META(dhdr); | ||
3745 | |||
3746 | psState = (((WMI_DATA_HDR *)A_NETBUF_DATA(skb))->info | ||
3747 | >> WMI_DATA_HDR_PS_SHIFT) & WMI_DATA_HDR_PS_MASK; | ||
3748 | |||
3749 | offset = sizeof(WMI_DATA_HDR); | ||
3750 | |||
3751 | switch (meta_type) { | ||
3752 | case 0: | ||
3753 | break; | ||
3754 | case WMI_META_VERSION_1: | ||
3755 | offset += sizeof(WMI_RX_META_V1); | ||
3756 | break; | ||
3757 | case WMI_META_VERSION_2: | ||
3758 | offset += sizeof(WMI_RX_META_V2); | ||
3759 | break; | ||
3760 | default: | ||
3761 | break; | ||
3762 | } | ||
3763 | |||
3764 | datap = (ATH_MAC_HDR *)(A_NETBUF_DATA(skb)+offset); | ||
3765 | conn = ieee80211_find_conn(ar, datap->srcMac); | ||
3766 | |||
3767 | if (conn) { | ||
3768 | /* if there is a change in PS state of the STA, | ||
3769 | * take appropriate steps. | ||
3770 | * 1. If Sleep-->Awake, flush the psq for the STA | ||
3771 | * Clear the PVB for the STA. | ||
3772 | * 2. If Awake-->Sleep, Starting queueing frames | ||
3773 | * the STA. | ||
3774 | */ | ||
3775 | prevPsState = STA_IS_PWR_SLEEP(conn); | ||
3776 | if (psState) { | ||
3777 | STA_SET_PWR_SLEEP(conn); | ||
3778 | } else { | ||
3779 | STA_CLR_PWR_SLEEP(conn); | ||
3780 | } | ||
3781 | |||
3782 | if (prevPsState ^ STA_IS_PWR_SLEEP(conn)) { | ||
3783 | |||
3784 | if (!STA_IS_PWR_SLEEP(conn)) { | ||
3785 | |||
3786 | A_MUTEX_LOCK(&conn->psqLock); | ||
3787 | while (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) { | ||
3788 | struct sk_buff *skb=NULL; | ||
3789 | |||
3790 | skb = A_NETBUF_DEQUEUE(&conn->psq); | ||
3791 | A_MUTEX_UNLOCK(&conn->psqLock); | ||
3792 | ar6000_data_tx(skb,ar->arNetDev); | ||
3793 | A_MUTEX_LOCK(&conn->psqLock); | ||
3794 | } | ||
3795 | A_MUTEX_UNLOCK(&conn->psqLock); | ||
3796 | /* Clear the PVB for this STA */ | ||
3797 | wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0); | ||
3798 | } | ||
3799 | } | ||
3800 | } else { | ||
3801 | /* This frame is from a STA that is not associated*/ | ||
3802 | A_ASSERT(false); | ||
3803 | } | ||
3804 | |||
3805 | /* Drop NULL data frames here */ | ||
3806 | if((pPacket->ActualLength < minHdrLen) || | ||
3807 | (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_SIZE)) { | ||
3808 | A_NETBUF_FREE(skb); | ||
3809 | goto rx_done; | ||
3810 | } | ||
3811 | } | ||
3812 | |||
3813 | is_amsdu = WMI_DATA_HDR_IS_AMSDU(dhdr) ? true : false; | ||
3814 | tid = WMI_DATA_HDR_GET_UP(dhdr); | ||
3815 | seq_no = WMI_DATA_HDR_GET_SEQNO(dhdr); | ||
3816 | meta_type = WMI_DATA_HDR_GET_META(dhdr); | ||
3817 | containsDot11Hdr = WMI_DATA_HDR_GET_DOT11(dhdr); | ||
3818 | |||
3819 | wmi_data_hdr_remove(ar->arWmi, skb); | ||
3820 | |||
3821 | switch (meta_type) { | ||
3822 | case WMI_META_VERSION_1: | ||
3823 | { | ||
3824 | WMI_RX_META_V1 *pMeta = (WMI_RX_META_V1 *)A_NETBUF_DATA(skb); | ||
3825 | A_PRINTF("META %d %d %d %d %x\n", pMeta->status, pMeta->rix, pMeta->rssi, pMeta->channel, pMeta->flags); | ||
3826 | A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V1)); | ||
3827 | break; | ||
3828 | } | ||
3829 | case WMI_META_VERSION_2: | ||
3830 | { | ||
3831 | WMI_RX_META_V2 *pMeta = (WMI_RX_META_V2 *)A_NETBUF_DATA(skb); | ||
3832 | if(pMeta->csumFlags & 0x1){ | ||
3833 | skb->ip_summed=CHECKSUM_COMPLETE; | ||
3834 | skb->csum=(pMeta->csum); | ||
3835 | } | ||
3836 | A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V2)); | ||
3837 | break; | ||
3838 | } | ||
3839 | default: | ||
3840 | break; | ||
3841 | } | ||
3842 | |||
3843 | A_ASSERT(status == 0); | ||
3844 | |||
3845 | /* NWF: print the 802.11 hdr bytes */ | ||
3846 | if(containsDot11Hdr) { | ||
3847 | status = wmi_dot11_hdr_remove(ar->arWmi,skb); | ||
3848 | } else if(!is_amsdu) { | ||
3849 | status = wmi_dot3_2_dix(skb); | ||
3850 | } | ||
3851 | |||
3852 | if (status) { | ||
3853 | /* Drop frames that could not be processed (lack of memory, etc.) */ | ||
3854 | A_NETBUF_FREE(skb); | ||
3855 | goto rx_done; | ||
3856 | } | ||
3857 | |||
3858 | if ((ar->arNetDev->flags & IFF_UP) == IFF_UP) { | ||
3859 | if (ar->arNetworkType == AP_NETWORK) { | ||
3860 | struct sk_buff *skb1 = NULL; | ||
3861 | ATH_MAC_HDR *datap; | ||
3862 | |||
3863 | datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); | ||
3864 | if (IEEE80211_IS_MULTICAST(datap->dstMac)) { | ||
3865 | /* Bcast/Mcast frames should be sent to the OS | ||
3866 | * stack as well as on the air. | ||
3867 | */ | ||
3868 | skb1 = skb_copy(skb,GFP_ATOMIC); | ||
3869 | } else { | ||
3870 | /* Search for a connected STA with dstMac as | ||
3871 | * the Mac address. If found send the frame to | ||
3872 | * it on the air else send the frame up the | ||
3873 | * stack | ||
3874 | */ | ||
3875 | sta_t *conn = NULL; | ||
3876 | conn = ieee80211_find_conn(ar, datap->dstMac); | ||
3877 | |||
3878 | if (conn && ar->intra_bss) { | ||
3879 | skb1 = skb; | ||
3880 | skb = NULL; | ||
3881 | } else if(conn && !ar->intra_bss) { | ||
3882 | A_NETBUF_FREE(skb); | ||
3883 | skb = NULL; | ||
3884 | } | ||
3885 | } | ||
3886 | if (skb1) { | ||
3887 | ar6000_data_tx(skb1, ar->arNetDev); | ||
3888 | } | ||
3889 | } | ||
3890 | } | ||
3891 | aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, is_amsdu, (void **)&skb); | ||
3892 | ar6000_deliver_frames_to_nw_stack((void *) ar->arNetDev, (void *)skb); | ||
3893 | } | ||
3894 | } | ||
3895 | } else { | ||
3896 | if (EPPING_ALIGNMENT_PAD > 0) { | ||
3897 | A_NETBUF_PULL(skb, EPPING_ALIGNMENT_PAD); | ||
3898 | } | ||
3899 | ar6000_deliver_frames_to_nw_stack((void *)ar->arNetDev, (void *)skb); | ||
3900 | } | ||
3901 | |||
3902 | rx_done: | ||
3903 | |||
3904 | return; | ||
3905 | } | ||
3906 | |||
3907 | static void | ||
3908 | ar6000_deliver_frames_to_nw_stack(void *dev, void *osbuf) | ||
3909 | { | ||
3910 | struct sk_buff *skb = (struct sk_buff *)osbuf; | ||
3911 | |||
3912 | if(skb) { | ||
3913 | skb->dev = dev; | ||
3914 | if ((skb->dev->flags & IFF_UP) == IFF_UP) { | ||
3915 | #ifdef CONFIG_PM | ||
3916 | ar6000_check_wow_status((struct ar6_softc *)ar6k_priv(dev), skb, false); | ||
3917 | #endif /* CONFIG_PM */ | ||
3918 | skb->protocol = eth_type_trans(skb, skb->dev); | ||
3919 | /* | ||
3920 | * If this routine is called on a ISR (Hard IRQ) or DSR (Soft IRQ) | ||
3921 | * or tasklet use the netif_rx to deliver the packet to the stack | ||
3922 | * netif_rx will queue the packet onto the receive queue and mark | ||
3923 | * the softirq thread has a pending action to complete. Kernel will | ||
3924 | * schedule the softIrq kernel thread after processing the DSR. | ||
3925 | * | ||
3926 | * If this routine is called on a process context, use netif_rx_ni | ||
3927 | * which will schedle the softIrq kernel thread after queuing the packet. | ||
3928 | */ | ||
3929 | if (in_interrupt()) { | ||
3930 | netif_rx(skb); | ||
3931 | } else { | ||
3932 | netif_rx_ni(skb); | ||
3933 | } | ||
3934 | } else { | ||
3935 | A_NETBUF_FREE(skb); | ||
3936 | } | ||
3937 | } | ||
3938 | } | ||
3939 | |||
3940 | #if 0 | ||
3941 | static void | ||
3942 | ar6000_deliver_frames_to_bt_stack(void *dev, void *osbuf) | ||
3943 | { | ||
3944 | struct sk_buff *skb = (struct sk_buff *)osbuf; | ||
3945 | |||
3946 | if(skb) { | ||
3947 | skb->dev = dev; | ||
3948 | if ((skb->dev->flags & IFF_UP) == IFF_UP) { | ||
3949 | skb->protocol = htons(ETH_P_CONTROL); | ||
3950 | netif_rx(skb); | ||
3951 | } else { | ||
3952 | A_NETBUF_FREE(skb); | ||
3953 | } | ||
3954 | } | ||
3955 | } | ||
3956 | #endif | ||
3957 | |||
3958 | static void | ||
3959 | ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint) | ||
3960 | { | ||
3961 | struct ar6_softc *ar = (struct ar6_softc *)Context; | ||
3962 | void *osBuf; | ||
3963 | int RxBuffers; | ||
3964 | int buffersToRefill; | ||
3965 | struct htc_packet *pPacket; | ||
3966 | struct htc_packet_queue queue; | ||
3967 | |||
3968 | buffersToRefill = (int)AR6000_MAX_RX_BUFFERS - | ||
3969 | HTCGetNumRecvBuffers(ar->arHtcTarget, Endpoint); | ||
3970 | |||
3971 | if (buffersToRefill <= 0) { | ||
3972 | /* fast return, nothing to fill */ | ||
3973 | return; | ||
3974 | } | ||
3975 | |||
3976 | INIT_HTC_PACKET_QUEUE(&queue); | ||
3977 | |||
3978 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx_refill: providing htc with %d buffers at eid=%d\n", | ||
3979 | buffersToRefill, Endpoint)); | ||
3980 | |||
3981 | for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) { | ||
3982 | osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE); | ||
3983 | if (NULL == osBuf) { | ||
3984 | break; | ||
3985 | } | ||
3986 | /* the HTC packet wrapper is at the head of the reserved area | ||
3987 | * in the skb */ | ||
3988 | pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf)); | ||
3989 | /* set re-fill info */ | ||
3990 | SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint); | ||
3991 | /* add to queue */ | ||
3992 | HTC_PACKET_ENQUEUE(&queue,pPacket); | ||
3993 | } | ||
3994 | |||
3995 | if (!HTC_QUEUE_EMPTY(&queue)) { | ||
3996 | /* add packets */ | ||
3997 | HTCAddReceivePktMultiple(ar->arHtcTarget, &queue); | ||
3998 | } | ||
3999 | |||
4000 | } | ||
4001 | |||
4002 | /* clean up our amsdu buffer list */ | ||
4003 | static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar) | ||
4004 | { | ||
4005 | struct htc_packet *pPacket; | ||
4006 | void *osBuf; | ||
4007 | |||
4008 | /* empty AMSDU buffer queue and free OS bufs */ | ||
4009 | while (true) { | ||
4010 | |||
4011 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
4012 | pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue); | ||
4013 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
4014 | |||
4015 | if (NULL == pPacket) { | ||
4016 | break; | ||
4017 | } | ||
4018 | |||
4019 | osBuf = pPacket->pPktContext; | ||
4020 | if (NULL == osBuf) { | ||
4021 | A_ASSERT(false); | ||
4022 | break; | ||
4023 | } | ||
4024 | |||
4025 | A_NETBUF_FREE(osBuf); | ||
4026 | } | ||
4027 | |||
4028 | } | ||
4029 | |||
4030 | |||
4031 | /* refill the amsdu buffer list */ | ||
4032 | static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count) | ||
4033 | { | ||
4034 | struct htc_packet *pPacket; | ||
4035 | void *osBuf; | ||
4036 | |||
4037 | while (Count > 0) { | ||
4038 | osBuf = A_NETBUF_ALLOC(AR6000_AMSDU_BUFFER_SIZE); | ||
4039 | if (NULL == osBuf) { | ||
4040 | break; | ||
4041 | } | ||
4042 | /* the HTC packet wrapper is at the head of the reserved area | ||
4043 | * in the skb */ | ||
4044 | pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf)); | ||
4045 | /* set re-fill info */ | ||
4046 | SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_AMSDU_BUFFER_SIZE,0); | ||
4047 | |||
4048 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
4049 | /* put it in the list */ | ||
4050 | HTC_PACKET_ENQUEUE(&ar->amsdu_rx_buffer_queue,pPacket); | ||
4051 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
4052 | Count--; | ||
4053 | } | ||
4054 | |||
4055 | } | ||
4056 | |||
4057 | /* callback to allocate a large receive buffer for a pending packet. This function is called when | ||
4058 | * an HTC packet arrives whose length exceeds a threshold value | ||
4059 | * | ||
4060 | * We use a pre-allocated list of buffers of maximum AMSDU size (4K). Under linux it is more optimal to | ||
4061 | * keep the allocation size the same to optimize cached-slab allocations. | ||
4062 | * | ||
4063 | * */ | ||
4064 | static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length) | ||
4065 | { | ||
4066 | struct htc_packet *pPacket = NULL; | ||
4067 | struct ar6_softc *ar = (struct ar6_softc *)Context; | ||
4068 | int refillCount = 0; | ||
4069 | |||
4070 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_alloc_amsdu_rxbuf: eid=%d, Length:%d\n",Endpoint,Length)); | ||
4071 | |||
4072 | do { | ||
4073 | |||
4074 | if (Length <= AR6000_BUFFER_SIZE) { | ||
4075 | /* shouldn't be getting called on normal sized packets */ | ||
4076 | A_ASSERT(false); | ||
4077 | break; | ||
4078 | } | ||
4079 | |||
4080 | if (Length > AR6000_AMSDU_BUFFER_SIZE) { | ||
4081 | A_ASSERT(false); | ||
4082 | break; | ||
4083 | } | ||
4084 | |||
4085 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
4086 | /* allocate a packet from the list */ | ||
4087 | pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue); | ||
4088 | /* see if we need to refill again */ | ||
4089 | refillCount = AR6000_MAX_AMSDU_RX_BUFFERS - HTC_PACKET_QUEUE_DEPTH(&ar->amsdu_rx_buffer_queue); | ||
4090 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
4091 | |||
4092 | if (NULL == pPacket) { | ||
4093 | break; | ||
4094 | } | ||
4095 | /* set actual endpoint ID */ | ||
4096 | pPacket->Endpoint = Endpoint; | ||
4097 | |||
4098 | } while (false); | ||
4099 | |||
4100 | if (refillCount >= AR6000_AMSDU_REFILL_THRESHOLD) { | ||
4101 | ar6000_refill_amsdu_rxbufs(ar,refillCount); | ||
4102 | } | ||
4103 | |||
4104 | return pPacket; | ||
4105 | } | ||
4106 | |||
4107 | static void | ||
4108 | ar6000_set_multicast_list(struct net_device *dev) | ||
4109 | { | ||
4110 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000: Multicast filter not supported\n")); | ||
4111 | } | ||
4112 | |||
4113 | static struct net_device_stats * | ||
4114 | ar6000_get_stats(struct net_device *dev) | ||
4115 | { | ||
4116 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
4117 | return &ar->arNetStats; | ||
4118 | } | ||
4119 | |||
4120 | void | ||
4121 | ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, u32 sw_ver, u32 abi_ver) | ||
4122 | { | ||
4123 | struct ar6_softc *ar = (struct ar6_softc *)devt; | ||
4124 | struct net_device *dev = ar->arNetDev; | ||
4125 | |||
4126 | memcpy(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN); | ||
4127 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", | ||
4128 | dev->dev_addr[0], dev->dev_addr[1], | ||
4129 | dev->dev_addr[2], dev->dev_addr[3], | ||
4130 | dev->dev_addr[4], dev->dev_addr[5])); | ||
4131 | |||
4132 | ar->arPhyCapability = phyCap; | ||
4133 | ar->arVersion.wlan_ver = sw_ver; | ||
4134 | ar->arVersion.abi_ver = abi_ver; | ||
4135 | |||
4136 | snprintf(ar->wdev->wiphy->fw_version, sizeof(ar->wdev->wiphy->fw_version), | ||
4137 | "%u:%u:%u:%u", | ||
4138 | (ar->arVersion.wlan_ver & 0xf0000000) >> 28, | ||
4139 | (ar->arVersion.wlan_ver & 0x0f000000) >> 24, | ||
4140 | (ar->arVersion.wlan_ver & 0x00ff0000) >> 16, | ||
4141 | (ar->arVersion.wlan_ver & 0x0000ffff)); | ||
4142 | |||
4143 | /* Indicate to the waiting thread that the ready event was received */ | ||
4144 | ar->arWmiReady = true; | ||
4145 | wake_up(&arEvent); | ||
4146 | } | ||
4147 | |||
4148 | void ar6000_install_static_wep_keys(struct ar6_softc *ar) | ||
4149 | { | ||
4150 | u8 index; | ||
4151 | u8 keyUsage; | ||
4152 | |||
4153 | for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { | ||
4154 | if (ar->arWepKeyList[index].arKeyLen) { | ||
4155 | keyUsage = GROUP_USAGE; | ||
4156 | if (index == ar->arDefTxKeyIndex) { | ||
4157 | keyUsage |= TX_USAGE; | ||
4158 | } | ||
4159 | wmi_addKey_cmd(ar->arWmi, | ||
4160 | index, | ||
4161 | WEP_CRYPT, | ||
4162 | keyUsage, | ||
4163 | ar->arWepKeyList[index].arKeyLen, | ||
4164 | NULL, | ||
4165 | ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL, | ||
4166 | NO_SYNC_WMIFLAG); | ||
4167 | } | ||
4168 | } | ||
4169 | } | ||
4170 | |||
4171 | void | ||
4172 | add_new_sta(struct ar6_softc *ar, u8 *mac, u16 aid, u8 *wpaie, | ||
4173 | u8 ielen, u8 keymgmt, u8 ucipher, u8 auth) | ||
4174 | { | ||
4175 | u8 free_slot=aid-1; | ||
4176 | |||
4177 | memcpy(ar->sta_list[free_slot].mac, mac, ATH_MAC_LEN); | ||
4178 | memcpy(ar->sta_list[free_slot].wpa_ie, wpaie, ielen); | ||
4179 | ar->sta_list[free_slot].aid = aid; | ||
4180 | ar->sta_list[free_slot].keymgmt = keymgmt; | ||
4181 | ar->sta_list[free_slot].ucipher = ucipher; | ||
4182 | ar->sta_list[free_slot].auth = auth; | ||
4183 | ar->sta_list_index = ar->sta_list_index | (1 << free_slot); | ||
4184 | ar->arAPStats.sta[free_slot].aid = aid; | ||
4185 | } | ||
4186 | |||
4187 | void | ||
4188 | ar6000_connect_event(struct ar6_softc *ar, u16 channel, u8 *bssid, | ||
4189 | u16 listenInterval, u16 beaconInterval, | ||
4190 | NETWORK_TYPE networkType, u8 beaconIeLen, | ||
4191 | u8 assocReqLen, u8 assocRespLen, | ||
4192 | u8 *assocInfo) | ||
4193 | { | ||
4194 | union iwreq_data wrqu; | ||
4195 | int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos; | ||
4196 | static const char *tag1 = "ASSOCINFO(ReqIEs="; | ||
4197 | static const char *tag2 = "ASSOCRESPIE="; | ||
4198 | static const char *beaconIetag = "BEACONIE="; | ||
4199 | char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + strlen(tag1) + 1]; | ||
4200 | char *pos; | ||
4201 | u8 key_op_ctrl; | ||
4202 | unsigned long flags; | ||
4203 | struct ieee80211req_key *ik; | ||
4204 | CRYPTO_TYPE keyType = NONE_CRYPT; | ||
4205 | |||
4206 | if(ar->arNetworkType & AP_NETWORK) { | ||
4207 | struct net_device *dev = ar->arNetDev; | ||
4208 | if(memcmp(dev->dev_addr, bssid, ATH_MAC_LEN)==0) { | ||
4209 | ar->arACS = channel; | ||
4210 | ik = &ar->ap_mode_bkey; | ||
4211 | |||
4212 | switch(ar->arAuthMode) { | ||
4213 | case NONE_AUTH: | ||
4214 | if(ar->arPairwiseCrypto == WEP_CRYPT) { | ||
4215 | ar6000_install_static_wep_keys(ar); | ||
4216 | } | ||
4217 | #ifdef WAPI_ENABLE | ||
4218 | else if(ar->arPairwiseCrypto == WAPI_CRYPT) { | ||
4219 | ap_set_wapi_key(ar, ik); | ||
4220 | } | ||
4221 | #endif | ||
4222 | break; | ||
4223 | case WPA_PSK_AUTH: | ||
4224 | case WPA2_PSK_AUTH: | ||
4225 | case (WPA_PSK_AUTH|WPA2_PSK_AUTH): | ||
4226 | switch (ik->ik_type) { | ||
4227 | case IEEE80211_CIPHER_TKIP: | ||
4228 | keyType = TKIP_CRYPT; | ||
4229 | break; | ||
4230 | case IEEE80211_CIPHER_AES_CCM: | ||
4231 | keyType = AES_CRYPT; | ||
4232 | break; | ||
4233 | default: | ||
4234 | goto skip_key; | ||
4235 | } | ||
4236 | wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, GROUP_USAGE, | ||
4237 | ik->ik_keylen, (u8 *)&ik->ik_keyrsc, | ||
4238 | ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr, | ||
4239 | SYNC_BOTH_WMIFLAG); | ||
4240 | |||
4241 | break; | ||
4242 | } | ||
4243 | skip_key: | ||
4244 | ar->arConnected = true; | ||
4245 | return; | ||
4246 | } | ||
4247 | |||
4248 | A_PRINTF("NEW STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n " | ||
4249 | " AID=%d \n", bssid[0], bssid[1], bssid[2], | ||
4250 | bssid[3], bssid[4], bssid[5], channel); | ||
4251 | switch ((listenInterval>>8)&0xFF) { | ||
4252 | case OPEN_AUTH: | ||
4253 | A_PRINTF("AUTH: OPEN\n"); | ||
4254 | break; | ||
4255 | case SHARED_AUTH: | ||
4256 | A_PRINTF("AUTH: SHARED\n"); | ||
4257 | break; | ||
4258 | default: | ||
4259 | A_PRINTF("AUTH: Unknown\n"); | ||
4260 | break; | ||
4261 | } | ||
4262 | switch (listenInterval&0xFF) { | ||
4263 | case WPA_PSK_AUTH: | ||
4264 | A_PRINTF("KeyMgmt: WPA-PSK\n"); | ||
4265 | break; | ||
4266 | case WPA2_PSK_AUTH: | ||
4267 | A_PRINTF("KeyMgmt: WPA2-PSK\n"); | ||
4268 | break; | ||
4269 | default: | ||
4270 | A_PRINTF("KeyMgmt: NONE\n"); | ||
4271 | break; | ||
4272 | } | ||
4273 | switch (beaconInterval) { | ||
4274 | case AES_CRYPT: | ||
4275 | A_PRINTF("Cipher: AES\n"); | ||
4276 | break; | ||
4277 | case TKIP_CRYPT: | ||
4278 | A_PRINTF("Cipher: TKIP\n"); | ||
4279 | break; | ||
4280 | case WEP_CRYPT: | ||
4281 | A_PRINTF("Cipher: WEP\n"); | ||
4282 | break; | ||
4283 | #ifdef WAPI_ENABLE | ||
4284 | case WAPI_CRYPT: | ||
4285 | A_PRINTF("Cipher: WAPI\n"); | ||
4286 | break; | ||
4287 | #endif | ||
4288 | default: | ||
4289 | A_PRINTF("Cipher: NONE\n"); | ||
4290 | break; | ||
4291 | } | ||
4292 | |||
4293 | add_new_sta(ar, bssid, channel /*aid*/, | ||
4294 | assocInfo /* WPA IE */, assocRespLen /* IE len */, | ||
4295 | listenInterval&0xFF /* Keymgmt */, beaconInterval /* cipher */, | ||
4296 | (listenInterval>>8)&0xFF /* auth alg */); | ||
4297 | |||
4298 | /* Send event to application */ | ||
4299 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
4300 | memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN); | ||
4301 | wireless_send_event(ar->arNetDev, IWEVREGISTERED, &wrqu, NULL); | ||
4302 | /* In case the queue is stopped when we switch modes, this will | ||
4303 | * wake it up | ||
4304 | */ | ||
4305 | netif_wake_queue(ar->arNetDev); | ||
4306 | return; | ||
4307 | } | ||
4308 | |||
4309 | ar6k_cfg80211_connect_event(ar, channel, bssid, | ||
4310 | listenInterval, beaconInterval, | ||
4311 | networkType, beaconIeLen, | ||
4312 | assocReqLen, assocRespLen, | ||
4313 | assocInfo); | ||
4314 | |||
4315 | memcpy(ar->arBssid, bssid, sizeof(ar->arBssid)); | ||
4316 | ar->arBssChannel = channel; | ||
4317 | |||
4318 | A_PRINTF("AR6000 connected event on freq %d ", channel); | ||
4319 | A_PRINTF("with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " | ||
4320 | " listenInterval=%d, beaconInterval = %d, beaconIeLen = %d assocReqLen=%d" | ||
4321 | " assocRespLen =%d\n", | ||
4322 | bssid[0], bssid[1], bssid[2], | ||
4323 | bssid[3], bssid[4], bssid[5], | ||
4324 | listenInterval, beaconInterval, | ||
4325 | beaconIeLen, assocReqLen, assocRespLen); | ||
4326 | if (networkType & ADHOC_NETWORK) { | ||
4327 | if (networkType & ADHOC_CREATOR) { | ||
4328 | A_PRINTF("Network: Adhoc (Creator)\n"); | ||
4329 | } else { | ||
4330 | A_PRINTF("Network: Adhoc (Joiner)\n"); | ||
4331 | } | ||
4332 | } else { | ||
4333 | A_PRINTF("Network: Infrastructure\n"); | ||
4334 | } | ||
4335 | |||
4336 | if ((ar->arNetworkType == INFRA_NETWORK)) { | ||
4337 | wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB); | ||
4338 | } | ||
4339 | |||
4340 | if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) { | ||
4341 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nBeaconIEs= ")); | ||
4342 | |||
4343 | beacon_ie_pos = 0; | ||
4344 | A_MEMZERO(buf, sizeof(buf)); | ||
4345 | sprintf(buf, "%s", beaconIetag); | ||
4346 | pos = buf + 9; | ||
4347 | for (i = beacon_ie_pos; i < beacon_ie_pos + beaconIeLen; i++) { | ||
4348 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); | ||
4349 | sprintf(pos, "%2.2x", assocInfo[i]); | ||
4350 | pos += 2; | ||
4351 | } | ||
4352 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); | ||
4353 | |||
4354 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
4355 | wrqu.data.length = strlen(buf); | ||
4356 | wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); | ||
4357 | } | ||
4358 | |||
4359 | if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2)))) | ||
4360 | { | ||
4361 | assoc_resp_ie_pos = beaconIeLen + assocReqLen + | ||
4362 | sizeof(u16) + /* capinfo*/ | ||
4363 | sizeof(u16) + /* status Code */ | ||
4364 | sizeof(u16) ; /* associd */ | ||
4365 | A_MEMZERO(buf, sizeof(buf)); | ||
4366 | sprintf(buf, "%s", tag2); | ||
4367 | pos = buf + 12; | ||
4368 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocRespIEs= ")); | ||
4369 | /* | ||
4370 | * The Association Response Frame w.o. the WLAN header is delivered to | ||
4371 | * the host, so skip over to the IEs | ||
4372 | */ | ||
4373 | for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i++) | ||
4374 | { | ||
4375 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); | ||
4376 | sprintf(pos, "%2.2x", assocInfo[i]); | ||
4377 | pos += 2; | ||
4378 | } | ||
4379 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); | ||
4380 | |||
4381 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
4382 | wrqu.data.length = strlen(buf); | ||
4383 | wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); | ||
4384 | } | ||
4385 | |||
4386 | if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) { | ||
4387 | /* | ||
4388 | * assoc Request includes capability and listen interval. Skip these. | ||
4389 | */ | ||
4390 | assoc_req_ie_pos = beaconIeLen + | ||
4391 | sizeof(u16) + /* capinfo*/ | ||
4392 | sizeof(u16); /* listen interval */ | ||
4393 | |||
4394 | A_MEMZERO(buf, sizeof(buf)); | ||
4395 | sprintf(buf, "%s", tag1); | ||
4396 | pos = buf + 17; | ||
4397 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AssocReqIEs= ")); | ||
4398 | for (i = assoc_req_ie_pos; i < assoc_req_ie_pos + assocReqLen - 4; i++) { | ||
4399 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); | ||
4400 | sprintf(pos, "%2.2x", assocInfo[i]); | ||
4401 | pos += 2; | ||
4402 | } | ||
4403 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); | ||
4404 | |||
4405 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
4406 | wrqu.data.length = strlen(buf); | ||
4407 | wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); | ||
4408 | } | ||
4409 | |||
4410 | if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN && | ||
4411 | ar->user_saved_keys.keyOk == true) | ||
4412 | { | ||
4413 | key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC; | ||
4414 | |||
4415 | if (ar->user_key_ctrl & AR6000_USER_SETKEYS_RSC_UNCHANGED) { | ||
4416 | key_op_ctrl &= ~KEY_OP_INIT_RSC; | ||
4417 | } else { | ||
4418 | key_op_ctrl |= KEY_OP_INIT_RSC; | ||
4419 | } | ||
4420 | ar6000_reinstall_keys(ar, key_op_ctrl); | ||
4421 | } | ||
4422 | |||
4423 | netif_wake_queue(ar->arNetDev); | ||
4424 | |||
4425 | /* Update connect & link status atomically */ | ||
4426 | spin_lock_irqsave(&ar->arLock, flags); | ||
4427 | ar->arConnected = true; | ||
4428 | ar->arConnectPending = false; | ||
4429 | netif_carrier_on(ar->arNetDev); | ||
4430 | spin_unlock_irqrestore(&ar->arLock, flags); | ||
4431 | /* reset the rx aggr state */ | ||
4432 | aggr_reset_state(ar->aggr_cntxt); | ||
4433 | reconnect_flag = 0; | ||
4434 | |||
4435 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
4436 | memcpy(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN); | ||
4437 | wrqu.addr.sa_family = ARPHRD_ETHER; | ||
4438 | wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL); | ||
4439 | if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) { | ||
4440 | A_MEMZERO(ar->arNodeMap, sizeof(ar->arNodeMap)); | ||
4441 | ar->arNodeNum = 0; | ||
4442 | ar->arNexEpId = ENDPOINT_2; | ||
4443 | } | ||
4444 | if (!ar->arUserBssFilter) { | ||
4445 | wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); | ||
4446 | } | ||
4447 | |||
4448 | } | ||
4449 | |||
4450 | void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num) | ||
4451 | { | ||
4452 | A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1)); | ||
4453 | ar->arNumDataEndPts = num; | ||
4454 | } | ||
4455 | |||
4456 | void | ||
4457 | sta_cleanup(struct ar6_softc *ar, u8 i) | ||
4458 | { | ||
4459 | struct sk_buff *skb; | ||
4460 | |||
4461 | /* empty the queued pkts in the PS queue if any */ | ||
4462 | A_MUTEX_LOCK(&ar->sta_list[i].psqLock); | ||
4463 | while (!A_NETBUF_QUEUE_EMPTY(&ar->sta_list[i].psq)) { | ||
4464 | skb = A_NETBUF_DEQUEUE(&ar->sta_list[i].psq); | ||
4465 | A_NETBUF_FREE(skb); | ||
4466 | } | ||
4467 | A_MUTEX_UNLOCK(&ar->sta_list[i].psqLock); | ||
4468 | |||
4469 | /* Zero out the state fields */ | ||
4470 | A_MEMZERO(&ar->arAPStats.sta[ar->sta_list[i].aid-1], sizeof(WMI_PER_STA_STAT)); | ||
4471 | A_MEMZERO(&ar->sta_list[i].mac, ATH_MAC_LEN); | ||
4472 | A_MEMZERO(&ar->sta_list[i].wpa_ie, IEEE80211_MAX_IE); | ||
4473 | ar->sta_list[i].aid = 0; | ||
4474 | ar->sta_list[i].flags = 0; | ||
4475 | |||
4476 | ar->sta_list_index = ar->sta_list_index & ~(1 << i); | ||
4477 | |||
4478 | } | ||
4479 | |||
4480 | u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason) | ||
4481 | { | ||
4482 | u8 i, removed=0; | ||
4483 | |||
4484 | if(IS_MAC_NULL(mac)) { | ||
4485 | return removed; | ||
4486 | } | ||
4487 | |||
4488 | if(IS_MAC_BCAST(mac)) { | ||
4489 | A_PRINTF("DEL ALL STA\n"); | ||
4490 | for(i=0; i < AP_MAX_NUM_STA; i++) { | ||
4491 | if(!IS_MAC_NULL(ar->sta_list[i].mac)) { | ||
4492 | sta_cleanup(ar, i); | ||
4493 | removed = 1; | ||
4494 | } | ||
4495 | } | ||
4496 | } else { | ||
4497 | for(i=0; i < AP_MAX_NUM_STA; i++) { | ||
4498 | if(memcmp(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) { | ||
4499 | A_PRINTF("DEL STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " | ||
4500 | " aid=%d REASON=%d\n", mac[0], mac[1], mac[2], | ||
4501 | mac[3], mac[4], mac[5], ar->sta_list[i].aid, reason); | ||
4502 | |||
4503 | sta_cleanup(ar, i); | ||
4504 | removed = 1; | ||
4505 | break; | ||
4506 | } | ||
4507 | } | ||
4508 | } | ||
4509 | return removed; | ||
4510 | } | ||
4511 | |||
4512 | void | ||
4513 | ar6000_disconnect_event(struct ar6_softc *ar, u8 reason, u8 *bssid, | ||
4514 | u8 assocRespLen, u8 *assocInfo, u16 protocolReasonStatus) | ||
4515 | { | ||
4516 | u8 i; | ||
4517 | unsigned long flags; | ||
4518 | union iwreq_data wrqu; | ||
4519 | |||
4520 | if(ar->arNetworkType & AP_NETWORK) { | ||
4521 | union iwreq_data wrqu; | ||
4522 | struct sk_buff *skb; | ||
4523 | |||
4524 | if(!remove_sta(ar, bssid, protocolReasonStatus)) { | ||
4525 | return; | ||
4526 | } | ||
4527 | |||
4528 | /* If there are no more associated STAs, empty the mcast PS q */ | ||
4529 | if (ar->sta_list_index == 0) { | ||
4530 | A_MUTEX_LOCK(&ar->mcastpsqLock); | ||
4531 | while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { | ||
4532 | skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); | ||
4533 | A_NETBUF_FREE(skb); | ||
4534 | } | ||
4535 | A_MUTEX_UNLOCK(&ar->mcastpsqLock); | ||
4536 | |||
4537 | /* Clear the LSB of the BitMapCtl field of the TIM IE */ | ||
4538 | if (ar->arWmiReady) { | ||
4539 | wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0); | ||
4540 | } | ||
4541 | } | ||
4542 | |||
4543 | if(!IS_MAC_BCAST(bssid)) { | ||
4544 | /* Send event to application */ | ||
4545 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
4546 | memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN); | ||
4547 | wireless_send_event(ar->arNetDev, IWEVEXPIRED, &wrqu, NULL); | ||
4548 | } | ||
4549 | |||
4550 | ar->arConnected = false; | ||
4551 | return; | ||
4552 | } | ||
4553 | |||
4554 | ar6k_cfg80211_disconnect_event(ar, reason, bssid, | ||
4555 | assocRespLen, assocInfo, | ||
4556 | protocolReasonStatus); | ||
4557 | |||
4558 | /* Send disconnect event to supplicant */ | ||
4559 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
4560 | wrqu.addr.sa_family = ARPHRD_ETHER; | ||
4561 | wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL); | ||
4562 | |||
4563 | /* it is necessary to clear the host-side rx aggregation state */ | ||
4564 | aggr_reset_state(ar->aggr_cntxt); | ||
4565 | |||
4566 | A_UNTIMEOUT(&ar->disconnect_timer); | ||
4567 | |||
4568 | A_PRINTF("AR6000 disconnected"); | ||
4569 | if (bssid[0] || bssid[1] || bssid[2] || bssid[3] || bssid[4] || bssid[5]) { | ||
4570 | A_PRINTF(" from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", | ||
4571 | bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); | ||
4572 | } | ||
4573 | |||
4574 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nDisconnect Reason is %d", reason)); | ||
4575 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nProtocol Reason/Status Code is %d", protocolReasonStatus)); | ||
4576 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocResp Frame = %s", | ||
4577 | assocRespLen ? " " : "NULL")); | ||
4578 | for (i = 0; i < assocRespLen; i++) { | ||
4579 | if (!(i % 0x10)) { | ||
4580 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); | ||
4581 | } | ||
4582 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); | ||
4583 | } | ||
4584 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); | ||
4585 | /* | ||
4586 | * If the event is due to disconnect cmd from the host, only they the target | ||
4587 | * would stop trying to connect. Under any other condition, target would | ||
4588 | * keep trying to connect. | ||
4589 | * | ||
4590 | */ | ||
4591 | if( reason == DISCONNECT_CMD) | ||
4592 | { | ||
4593 | if ((!ar->arUserBssFilter) && (ar->arWmiReady)) { | ||
4594 | wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); | ||
4595 | } | ||
4596 | } else { | ||
4597 | ar->arConnectPending = true; | ||
4598 | if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) || | ||
4599 | ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) { | ||
4600 | ar->arConnected = true; | ||
4601 | return; | ||
4602 | } | ||
4603 | } | ||
4604 | |||
4605 | if ((reason == NO_NETWORK_AVAIL) && (ar->arWmiReady)) | ||
4606 | { | ||
4607 | bss_t *pWmiSsidnode = NULL; | ||
4608 | |||
4609 | /* remove the current associated bssid node */ | ||
4610 | wmi_free_node (ar->arWmi, bssid); | ||
4611 | |||
4612 | /* | ||
4613 | * In case any other same SSID nodes are present | ||
4614 | * remove it, since those nodes also not available now | ||
4615 | */ | ||
4616 | do | ||
4617 | { | ||
4618 | /* | ||
4619 | * Find the nodes based on SSID and remove it | ||
4620 | * NOTE :: This case will not work out for Hidden-SSID | ||
4621 | */ | ||
4622 | pWmiSsidnode = wmi_find_Ssidnode (ar->arWmi, ar->arSsid, ar->arSsidLen, false, true); | ||
4623 | |||
4624 | if (pWmiSsidnode) | ||
4625 | { | ||
4626 | wmi_free_node (ar->arWmi, pWmiSsidnode->ni_macaddr); | ||
4627 | } | ||
4628 | |||
4629 | } while (pWmiSsidnode); | ||
4630 | } | ||
4631 | |||
4632 | /* Update connect & link status atomically */ | ||
4633 | spin_lock_irqsave(&ar->arLock, flags); | ||
4634 | ar->arConnected = false; | ||
4635 | netif_carrier_off(ar->arNetDev); | ||
4636 | spin_unlock_irqrestore(&ar->arLock, flags); | ||
4637 | |||
4638 | if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) { | ||
4639 | reconnect_flag = 0; | ||
4640 | } | ||
4641 | |||
4642 | if (reason != CSERV_DISCONNECT) | ||
4643 | { | ||
4644 | ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; | ||
4645 | ar->user_key_ctrl = 0; | ||
4646 | } | ||
4647 | |||
4648 | netif_stop_queue(ar->arNetDev); | ||
4649 | A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); | ||
4650 | ar->arBssChannel = 0; | ||
4651 | ar->arBeaconInterval = 0; | ||
4652 | |||
4653 | ar6000_TxDataCleanup(ar); | ||
4654 | } | ||
4655 | |||
4656 | void | ||
4657 | ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode) | ||
4658 | { | ||
4659 | A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode); | ||
4660 | ar->arRegCode = regCode; | ||
4661 | } | ||
4662 | |||
4663 | void | ||
4664 | ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *evt) | ||
4665 | { | ||
4666 | if(evt->status == 0) { | ||
4667 | aggr_recv_addba_req_evt(ar->aggr_cntxt, evt->tid, evt->st_seq_no, evt->win_sz); | ||
4668 | } | ||
4669 | } | ||
4670 | |||
4671 | void | ||
4672 | ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *evt) | ||
4673 | { | ||
4674 | A_PRINTF("ADDBA RESP. tid %d status %d, sz %d\n", evt->tid, evt->status, evt->amsdu_sz); | ||
4675 | if(evt->status == 0) { | ||
4676 | } | ||
4677 | } | ||
4678 | |||
4679 | void | ||
4680 | ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *evt) | ||
4681 | { | ||
4682 | aggr_recv_delba_req_evt(ar->aggr_cntxt, evt->tid); | ||
4683 | } | ||
4684 | |||
4685 | void register_pal_cb(ar6k_pal_config_t *palConfig_p) | ||
4686 | { | ||
4687 | ar6k_pal_config_g = *palConfig_p; | ||
4688 | } | ||
4689 | |||
4690 | void | ||
4691 | ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd) | ||
4692 | { | ||
4693 | void *osbuf = NULL; | ||
4694 | s8 i; | ||
4695 | u8 size, *buf; | ||
4696 | int ret = 0; | ||
4697 | |||
4698 | size = cmd->evt_buf_sz + 4; | ||
4699 | osbuf = A_NETBUF_ALLOC(size); | ||
4700 | if (osbuf == NULL) { | ||
4701 | ret = A_NO_MEMORY; | ||
4702 | A_PRINTF("Error in allocating netbuf \n"); | ||
4703 | return; | ||
4704 | } | ||
4705 | |||
4706 | A_NETBUF_PUT(osbuf, size); | ||
4707 | buf = (u8 *)A_NETBUF_DATA(osbuf); | ||
4708 | /* First 2-bytes carry HCI event/ACL data type | ||
4709 | * the next 2 are free | ||
4710 | */ | ||
4711 | *((short *)buf) = WMI_HCI_EVENT_EVENTID; | ||
4712 | buf += sizeof(int); | ||
4713 | memcpy(buf, cmd->buf, cmd->evt_buf_sz); | ||
4714 | |||
4715 | ar6000_deliver_frames_to_nw_stack(ar->arNetDev, osbuf); | ||
4716 | if(loghci) { | ||
4717 | A_PRINTF_LOG("HCI Event From PAL <-- \n"); | ||
4718 | for(i = 0; i < cmd->evt_buf_sz; i++) { | ||
4719 | A_PRINTF_LOG("0x%02x ", cmd->buf[i]); | ||
4720 | if((i % 10) == 0) { | ||
4721 | A_PRINTF_LOG("\n"); | ||
4722 | } | ||
4723 | } | ||
4724 | A_PRINTF_LOG("\n"); | ||
4725 | A_PRINTF_LOG("==================================\n"); | ||
4726 | } | ||
4727 | } | ||
4728 | |||
4729 | void | ||
4730 | ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, WMI_NEIGHBOR_INFO *info) | ||
4731 | { | ||
4732 | #if WIRELESS_EXT >= 18 | ||
4733 | struct iw_pmkid_cand *pmkcand; | ||
4734 | #else /* WIRELESS_EXT >= 18 */ | ||
4735 | static const char *tag = "PRE-AUTH"; | ||
4736 | char buf[128]; | ||
4737 | #endif /* WIRELESS_EXT >= 18 */ | ||
4738 | |||
4739 | union iwreq_data wrqu; | ||
4740 | int i; | ||
4741 | |||
4742 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("AR6000 Neighbor Report Event\n")); | ||
4743 | for (i=0; i < numAps; info++, i++) { | ||
4744 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", | ||
4745 | info->bssid[0], info->bssid[1], info->bssid[2], | ||
4746 | info->bssid[3], info->bssid[4], info->bssid[5])); | ||
4747 | if (info->bssFlags & WMI_PREAUTH_CAPABLE_BSS) { | ||
4748 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("preauth-cap")); | ||
4749 | } | ||
4750 | if (info->bssFlags & WMI_PMKID_VALID_BSS) { | ||
4751 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,(" pmkid-valid\n")); | ||
4752 | continue; /* we skip bss if the pmkid is already valid */ | ||
4753 | } | ||
4754 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("\n")); | ||
4755 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
4756 | #if WIRELESS_EXT >= 18 | ||
4757 | pmkcand = A_MALLOC_NOWAIT(sizeof(struct iw_pmkid_cand)); | ||
4758 | A_MEMZERO(pmkcand, sizeof(struct iw_pmkid_cand)); | ||
4759 | pmkcand->index = i; | ||
4760 | pmkcand->flags = info->bssFlags; | ||
4761 | memcpy(pmkcand->bssid.sa_data, info->bssid, ATH_MAC_LEN); | ||
4762 | wrqu.data.length = sizeof(struct iw_pmkid_cand); | ||
4763 | wireless_send_event(ar->arNetDev, IWEVPMKIDCAND, &wrqu, (char *)pmkcand); | ||
4764 | kfree(pmkcand); | ||
4765 | #else /* WIRELESS_EXT >= 18 */ | ||
4766 | snprintf(buf, sizeof(buf), "%s%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x", | ||
4767 | tag, | ||
4768 | info->bssid[0], info->bssid[1], info->bssid[2], | ||
4769 | info->bssid[3], info->bssid[4], info->bssid[5], | ||
4770 | i, info->bssFlags); | ||
4771 | wrqu.data.length = strlen(buf); | ||
4772 | wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); | ||
4773 | #endif /* WIRELESS_EXT >= 18 */ | ||
4774 | } | ||
4775 | } | ||
4776 | |||
4777 | void | ||
4778 | ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast) | ||
4779 | { | ||
4780 | static const char *tag = "MLME-MICHAELMICFAILURE.indication"; | ||
4781 | char buf[128]; | ||
4782 | union iwreq_data wrqu; | ||
4783 | |||
4784 | /* | ||
4785 | * For AP case, keyid will have aid of STA which sent pkt with | ||
4786 | * MIC error. Use this aid to get MAC & send it to hostapd. | ||
4787 | */ | ||
4788 | if (ar->arNetworkType == AP_NETWORK) { | ||
4789 | sta_t *s = ieee80211_find_conn_for_aid(ar, (keyid >> 2)); | ||
4790 | if(!s){ | ||
4791 | A_PRINTF("AP TKIP MIC error received from Invalid aid / STA not found =%d\n", keyid); | ||
4792 | return; | ||
4793 | } | ||
4794 | A_PRINTF("AP TKIP MIC error received from aid=%d\n", keyid); | ||
4795 | snprintf(buf,sizeof(buf), "%s addr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", | ||
4796 | tag, s->mac[0],s->mac[1],s->mac[2],s->mac[3],s->mac[4],s->mac[5]); | ||
4797 | } else { | ||
4798 | |||
4799 | ar6k_cfg80211_tkip_micerr_event(ar, keyid, ismcast); | ||
4800 | |||
4801 | A_PRINTF("AR6000 TKIP MIC error received for keyid %d %scast\n", | ||
4802 | keyid & 0x3, ismcast ? "multi": "uni"); | ||
4803 | snprintf(buf, sizeof(buf), "%s(keyid=%d %sicast)", tag, keyid & 0x3, | ||
4804 | ismcast ? "mult" : "un"); | ||
4805 | } | ||
4806 | |||
4807 | memset(&wrqu, 0, sizeof(wrqu)); | ||
4808 | wrqu.data.length = strlen(buf); | ||
4809 | wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); | ||
4810 | } | ||
4811 | |||
4812 | void | ||
4813 | ar6000_scanComplete_event(struct ar6_softc *ar, int status) | ||
4814 | { | ||
4815 | |||
4816 | ar6k_cfg80211_scanComplete_event(ar, status); | ||
4817 | |||
4818 | if (!ar->arUserBssFilter) { | ||
4819 | wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); | ||
4820 | } | ||
4821 | if (ar->scan_triggered) { | ||
4822 | if (status== 0) { | ||
4823 | union iwreq_data wrqu; | ||
4824 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
4825 | wireless_send_event(ar->arNetDev, SIOCGIWSCAN, &wrqu, NULL); | ||
4826 | } | ||
4827 | ar->scan_triggered = 0; | ||
4828 | } | ||
4829 | |||
4830 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,( "AR6000 scan complete: %d\n", status)); | ||
4831 | } | ||
4832 | |||
4833 | void | ||
4834 | ar6000_targetStats_event(struct ar6_softc *ar, u8 *ptr, u32 len) | ||
4835 | { | ||
4836 | u8 ac; | ||
4837 | |||
4838 | if(ar->arNetworkType == AP_NETWORK) { | ||
4839 | WMI_AP_MODE_STAT *p = (WMI_AP_MODE_STAT *)ptr; | ||
4840 | WMI_AP_MODE_STAT *ap = &ar->arAPStats; | ||
4841 | |||
4842 | if (len < sizeof(*p)) { | ||
4843 | return; | ||
4844 | } | ||
4845 | |||
4846 | for(ac=0;ac<AP_MAX_NUM_STA;ac++) { | ||
4847 | ap->sta[ac].tx_bytes += p->sta[ac].tx_bytes; | ||
4848 | ap->sta[ac].tx_pkts += p->sta[ac].tx_pkts; | ||
4849 | ap->sta[ac].tx_error += p->sta[ac].tx_error; | ||
4850 | ap->sta[ac].tx_discard += p->sta[ac].tx_discard; | ||
4851 | ap->sta[ac].rx_bytes += p->sta[ac].rx_bytes; | ||
4852 | ap->sta[ac].rx_pkts += p->sta[ac].rx_pkts; | ||
4853 | ap->sta[ac].rx_error += p->sta[ac].rx_error; | ||
4854 | ap->sta[ac].rx_discard += p->sta[ac].rx_discard; | ||
4855 | } | ||
4856 | |||
4857 | } else { | ||
4858 | WMI_TARGET_STATS *pTarget = (WMI_TARGET_STATS *)ptr; | ||
4859 | TARGET_STATS *pStats = &ar->arTargetStats; | ||
4860 | |||
4861 | if (len < sizeof(*pTarget)) { | ||
4862 | return; | ||
4863 | } | ||
4864 | |||
4865 | // Update the RSSI of the connected bss. | ||
4866 | if (ar->arConnected) { | ||
4867 | bss_t *pConnBss = NULL; | ||
4868 | |||
4869 | pConnBss = wmi_find_node(ar->arWmi,ar->arBssid); | ||
4870 | if (pConnBss) | ||
4871 | { | ||
4872 | pConnBss->ni_rssi = pTarget->cservStats.cs_aveBeacon_rssi; | ||
4873 | pConnBss->ni_snr = pTarget->cservStats.cs_aveBeacon_snr; | ||
4874 | wmi_node_return(ar->arWmi, pConnBss); | ||
4875 | } | ||
4876 | } | ||
4877 | |||
4878 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 updating target stats\n")); | ||
4879 | pStats->tx_packets += pTarget->txrxStats.tx_stats.tx_packets; | ||
4880 | pStats->tx_bytes += pTarget->txrxStats.tx_stats.tx_bytes; | ||
4881 | pStats->tx_unicast_pkts += pTarget->txrxStats.tx_stats.tx_unicast_pkts; | ||
4882 | pStats->tx_unicast_bytes += pTarget->txrxStats.tx_stats.tx_unicast_bytes; | ||
4883 | pStats->tx_multicast_pkts += pTarget->txrxStats.tx_stats.tx_multicast_pkts; | ||
4884 | pStats->tx_multicast_bytes += pTarget->txrxStats.tx_stats.tx_multicast_bytes; | ||
4885 | pStats->tx_broadcast_pkts += pTarget->txrxStats.tx_stats.tx_broadcast_pkts; | ||
4886 | pStats->tx_broadcast_bytes += pTarget->txrxStats.tx_stats.tx_broadcast_bytes; | ||
4887 | pStats->tx_rts_success_cnt += pTarget->txrxStats.tx_stats.tx_rts_success_cnt; | ||
4888 | for(ac = 0; ac < WMM_NUM_AC; ac++) | ||
4889 | pStats->tx_packet_per_ac[ac] += pTarget->txrxStats.tx_stats.tx_packet_per_ac[ac]; | ||
4890 | pStats->tx_errors += pTarget->txrxStats.tx_stats.tx_errors; | ||
4891 | pStats->tx_failed_cnt += pTarget->txrxStats.tx_stats.tx_failed_cnt; | ||
4892 | pStats->tx_retry_cnt += pTarget->txrxStats.tx_stats.tx_retry_cnt; | ||
4893 | pStats->tx_mult_retry_cnt += pTarget->txrxStats.tx_stats.tx_mult_retry_cnt; | ||
4894 | pStats->tx_rts_fail_cnt += pTarget->txrxStats.tx_stats.tx_rts_fail_cnt; | ||
4895 | pStats->tx_unicast_rate = wmi_get_rate(pTarget->txrxStats.tx_stats.tx_unicast_rate); | ||
4896 | |||
4897 | pStats->rx_packets += pTarget->txrxStats.rx_stats.rx_packets; | ||
4898 | pStats->rx_bytes += pTarget->txrxStats.rx_stats.rx_bytes; | ||
4899 | pStats->rx_unicast_pkts += pTarget->txrxStats.rx_stats.rx_unicast_pkts; | ||
4900 | pStats->rx_unicast_bytes += pTarget->txrxStats.rx_stats.rx_unicast_bytes; | ||
4901 | pStats->rx_multicast_pkts += pTarget->txrxStats.rx_stats.rx_multicast_pkts; | ||
4902 | pStats->rx_multicast_bytes += pTarget->txrxStats.rx_stats.rx_multicast_bytes; | ||
4903 | pStats->rx_broadcast_pkts += pTarget->txrxStats.rx_stats.rx_broadcast_pkts; | ||
4904 | pStats->rx_broadcast_bytes += pTarget->txrxStats.rx_stats.rx_broadcast_bytes; | ||
4905 | pStats->rx_fragment_pkt += pTarget->txrxStats.rx_stats.rx_fragment_pkt; | ||
4906 | pStats->rx_errors += pTarget->txrxStats.rx_stats.rx_errors; | ||
4907 | pStats->rx_crcerr += pTarget->txrxStats.rx_stats.rx_crcerr; | ||
4908 | pStats->rx_key_cache_miss += pTarget->txrxStats.rx_stats.rx_key_cache_miss; | ||
4909 | pStats->rx_decrypt_err += pTarget->txrxStats.rx_stats.rx_decrypt_err; | ||
4910 | pStats->rx_duplicate_frames += pTarget->txrxStats.rx_stats.rx_duplicate_frames; | ||
4911 | pStats->rx_unicast_rate = wmi_get_rate(pTarget->txrxStats.rx_stats.rx_unicast_rate); | ||
4912 | |||
4913 | |||
4914 | pStats->tkip_local_mic_failure | ||
4915 | += pTarget->txrxStats.tkipCcmpStats.tkip_local_mic_failure; | ||
4916 | pStats->tkip_counter_measures_invoked | ||
4917 | += pTarget->txrxStats.tkipCcmpStats.tkip_counter_measures_invoked; | ||
4918 | pStats->tkip_replays += pTarget->txrxStats.tkipCcmpStats.tkip_replays; | ||
4919 | pStats->tkip_format_errors += pTarget->txrxStats.tkipCcmpStats.tkip_format_errors; | ||
4920 | pStats->ccmp_format_errors += pTarget->txrxStats.tkipCcmpStats.ccmp_format_errors; | ||
4921 | pStats->ccmp_replays += pTarget->txrxStats.tkipCcmpStats.ccmp_replays; | ||
4922 | |||
4923 | pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cnt; | ||
4924 | pStats->noise_floor_calibation = pTarget->noise_floor_calibation; | ||
4925 | |||
4926 | pStats->cs_bmiss_cnt += pTarget->cservStats.cs_bmiss_cnt; | ||
4927 | pStats->cs_lowRssi_cnt += pTarget->cservStats.cs_lowRssi_cnt; | ||
4928 | pStats->cs_connect_cnt += pTarget->cservStats.cs_connect_cnt; | ||
4929 | pStats->cs_disconnect_cnt += pTarget->cservStats.cs_disconnect_cnt; | ||
4930 | pStats->cs_aveBeacon_snr = pTarget->cservStats.cs_aveBeacon_snr; | ||
4931 | pStats->cs_aveBeacon_rssi = pTarget->cservStats.cs_aveBeacon_rssi; | ||
4932 | |||
4933 | if (enablerssicompensation) { | ||
4934 | pStats->cs_aveBeacon_rssi = | ||
4935 | rssi_compensation_calc(ar, pStats->cs_aveBeacon_rssi); | ||
4936 | } | ||
4937 | pStats->cs_lastRoam_msec = pTarget->cservStats.cs_lastRoam_msec; | ||
4938 | pStats->cs_snr = pTarget->cservStats.cs_snr; | ||
4939 | pStats->cs_rssi = pTarget->cservStats.cs_rssi; | ||
4940 | |||
4941 | pStats->lq_val = pTarget->lqVal; | ||
4942 | |||
4943 | pStats->wow_num_pkts_dropped += pTarget->wowStats.wow_num_pkts_dropped; | ||
4944 | pStats->wow_num_host_pkt_wakeups += pTarget->wowStats.wow_num_host_pkt_wakeups; | ||
4945 | pStats->wow_num_host_event_wakeups += pTarget->wowStats.wow_num_host_event_wakeups; | ||
4946 | pStats->wow_num_events_discarded += pTarget->wowStats.wow_num_events_discarded; | ||
4947 | pStats->arp_received += pTarget->arpStats.arp_received; | ||
4948 | pStats->arp_matched += pTarget->arpStats.arp_matched; | ||
4949 | pStats->arp_replied += pTarget->arpStats.arp_replied; | ||
4950 | |||
4951 | if (ar->statsUpdatePending) { | ||
4952 | ar->statsUpdatePending = false; | ||
4953 | wake_up(&arEvent); | ||
4954 | } | ||
4955 | } | ||
4956 | } | ||
4957 | |||
4958 | void | ||
4959 | ar6000_rssiThreshold_event(struct ar6_softc *ar, WMI_RSSI_THRESHOLD_VAL newThreshold, s16 rssi) | ||
4960 | { | ||
4961 | USER_RSSI_THOLD userRssiThold; | ||
4962 | |||
4963 | rssi = rssi + SIGNAL_QUALITY_NOISE_FLOOR; | ||
4964 | |||
4965 | if (enablerssicompensation) { | ||
4966 | rssi = rssi_compensation_calc(ar, rssi); | ||
4967 | } | ||
4968 | |||
4969 | /* Send an event to the app */ | ||
4970 | userRssiThold.tag = ar->rssi_map[newThreshold].tag; | ||
4971 | userRssiThold.rssi = rssi; | ||
4972 | A_PRINTF("rssi Threshold range = %d tag = %d rssi = %d\n", newThreshold, | ||
4973 | userRssiThold.tag, userRssiThold.rssi); | ||
4974 | } | ||
4975 | |||
4976 | |||
4977 | void | ||
4978 | ar6000_hbChallengeResp_event(struct ar6_softc *ar, u32 cookie, u32 source) | ||
4979 | { | ||
4980 | if (source != APP_HB_CHALLENGE) { | ||
4981 | /* This would ignore the replys that come in after their due time */ | ||
4982 | if (cookie == ar->arHBChallengeResp.seqNum) { | ||
4983 | ar->arHBChallengeResp.outstanding = false; | ||
4984 | } | ||
4985 | } | ||
4986 | } | ||
4987 | |||
4988 | |||
4989 | void | ||
4990 | ar6000_reportError_event(struct ar6_softc *ar, WMI_TARGET_ERROR_VAL errorVal) | ||
4991 | { | ||
4992 | static const char * const errString[] = { | ||
4993 | [WMI_TARGET_PM_ERR_FAIL] "WMI_TARGET_PM_ERR_FAIL", | ||
4994 | [WMI_TARGET_KEY_NOT_FOUND] "WMI_TARGET_KEY_NOT_FOUND", | ||
4995 | [WMI_TARGET_DECRYPTION_ERR] "WMI_TARGET_DECRYPTION_ERR", | ||
4996 | [WMI_TARGET_BMISS] "WMI_TARGET_BMISS", | ||
4997 | [WMI_PSDISABLE_NODE_JOIN] "WMI_PSDISABLE_NODE_JOIN" | ||
4998 | }; | ||
4999 | |||
5000 | A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal); | ||
5001 | |||
5002 | /* One error is reported at a time, and errorval is a bitmask */ | ||
5003 | if(errorVal & (errorVal - 1)) | ||
5004 | return; | ||
5005 | |||
5006 | A_PRINTF("AR6000 Error type = "); | ||
5007 | switch(errorVal) | ||
5008 | { | ||
5009 | case WMI_TARGET_PM_ERR_FAIL: | ||
5010 | case WMI_TARGET_KEY_NOT_FOUND: | ||
5011 | case WMI_TARGET_DECRYPTION_ERR: | ||
5012 | case WMI_TARGET_BMISS: | ||
5013 | case WMI_PSDISABLE_NODE_JOIN: | ||
5014 | A_PRINTF("%s\n", errString[errorVal]); | ||
5015 | break; | ||
5016 | default: | ||
5017 | A_PRINTF("INVALID\n"); | ||
5018 | break; | ||
5019 | } | ||
5020 | |||
5021 | } | ||
5022 | |||
5023 | |||
5024 | void | ||
5025 | ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cacIndication, | ||
5026 | u8 statusCode, u8 *tspecSuggestion) | ||
5027 | { | ||
5028 | WMM_TSPEC_IE *tspecIe; | ||
5029 | |||
5030 | /* | ||
5031 | * This is the TSPEC IE suggestion from AP. | ||
5032 | * Suggestion provided by AP under some error | ||
5033 | * cases, could be helpful for the host app. | ||
5034 | * Check documentation. | ||
5035 | */ | ||
5036 | tspecIe = (WMM_TSPEC_IE *)tspecSuggestion; | ||
5037 | |||
5038 | /* | ||
5039 | * What do we do, if we get TSPEC rejection? One thought | ||
5040 | * that comes to mind is implictly delete the pstream... | ||
5041 | */ | ||
5042 | A_PRINTF("AR6000 CAC notification. " | ||
5043 | "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n", | ||
5044 | ac, cacIndication, statusCode); | ||
5045 | } | ||
5046 | |||
5047 | void | ||
5048 | ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel, | ||
5049 | u16 newChannel) | ||
5050 | { | ||
5051 | A_PRINTF("Channel Change notification\nOld Channel: %d, New Channel: %d\n", | ||
5052 | oldChannel, newChannel); | ||
5053 | } | ||
5054 | |||
5055 | #define AR6000_PRINT_BSSID(_pBss) do { \ | ||
5056 | A_PRINTF("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",\ | ||
5057 | (_pBss)[0],(_pBss)[1],(_pBss)[2],(_pBss)[3],\ | ||
5058 | (_pBss)[4],(_pBss)[5]); \ | ||
5059 | } while(0) | ||
5060 | |||
5061 | void | ||
5062 | ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl) | ||
5063 | { | ||
5064 | u8 i; | ||
5065 | |||
5066 | A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n", | ||
5067 | pTbl->numEntries, pTbl->roamMode); | ||
5068 | for (i= 0; i < pTbl->numEntries; i++) { | ||
5069 | A_PRINTF("[%d]bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", i, | ||
5070 | pTbl->bssRoamInfo[i].bssid[0], pTbl->bssRoamInfo[i].bssid[1], | ||
5071 | pTbl->bssRoamInfo[i].bssid[2], | ||
5072 | pTbl->bssRoamInfo[i].bssid[3], | ||
5073 | pTbl->bssRoamInfo[i].bssid[4], | ||
5074 | pTbl->bssRoamInfo[i].bssid[5]); | ||
5075 | A_PRINTF("RSSI %d RSSIDT %d LAST RSSI %d UTIL %d ROAM_UTIL %d" | ||
5076 | " BIAS %d\n", | ||
5077 | pTbl->bssRoamInfo[i].rssi, | ||
5078 | pTbl->bssRoamInfo[i].rssidt, | ||
5079 | pTbl->bssRoamInfo[i].last_rssi, | ||
5080 | pTbl->bssRoamInfo[i].util, | ||
5081 | pTbl->bssRoamInfo[i].roam_util, | ||
5082 | pTbl->bssRoamInfo[i].bias); | ||
5083 | } | ||
5084 | } | ||
5085 | |||
5086 | void | ||
5087 | ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply) | ||
5088 | { | ||
5089 | u8 i,j; | ||
5090 | |||
5091 | /*Each event now contains exactly one filter, see bug 26613*/ | ||
5092 | A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num, wow_reply->num_filters); | ||
5093 | A_PRINTF("wow mode = %s host mode = %s\n", | ||
5094 | (wow_reply->wow_mode == 0? "disabled":"enabled"), | ||
5095 | (wow_reply->host_mode == 1 ? "awake":"asleep")); | ||
5096 | |||
5097 | |||
5098 | /*If there are no patterns, the reply will only contain generic | ||
5099 | WoW information. Pattern information will exist only if there are | ||
5100 | patterns present. Bug 26716*/ | ||
5101 | |||
5102 | /* If this event contains pattern information, display it*/ | ||
5103 | if (wow_reply->this_filter_num) { | ||
5104 | i=0; | ||
5105 | A_PRINTF("id=%d size=%d offset=%d\n", | ||
5106 | wow_reply->wow_filters[i].wow_filter_id, | ||
5107 | wow_reply->wow_filters[i].wow_filter_size, | ||
5108 | wow_reply->wow_filters[i].wow_filter_offset); | ||
5109 | A_PRINTF("wow pattern = "); | ||
5110 | for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { | ||
5111 | A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_pattern[j]); | ||
5112 | } | ||
5113 | |||
5114 | A_PRINTF("\nwow mask = "); | ||
5115 | for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { | ||
5116 | A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_mask[j]); | ||
5117 | } | ||
5118 | A_PRINTF("\n"); | ||
5119 | } | ||
5120 | } | ||
5121 | |||
5122 | /* | ||
5123 | * Report the Roaming related data collected on the target | ||
5124 | */ | ||
5125 | void | ||
5126 | ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p) | ||
5127 | { | ||
5128 | A_PRINTF("Disconnect Data : BSSID: "); | ||
5129 | AR6000_PRINT_BSSID(p->disassoc_bssid); | ||
5130 | A_PRINTF(" RSSI %d DISASSOC Time %d NO_TXRX_TIME %d\n", | ||
5131 | p->disassoc_bss_rssi,p->disassoc_time, | ||
5132 | p->no_txrx_time); | ||
5133 | A_PRINTF("Connect Data: BSSID: "); | ||
5134 | AR6000_PRINT_BSSID(p->assoc_bssid); | ||
5135 | A_PRINTF(" RSSI %d ASSOC Time %d TXRX_TIME %d\n", | ||
5136 | p->assoc_bss_rssi,p->assoc_time, | ||
5137 | p->allow_txrx_time); | ||
5138 | } | ||
5139 | |||
5140 | void | ||
5141 | ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p) | ||
5142 | { | ||
5143 | switch (p->roamDataType) { | ||
5144 | case ROAM_DATA_TIME: | ||
5145 | ar6000_display_roam_time(&p->u.roamTime); | ||
5146 | break; | ||
5147 | default: | ||
5148 | break; | ||
5149 | } | ||
5150 | } | ||
5151 | |||
5152 | void | ||
5153 | ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *datap, int len) | ||
5154 | { | ||
5155 | struct sk_buff *skb; | ||
5156 | WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap; | ||
5157 | |||
5158 | |||
5159 | if (!ar->arMgmtFilter) { | ||
5160 | return; | ||
5161 | } | ||
5162 | if (((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_BEACON) && | ||
5163 | (bih->frameType != BEACON_FTYPE)) || | ||
5164 | ((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_PROBE_RESP) && | ||
5165 | (bih->frameType != PROBERESP_FTYPE))) | ||
5166 | { | ||
5167 | return; | ||
5168 | } | ||
5169 | |||
5170 | if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) { | ||
5171 | |||
5172 | A_NETBUF_PUT(skb, len); | ||
5173 | memcpy(A_NETBUF_DATA(skb), datap, len); | ||
5174 | skb->dev = ar->arNetDev; | ||
5175 | memcpy(skb_mac_header(skb), A_NETBUF_DATA(skb), 6); | ||
5176 | skb->ip_summed = CHECKSUM_NONE; | ||
5177 | skb->pkt_type = PACKET_OTHERHOST; | ||
5178 | skb->protocol = __constant_htons(0x0019); | ||
5179 | netif_rx(skb); | ||
5180 | } | ||
5181 | } | ||
5182 | |||
5183 | u32 wmiSendCmdNum; | ||
5184 | |||
5185 | int | ||
5186 | ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid) | ||
5187 | { | ||
5188 | struct ar6_softc *ar = (struct ar6_softc *)devt; | ||
5189 | int status = 0; | ||
5190 | struct ar_cookie *cookie = NULL; | ||
5191 | int i; | ||
5192 | #ifdef CONFIG_PM | ||
5193 | if (ar->arWowState != WLAN_WOW_STATE_NONE) { | ||
5194 | A_NETBUF_FREE(osbuf); | ||
5195 | return A_EACCES; | ||
5196 | } | ||
5197 | #endif /* CONFIG_PM */ | ||
5198 | /* take lock to protect ar6000_alloc_cookie() */ | ||
5199 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
5200 | |||
5201 | do { | ||
5202 | |||
5203 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar_contrstatus = ol_tx: skb=0x%lx, len=0x%x eid =%d\n", | ||
5204 | (unsigned long)osbuf, A_NETBUF_LEN(osbuf), eid)); | ||
5205 | |||
5206 | if (ar->arWMIControlEpFull && (eid == ar->arControlEp)) { | ||
5207 | /* control endpoint is full, don't allocate resources, we | ||
5208 | * are just going to drop this packet */ | ||
5209 | cookie = NULL; | ||
5210 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" WMI Control EP full, dropping packet : 0x%lX, len:%d \n", | ||
5211 | (unsigned long)osbuf, A_NETBUF_LEN(osbuf))); | ||
5212 | } else { | ||
5213 | cookie = ar6000_alloc_cookie(ar); | ||
5214 | } | ||
5215 | |||
5216 | if (cookie == NULL) { | ||
5217 | status = A_NO_MEMORY; | ||
5218 | break; | ||
5219 | } | ||
5220 | |||
5221 | if(logWmiRawMsgs) { | ||
5222 | A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum); | ||
5223 | for(i = 0; i < a_netbuf_to_len(osbuf); i++) | ||
5224 | A_PRINTF("%x ", ((u8 *)a_netbuf_to_data(osbuf))[i]); | ||
5225 | A_PRINTF("\n"); | ||
5226 | } | ||
5227 | |||
5228 | wmiSendCmdNum++; | ||
5229 | |||
5230 | } while (false); | ||
5231 | |||
5232 | if (cookie != NULL) { | ||
5233 | /* got a structure to send it out on */ | ||
5234 | ar->arTxPending[eid]++; | ||
5235 | |||
5236 | if (eid != ar->arControlEp) { | ||
5237 | ar->arTotalTxDataPending++; | ||
5238 | } | ||
5239 | } | ||
5240 | |||
5241 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
5242 | |||
5243 | if (cookie != NULL) { | ||
5244 | cookie->arc_bp[0] = (unsigned long)osbuf; | ||
5245 | cookie->arc_bp[1] = 0; | ||
5246 | SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, | ||
5247 | cookie, | ||
5248 | A_NETBUF_DATA(osbuf), | ||
5249 | A_NETBUF_LEN(osbuf), | ||
5250 | eid, | ||
5251 | AR6K_CONTROL_PKT_TAG); | ||
5252 | /* this interface is asynchronous, if there is an error, cleanup will happen in the | ||
5253 | * TX completion callback */ | ||
5254 | HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); | ||
5255 | status = 0; | ||
5256 | } | ||
5257 | |||
5258 | if (status) { | ||
5259 | A_NETBUF_FREE(osbuf); | ||
5260 | } | ||
5261 | return status; | ||
5262 | } | ||
5263 | |||
5264 | /* indicate tx activity or inactivity on a WMI stream */ | ||
5265 | void ar6000_indicate_tx_activity(void *devt, u8 TrafficClass, bool Active) | ||
5266 | { | ||
5267 | struct ar6_softc *ar = (struct ar6_softc *)devt; | ||
5268 | HTC_ENDPOINT_ID eid ; | ||
5269 | int i; | ||
5270 | |||
5271 | if (ar->arWmiEnabled) { | ||
5272 | eid = arAc2EndpointID(ar, TrafficClass); | ||
5273 | |||
5274 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
5275 | |||
5276 | ar->arAcStreamActive[TrafficClass] = Active; | ||
5277 | |||
5278 | if (Active) { | ||
5279 | /* when a stream goes active, keep track of the active stream with the highest priority */ | ||
5280 | |||
5281 | if (ar->arAcStreamPriMap[TrafficClass] > ar->arHiAcStreamActivePri) { | ||
5282 | /* set the new highest active priority */ | ||
5283 | ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[TrafficClass]; | ||
5284 | } | ||
5285 | |||
5286 | } else { | ||
5287 | /* when a stream goes inactive, we may have to search for the next active stream | ||
5288 | * that is the highest priority */ | ||
5289 | |||
5290 | if (ar->arHiAcStreamActivePri == ar->arAcStreamPriMap[TrafficClass]) { | ||
5291 | |||
5292 | /* the highest priority stream just went inactive */ | ||
5293 | |||
5294 | /* reset and search for the "next" highest "active" priority stream */ | ||
5295 | ar->arHiAcStreamActivePri = 0; | ||
5296 | for (i = 0; i < WMM_NUM_AC; i++) { | ||
5297 | if (ar->arAcStreamActive[i]) { | ||
5298 | if (ar->arAcStreamPriMap[i] > ar->arHiAcStreamActivePri) { | ||
5299 | /* set the new highest active priority */ | ||
5300 | ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[i]; | ||
5301 | } | ||
5302 | } | ||
5303 | } | ||
5304 | } | ||
5305 | } | ||
5306 | |||
5307 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
5308 | |||
5309 | } else { | ||
5310 | /* for mbox ping testing, the traffic class is mapped directly as a stream ID, | ||
5311 | * see handling of AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE in ioctl.c | ||
5312 | * convert the stream ID to a endpoint */ | ||
5313 | eid = arAc2EndpointID(ar, TrafficClass); | ||
5314 | } | ||
5315 | |||
5316 | /* notify HTC, this may cause credit distribution changes */ | ||
5317 | |||
5318 | HTCIndicateActivityChange(ar->arHtcTarget, | ||
5319 | eid, | ||
5320 | Active); | ||
5321 | |||
5322 | } | ||
5323 | |||
5324 | void | ||
5325 | ar6000_btcoex_config_event(struct ar6_softc *ar, u8 *ptr, u32 len) | ||
5326 | { | ||
5327 | |||
5328 | WMI_BTCOEX_CONFIG_EVENT *pBtcoexConfig = (WMI_BTCOEX_CONFIG_EVENT *)ptr; | ||
5329 | WMI_BTCOEX_CONFIG_EVENT *pArbtcoexConfig =&ar->arBtcoexConfig; | ||
5330 | |||
5331 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n")); | ||
5332 | |||
5333 | A_PRINTF("received config event\n"); | ||
5334 | pArbtcoexConfig->btProfileType = pBtcoexConfig->btProfileType; | ||
5335 | pArbtcoexConfig->linkId = pBtcoexConfig->linkId; | ||
5336 | |||
5337 | switch (pBtcoexConfig->btProfileType) { | ||
5338 | case WMI_BTCOEX_BT_PROFILE_SCO: | ||
5339 | memcpy(&pArbtcoexConfig->info.scoConfigCmd, &pBtcoexConfig->info.scoConfigCmd, | ||
5340 | sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD)); | ||
5341 | break; | ||
5342 | case WMI_BTCOEX_BT_PROFILE_A2DP: | ||
5343 | memcpy(&pArbtcoexConfig->info.a2dpConfigCmd, &pBtcoexConfig->info.a2dpConfigCmd, | ||
5344 | sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD)); | ||
5345 | break; | ||
5346 | case WMI_BTCOEX_BT_PROFILE_ACLCOEX: | ||
5347 | memcpy(&pArbtcoexConfig->info.aclcoexConfig, &pBtcoexConfig->info.aclcoexConfig, | ||
5348 | sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); | ||
5349 | break; | ||
5350 | case WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE: | ||
5351 | memcpy(&pArbtcoexConfig->info.btinquiryPageConfigCmd, &pBtcoexConfig->info.btinquiryPageConfigCmd, | ||
5352 | sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); | ||
5353 | break; | ||
5354 | } | ||
5355 | if (ar->statsUpdatePending) { | ||
5356 | ar->statsUpdatePending = false; | ||
5357 | wake_up(&arEvent); | ||
5358 | } | ||
5359 | } | ||
5360 | |||
5361 | void | ||
5362 | ar6000_btcoex_stats_event(struct ar6_softc *ar, u8 *ptr, u32 len) | ||
5363 | { | ||
5364 | WMI_BTCOEX_STATS_EVENT *pBtcoexStats = (WMI_BTCOEX_STATS_EVENT *)ptr; | ||
5365 | |||
5366 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n")); | ||
5367 | |||
5368 | memcpy(&ar->arBtcoexStats, pBtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT)); | ||
5369 | |||
5370 | if (ar->statsUpdatePending) { | ||
5371 | ar->statsUpdatePending = false; | ||
5372 | wake_up(&arEvent); | ||
5373 | } | ||
5374 | |||
5375 | } | ||
5376 | module_init(ar6000_init_module); | ||
5377 | module_exit(ar6000_cleanup_module); | ||
5378 | |||
5379 | /* Init cookie queue */ | ||
5380 | static void | ||
5381 | ar6000_cookie_init(struct ar6_softc *ar) | ||
5382 | { | ||
5383 | u32 i; | ||
5384 | |||
5385 | ar->arCookieList = NULL; | ||
5386 | ar->arCookieCount = 0; | ||
5387 | |||
5388 | A_MEMZERO(s_ar_cookie_mem, sizeof(s_ar_cookie_mem)); | ||
5389 | |||
5390 | for (i = 0; i < MAX_COOKIE_NUM; i++) { | ||
5391 | ar6000_free_cookie(ar, &s_ar_cookie_mem[i]); | ||
5392 | } | ||
5393 | } | ||
5394 | |||
5395 | /* cleanup cookie queue */ | ||
5396 | static void | ||
5397 | ar6000_cookie_cleanup(struct ar6_softc *ar) | ||
5398 | { | ||
5399 | /* It is gone .... */ | ||
5400 | ar->arCookieList = NULL; | ||
5401 | ar->arCookieCount = 0; | ||
5402 | } | ||
5403 | |||
5404 | /* Init cookie queue */ | ||
5405 | static void | ||
5406 | ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie) | ||
5407 | { | ||
5408 | /* Insert first */ | ||
5409 | A_ASSERT(ar != NULL); | ||
5410 | A_ASSERT(cookie != NULL); | ||
5411 | |||
5412 | cookie->arc_list_next = ar->arCookieList; | ||
5413 | ar->arCookieList = cookie; | ||
5414 | ar->arCookieCount++; | ||
5415 | } | ||
5416 | |||
5417 | /* cleanup cookie queue */ | ||
5418 | static struct ar_cookie * | ||
5419 | ar6000_alloc_cookie(struct ar6_softc *ar) | ||
5420 | { | ||
5421 | struct ar_cookie *cookie; | ||
5422 | |||
5423 | cookie = ar->arCookieList; | ||
5424 | if(cookie != NULL) | ||
5425 | { | ||
5426 | ar->arCookieList = cookie->arc_list_next; | ||
5427 | ar->arCookieCount--; | ||
5428 | } | ||
5429 | |||
5430 | return cookie; | ||
5431 | } | ||
5432 | |||
5433 | void | ||
5434 | ar6000_tx_retry_err_event(void *devt) | ||
5435 | { | ||
5436 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Tx retries reach maximum!\n")); | ||
5437 | } | ||
5438 | |||
5439 | void | ||
5440 | ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, u8 snr) | ||
5441 | { | ||
5442 | WMI_SNR_THRESHOLD_EVENT event; | ||
5443 | |||
5444 | event.range = newThreshold; | ||
5445 | event.snr = snr; | ||
5446 | } | ||
5447 | |||
5448 | void | ||
5449 | ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, u8 lq) | ||
5450 | { | ||
5451 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("lq threshold range %d, lq %d\n", newThreshold, lq)); | ||
5452 | } | ||
5453 | |||
5454 | |||
5455 | |||
5456 | u32 a_copy_to_user(void *to, const void *from, u32 n) | ||
5457 | { | ||
5458 | return(copy_to_user(to, from, n)); | ||
5459 | } | ||
5460 | |||
5461 | u32 a_copy_from_user(void *to, const void *from, u32 n) | ||
5462 | { | ||
5463 | return(copy_from_user(to, from, n)); | ||
5464 | } | ||
5465 | |||
5466 | |||
5467 | int | ||
5468 | ar6000_get_driver_cfg(struct net_device *dev, | ||
5469 | u16 cfgParam, | ||
5470 | void *result) | ||
5471 | { | ||
5472 | |||
5473 | int ret = 0; | ||
5474 | |||
5475 | switch(cfgParam) | ||
5476 | { | ||
5477 | case AR6000_DRIVER_CFG_GET_WLANNODECACHING: | ||
5478 | *((u32 *)result) = wlanNodeCaching; | ||
5479 | break; | ||
5480 | case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS: | ||
5481 | *((u32 *)result) = logWmiRawMsgs; | ||
5482 | break; | ||
5483 | default: | ||
5484 | ret = EINVAL; | ||
5485 | break; | ||
5486 | } | ||
5487 | |||
5488 | return ret; | ||
5489 | } | ||
5490 | |||
5491 | void | ||
5492 | ar6000_keepalive_rx(void *devt, u8 configured) | ||
5493 | { | ||
5494 | struct ar6_softc *ar = (struct ar6_softc *)devt; | ||
5495 | |||
5496 | ar->arKeepaliveConfigured = configured; | ||
5497 | wake_up(&arEvent); | ||
5498 | } | ||
5499 | |||
5500 | void | ||
5501 | ar6000_pmkid_list_event(void *devt, u8 numPMKID, WMI_PMKID *pmkidList, | ||
5502 | u8 *bssidList) | ||
5503 | { | ||
5504 | u8 i, j; | ||
5505 | |||
5506 | A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID); | ||
5507 | |||
5508 | for (i = 0; i < numPMKID; i++) { | ||
5509 | A_PRINTF("\nBSSID %d ", i); | ||
5510 | for (j = 0; j < ATH_MAC_LEN; j++) { | ||
5511 | A_PRINTF("%2.2x", bssidList[j]); | ||
5512 | } | ||
5513 | bssidList += (ATH_MAC_LEN + WMI_PMKID_LEN); | ||
5514 | A_PRINTF("\nPMKID %d ", i); | ||
5515 | for (j = 0; j < WMI_PMKID_LEN; j++) { | ||
5516 | A_PRINTF("%2.2x", pmkidList->pmkid[j]); | ||
5517 | } | ||
5518 | pmkidList = (WMI_PMKID *)((u8 *)pmkidList + ATH_MAC_LEN + | ||
5519 | WMI_PMKID_LEN); | ||
5520 | } | ||
5521 | } | ||
5522 | |||
5523 | void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid) | ||
5524 | { | ||
5525 | sta_t *conn=NULL; | ||
5526 | bool isPsqEmpty = false; | ||
5527 | |||
5528 | conn = ieee80211_find_conn_for_aid(ar, aid); | ||
5529 | |||
5530 | /* If the PS q for this STA is not empty, dequeue and send a pkt from | ||
5531 | * the head of the q. Also update the More data bit in the WMI_DATA_HDR | ||
5532 | * if there are more pkts for this STA in the PS q. If there are no more | ||
5533 | * pkts for this STA, update the PVB for this STA. | ||
5534 | */ | ||
5535 | A_MUTEX_LOCK(&conn->psqLock); | ||
5536 | isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); | ||
5537 | A_MUTEX_UNLOCK(&conn->psqLock); | ||
5538 | |||
5539 | if (isPsqEmpty) { | ||
5540 | /* TODO:No buffered pkts for this STA. Send out a NULL data frame */ | ||
5541 | } else { | ||
5542 | struct sk_buff *skb = NULL; | ||
5543 | |||
5544 | A_MUTEX_LOCK(&conn->psqLock); | ||
5545 | skb = A_NETBUF_DEQUEUE(&conn->psq); | ||
5546 | A_MUTEX_UNLOCK(&conn->psqLock); | ||
5547 | /* Set the STA flag to PSPolled, so that the frame will go out */ | ||
5548 | STA_SET_PS_POLLED(conn); | ||
5549 | ar6000_data_tx(skb, ar->arNetDev); | ||
5550 | STA_CLR_PS_POLLED(conn); | ||
5551 | |||
5552 | /* Clear the PVB for this STA if the queue has become empty */ | ||
5553 | A_MUTEX_LOCK(&conn->psqLock); | ||
5554 | isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); | ||
5555 | A_MUTEX_UNLOCK(&conn->psqLock); | ||
5556 | |||
5557 | if (isPsqEmpty) { | ||
5558 | wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0); | ||
5559 | } | ||
5560 | } | ||
5561 | } | ||
5562 | |||
5563 | void ar6000_dtimexpiry_event(struct ar6_softc *ar) | ||
5564 | { | ||
5565 | bool isMcastQueued = false; | ||
5566 | struct sk_buff *skb = NULL; | ||
5567 | |||
5568 | /* If there are no associated STAs, ignore the DTIM expiry event. | ||
5569 | * There can be potential race conditions where the last associated | ||
5570 | * STA may disconnect & before the host could clear the 'Indicate DTIM' | ||
5571 | * request to the firmware, the firmware would have just indicated a DTIM | ||
5572 | * expiry event. The race is between 'clear DTIM expiry cmd' going | ||
5573 | * from the host to the firmware & the DTIM expiry event happening from | ||
5574 | * the firmware to the host. | ||
5575 | */ | ||
5576 | if (ar->sta_list_index == 0) { | ||
5577 | return; | ||
5578 | } | ||
5579 | |||
5580 | A_MUTEX_LOCK(&ar->mcastpsqLock); | ||
5581 | isMcastQueued = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq); | ||
5582 | A_MUTEX_UNLOCK(&ar->mcastpsqLock); | ||
5583 | |||
5584 | A_ASSERT(isMcastQueued == false); | ||
5585 | |||
5586 | /* Flush the mcast psq to the target */ | ||
5587 | /* Set the STA flag to DTIMExpired, so that the frame will go out */ | ||
5588 | ar->DTIMExpired = true; | ||
5589 | |||
5590 | A_MUTEX_LOCK(&ar->mcastpsqLock); | ||
5591 | while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { | ||
5592 | skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); | ||
5593 | A_MUTEX_UNLOCK(&ar->mcastpsqLock); | ||
5594 | |||
5595 | ar6000_data_tx(skb, ar->arNetDev); | ||
5596 | |||
5597 | A_MUTEX_LOCK(&ar->mcastpsqLock); | ||
5598 | } | ||
5599 | A_MUTEX_UNLOCK(&ar->mcastpsqLock); | ||
5600 | |||
5601 | /* Reset the DTIMExpired flag back to 0 */ | ||
5602 | ar->DTIMExpired = false; | ||
5603 | |||
5604 | /* Clear the LSB of the BitMapCtl field of the TIM IE */ | ||
5605 | wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0); | ||
5606 | } | ||
5607 | |||
5608 | void | ||
5609 | read_rssi_compensation_param(struct ar6_softc *ar) | ||
5610 | { | ||
5611 | u8 *cust_data_ptr; | ||
5612 | |||
5613 | //#define RSSICOMPENSATION_PRINT | ||
5614 | |||
5615 | #ifdef RSSICOMPENSATION_PRINT | ||
5616 | s16 i; | ||
5617 | cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType); | ||
5618 | for (i=0; i<16; i++) { | ||
5619 | A_PRINTF("cust_data_%d = %x \n", i, *(u8 *)cust_data_ptr); | ||
5620 | cust_data_ptr += 1; | ||
5621 | } | ||
5622 | #endif | ||
5623 | |||
5624 | cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType); | ||
5625 | |||
5626 | rssi_compensation_param.customerID = *(u16 *)cust_data_ptr & 0xffff; | ||
5627 | rssi_compensation_param.enable = *(u16 *)(cust_data_ptr+2) & 0xffff; | ||
5628 | rssi_compensation_param.bg_param_a = *(u16 *)(cust_data_ptr+4) & 0xffff; | ||
5629 | rssi_compensation_param.bg_param_b = *(u16 *)(cust_data_ptr+6) & 0xffff; | ||
5630 | rssi_compensation_param.a_param_a = *(u16 *)(cust_data_ptr+8) & 0xffff; | ||
5631 | rssi_compensation_param.a_param_b = *(u16 *)(cust_data_ptr+10) &0xffff; | ||
5632 | rssi_compensation_param.reserved = *(u32 *)(cust_data_ptr+12); | ||
5633 | |||
5634 | #ifdef RSSICOMPENSATION_PRINT | ||
5635 | A_PRINTF("customerID = 0x%x \n", rssi_compensation_param.customerID); | ||
5636 | A_PRINTF("enable = 0x%x \n", rssi_compensation_param.enable); | ||
5637 | A_PRINTF("bg_param_a = 0x%x and %d \n", rssi_compensation_param.bg_param_a, rssi_compensation_param.bg_param_a); | ||
5638 | A_PRINTF("bg_param_b = 0x%x and %d \n", rssi_compensation_param.bg_param_b, rssi_compensation_param.bg_param_b); | ||
5639 | A_PRINTF("a_param_a = 0x%x and %d \n", rssi_compensation_param.a_param_a, rssi_compensation_param.a_param_a); | ||
5640 | A_PRINTF("a_param_b = 0x%x and %d \n", rssi_compensation_param.a_param_b, rssi_compensation_param.a_param_b); | ||
5641 | A_PRINTF("Last 4 bytes = 0x%x \n", rssi_compensation_param.reserved); | ||
5642 | #endif | ||
5643 | |||
5644 | if (rssi_compensation_param.enable != 0x1) { | ||
5645 | rssi_compensation_param.enable = 0; | ||
5646 | } | ||
5647 | |||
5648 | return; | ||
5649 | } | ||
5650 | |||
5651 | s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt) | ||
5652 | { | ||
5653 | |||
5654 | if (freq > 5000) | ||
5655 | { | ||
5656 | if (rssi_compensation_param.enable) | ||
5657 | { | ||
5658 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); | ||
5659 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, totalPkt = %d\n", rssi,totalPkt)); | ||
5660 | rssi = rssi * rssi_compensation_param.a_param_a + totalPkt * rssi_compensation_param.a_param_b; | ||
5661 | rssi = (rssi-50) /100; | ||
5662 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); | ||
5663 | } | ||
5664 | } | ||
5665 | else | ||
5666 | { | ||
5667 | if (rssi_compensation_param.enable) | ||
5668 | { | ||
5669 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); | ||
5670 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, totalPkt = %d\n", rssi,totalPkt)); | ||
5671 | rssi = rssi * rssi_compensation_param.bg_param_a + totalPkt * rssi_compensation_param.bg_param_b; | ||
5672 | rssi = (rssi-50) /100; | ||
5673 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); | ||
5674 | } | ||
5675 | } | ||
5676 | |||
5677 | return rssi; | ||
5678 | } | ||
5679 | |||
5680 | s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi) | ||
5681 | { | ||
5682 | if (ar->arBssChannel > 5000) | ||
5683 | { | ||
5684 | if (rssi_compensation_param.enable) | ||
5685 | { | ||
5686 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); | ||
5687 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n", rssi)); | ||
5688 | rssi = rssi * rssi_compensation_param.a_param_a + rssi_compensation_param.a_param_b; | ||
5689 | rssi = (rssi-50) /100; | ||
5690 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); | ||
5691 | } | ||
5692 | } | ||
5693 | else | ||
5694 | { | ||
5695 | if (rssi_compensation_param.enable) | ||
5696 | { | ||
5697 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); | ||
5698 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n", rssi)); | ||
5699 | rssi = rssi * rssi_compensation_param.bg_param_a + rssi_compensation_param.bg_param_b; | ||
5700 | rssi = (rssi-50) /100; | ||
5701 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", rssi)); | ||
5702 | } | ||
5703 | } | ||
5704 | |||
5705 | return rssi; | ||
5706 | } | ||
5707 | |||
5708 | s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above) | ||
5709 | { | ||
5710 | s16 i; | ||
5711 | |||
5712 | if (ar->arBssChannel > 5000) | ||
5713 | { | ||
5714 | if (rssi_compensation_param.enable) | ||
5715 | { | ||
5716 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); | ||
5717 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d\n", rssi)); | ||
5718 | rssi = rssi * 100; | ||
5719 | rssi = (rssi - rssi_compensation_param.a_param_b) / rssi_compensation_param.a_param_a; | ||
5720 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n", rssi)); | ||
5721 | } | ||
5722 | } | ||
5723 | else | ||
5724 | { | ||
5725 | if (rssi_compensation_param.enable) | ||
5726 | { | ||
5727 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); | ||
5728 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d\n", rssi)); | ||
5729 | |||
5730 | if (Above) { | ||
5731 | for (i=95; i>=0; i--) { | ||
5732 | if (rssi <= rssi_compensation_table[i]) { | ||
5733 | rssi = 0 - i; | ||
5734 | break; | ||
5735 | } | ||
5736 | } | ||
5737 | } else { | ||
5738 | for (i=0; i<=95; i++) { | ||
5739 | if (rssi >= rssi_compensation_table[i]) { | ||
5740 | rssi = 0 - i; | ||
5741 | break; | ||
5742 | } | ||
5743 | } | ||
5744 | } | ||
5745 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n", rssi)); | ||
5746 | } | ||
5747 | } | ||
5748 | |||
5749 | return rssi; | ||
5750 | } | ||
5751 | |||
5752 | #ifdef WAPI_ENABLE | ||
5753 | void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac) | ||
5754 | { | ||
5755 | union iwreq_data wrqu; | ||
5756 | char buf[20]; | ||
5757 | |||
5758 | A_MEMZERO(buf, sizeof(buf)); | ||
5759 | |||
5760 | strcpy(buf, "WAPI_REKEY"); | ||
5761 | buf[10] = type; | ||
5762 | memcpy(&buf[11], mac, ATH_MAC_LEN); | ||
5763 | |||
5764 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
5765 | wrqu.data.length = 10+1+ATH_MAC_LEN; | ||
5766 | wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); | ||
5767 | |||
5768 | A_PRINTF("WAPI REKEY - %d - %02x:%02x\n", type, mac[4], mac[5]); | ||
5769 | } | ||
5770 | #endif | ||
5771 | |||
5772 | static int | ||
5773 | ar6000_reinstall_keys(struct ar6_softc *ar, u8 key_op_ctrl) | ||
5774 | { | ||
5775 | int status = 0; | ||
5776 | struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik; | ||
5777 | struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik; | ||
5778 | CRYPTO_TYPE keyType = ar->user_saved_keys.keyType; | ||
5779 | |||
5780 | if (IEEE80211_CIPHER_CCKM_KRK != uik->ik_type) { | ||
5781 | if (NONE_CRYPT == keyType) { | ||
5782 | goto _reinstall_keys_out; | ||
5783 | } | ||
5784 | |||
5785 | if (uik->ik_keylen) { | ||
5786 | status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix, | ||
5787 | ar->user_saved_keys.keyType, PAIRWISE_USAGE, | ||
5788 | uik->ik_keylen, (u8 *)&uik->ik_keyrsc, | ||
5789 | uik->ik_keydata, key_op_ctrl, uik->ik_macaddr, SYNC_BEFORE_WMIFLAG); | ||
5790 | } | ||
5791 | |||
5792 | } else { | ||
5793 | status = wmi_add_krk_cmd(ar->arWmi, uik->ik_keydata); | ||
5794 | } | ||
5795 | |||
5796 | if (IEEE80211_CIPHER_CCKM_KRK != bik->ik_type) { | ||
5797 | if (NONE_CRYPT == keyType) { | ||
5798 | goto _reinstall_keys_out; | ||
5799 | } | ||
5800 | |||
5801 | if (bik->ik_keylen) { | ||
5802 | status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix, | ||
5803 | ar->user_saved_keys.keyType, GROUP_USAGE, | ||
5804 | bik->ik_keylen, (u8 *)&bik->ik_keyrsc, | ||
5805 | bik->ik_keydata, key_op_ctrl, bik->ik_macaddr, NO_SYNC_WMIFLAG); | ||
5806 | } | ||
5807 | } else { | ||
5808 | status = wmi_add_krk_cmd(ar->arWmi, bik->ik_keydata); | ||
5809 | } | ||
5810 | |||
5811 | _reinstall_keys_out: | ||
5812 | ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; | ||
5813 | ar->user_key_ctrl = 0; | ||
5814 | |||
5815 | return status; | ||
5816 | } | ||
5817 | |||
5818 | |||
5819 | void | ||
5820 | ar6000_dset_open_req( | ||
5821 | void *context, | ||
5822 | u32 id, | ||
5823 | u32 targHandle, | ||
5824 | u32 targReplyFn, | ||
5825 | u32 targReplyArg) | ||
5826 | { | ||
5827 | } | ||
5828 | |||
5829 | void | ||
5830 | ar6000_dset_close( | ||
5831 | void *context, | ||
5832 | u32 access_cookie) | ||
5833 | { | ||
5834 | return; | ||
5835 | } | ||
5836 | |||
5837 | void | ||
5838 | ar6000_dset_data_req( | ||
5839 | void *context, | ||
5840 | u32 accessCookie, | ||
5841 | u32 offset, | ||
5842 | u32 length, | ||
5843 | u32 targBuf, | ||
5844 | u32 targReplyFn, | ||
5845 | u32 targReplyArg) | ||
5846 | { | ||
5847 | } | ||
5848 | |||
5849 | int | ||
5850 | ar6000_ap_mode_profile_commit(struct ar6_softc *ar) | ||
5851 | { | ||
5852 | WMI_CONNECT_CMD p; | ||
5853 | unsigned long flags; | ||
5854 | |||
5855 | /* No change in AP's profile configuration */ | ||
5856 | if(ar->ap_profile_flag==0) { | ||
5857 | A_PRINTF("COMMIT: No change in profile!!!\n"); | ||
5858 | return -ENODATA; | ||
5859 | } | ||
5860 | |||
5861 | if(!ar->arSsidLen) { | ||
5862 | A_PRINTF("SSID not set!!!\n"); | ||
5863 | return -ECHRNG; | ||
5864 | } | ||
5865 | |||
5866 | switch(ar->arAuthMode) { | ||
5867 | case NONE_AUTH: | ||
5868 | if((ar->arPairwiseCrypto != NONE_CRYPT) && | ||
5869 | #ifdef WAPI_ENABLE | ||
5870 | (ar->arPairwiseCrypto != WAPI_CRYPT) && | ||
5871 | #endif | ||
5872 | (ar->arPairwiseCrypto != WEP_CRYPT)) { | ||
5873 | A_PRINTF("Cipher not supported in AP mode Open auth\n"); | ||
5874 | return -EOPNOTSUPP; | ||
5875 | } | ||
5876 | break; | ||
5877 | case WPA_PSK_AUTH: | ||
5878 | case WPA2_PSK_AUTH: | ||
5879 | case (WPA_PSK_AUTH|WPA2_PSK_AUTH): | ||
5880 | break; | ||
5881 | default: | ||
5882 | A_PRINTF("This key mgmt type not supported in AP mode\n"); | ||
5883 | return -EOPNOTSUPP; | ||
5884 | } | ||
5885 | |||
5886 | /* Update the arNetworkType */ | ||
5887 | ar->arNetworkType = ar->arNextMode; | ||
5888 | |||
5889 | A_MEMZERO(&p,sizeof(p)); | ||
5890 | p.ssidLength = ar->arSsidLen; | ||
5891 | memcpy(p.ssid,ar->arSsid,p.ssidLength); | ||
5892 | p.channel = ar->arChannelHint; | ||
5893 | p.networkType = ar->arNetworkType; | ||
5894 | |||
5895 | p.dot11AuthMode = ar->arDot11AuthMode; | ||
5896 | p.authMode = ar->arAuthMode; | ||
5897 | p.pairwiseCryptoType = ar->arPairwiseCrypto; | ||
5898 | p.pairwiseCryptoLen = ar->arPairwiseCryptoLen; | ||
5899 | p.groupCryptoType = ar->arGroupCrypto; | ||
5900 | p.groupCryptoLen = ar->arGroupCryptoLen; | ||
5901 | p.ctrl_flags = ar->arConnectCtrlFlags; | ||
5902 | |||
5903 | wmi_ap_profile_commit(ar->arWmi, &p); | ||
5904 | spin_lock_irqsave(&ar->arLock, flags); | ||
5905 | ar->arConnected = true; | ||
5906 | netif_carrier_on(ar->arNetDev); | ||
5907 | spin_unlock_irqrestore(&ar->arLock, flags); | ||
5908 | ar->ap_profile_flag = 0; | ||
5909 | return 0; | ||
5910 | } | ||
5911 | |||
5912 | int | ||
5913 | ar6000_connect_to_ap(struct ar6_softc *ar) | ||
5914 | { | ||
5915 | /* The ssid length check prevents second "essid off" from the user, | ||
5916 | to be treated as a connect cmd. The second "essid off" is ignored. | ||
5917 | */ | ||
5918 | if((ar->arWmiReady == true) && (ar->arSsidLen > 0) && ar->arNetworkType!=AP_NETWORK) | ||
5919 | { | ||
5920 | int status; | ||
5921 | if((ADHOC_NETWORK != ar->arNetworkType) && | ||
5922 | (NONE_AUTH==ar->arAuthMode) && | ||
5923 | (WEP_CRYPT==ar->arPairwiseCrypto)) { | ||
5924 | ar6000_install_static_wep_keys(ar); | ||
5925 | } | ||
5926 | |||
5927 | if (!ar->arUserBssFilter) { | ||
5928 | if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) { | ||
5929 | return -EIO; | ||
5930 | } | ||
5931 | } | ||
5932 | #ifdef WAPI_ENABLE | ||
5933 | if (ar->arWapiEnable) { | ||
5934 | ar->arPairwiseCrypto = WAPI_CRYPT; | ||
5935 | ar->arPairwiseCryptoLen = 0; | ||
5936 | ar->arGroupCrypto = WAPI_CRYPT; | ||
5937 | ar->arGroupCryptoLen = 0; | ||
5938 | ar->arAuthMode = NONE_AUTH; | ||
5939 | ar->arConnectCtrlFlags |= CONNECT_IGNORE_WPAx_GROUP_CIPHER; | ||
5940 | } | ||
5941 | #endif | ||
5942 | AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Connect called with authmode %d dot11 auth %d"\ | ||
5943 | " PW crypto %d PW crypto Len %d GRP crypto %d"\ | ||
5944 | " GRP crypto Len %d\n", | ||
5945 | ar->arAuthMode, ar->arDot11AuthMode, | ||
5946 | ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, | ||
5947 | ar->arGroupCrypto, ar->arGroupCryptoLen)); | ||
5948 | reconnect_flag = 0; | ||
5949 | /* Set the listen interval into 1000TUs or more. This value will be indicated to Ap in the conn. | ||
5950 | later set it back locally at the STA to 100/1000 TUs depending on the power mode */ | ||
5951 | if ((ar->arNetworkType == INFRA_NETWORK)) { | ||
5952 | wmi_listeninterval_cmd(ar->arWmi, max(ar->arListenIntervalT, (u16)A_MAX_WOW_LISTEN_INTERVAL), 0); | ||
5953 | } | ||
5954 | status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, | ||
5955 | ar->arDot11AuthMode, ar->arAuthMode, | ||
5956 | ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, | ||
5957 | ar->arGroupCrypto,ar->arGroupCryptoLen, | ||
5958 | ar->arSsidLen, ar->arSsid, | ||
5959 | ar->arReqBssid, ar->arChannelHint, | ||
5960 | ar->arConnectCtrlFlags); | ||
5961 | if (status) { | ||
5962 | wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB); | ||
5963 | if (!ar->arUserBssFilter) { | ||
5964 | wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); | ||
5965 | } | ||
5966 | return status; | ||
5967 | } | ||
5968 | |||
5969 | if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) && | ||
5970 | ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode))) | ||
5971 | { | ||
5972 | A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0); | ||
5973 | } | ||
5974 | |||
5975 | ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD; | ||
5976 | |||
5977 | ar->arConnectPending = true; | ||
5978 | return status; | ||
5979 | } | ||
5980 | return A_ERROR; | ||
5981 | } | ||
5982 | |||
5983 | int | ||
5984 | ar6000_disconnect(struct ar6_softc *ar) | ||
5985 | { | ||
5986 | if ((ar->arConnected == true) || (ar->arConnectPending == true)) { | ||
5987 | wmi_disconnect_cmd(ar->arWmi); | ||
5988 | /* | ||
5989 | * Disconnect cmd is issued, clear connectPending. | ||
5990 | * arConnected will be cleard in disconnect_event notification. | ||
5991 | */ | ||
5992 | ar->arConnectPending = false; | ||
5993 | } | ||
5994 | |||
5995 | return 0; | ||
5996 | } | ||
5997 | |||
5998 | int | ||
5999 | ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie) | ||
6000 | { | ||
6001 | sta_t *conn = NULL; | ||
6002 | conn = ieee80211_find_conn(ar, wpaie->wpa_macaddr); | ||
6003 | |||
6004 | A_MEMZERO(wpaie->wpa_ie, IEEE80211_MAX_IE); | ||
6005 | A_MEMZERO(wpaie->rsn_ie, IEEE80211_MAX_IE); | ||
6006 | |||
6007 | if(conn) { | ||
6008 | memcpy(wpaie->wpa_ie, conn->wpa_ie, IEEE80211_MAX_IE); | ||
6009 | } | ||
6010 | |||
6011 | return 0; | ||
6012 | } | ||
6013 | |||
6014 | int | ||
6015 | is_iwioctl_allowed(u8 mode, u16 cmd) | ||
6016 | { | ||
6017 | if(cmd >= SIOCSIWCOMMIT && cmd <= SIOCGIWPOWER) { | ||
6018 | cmd -= SIOCSIWCOMMIT; | ||
6019 | if(sioctl_filter[cmd] == 0xFF) return 0; | ||
6020 | if(sioctl_filter[cmd] & mode) return 0; | ||
6021 | } else if(cmd >= SIOCIWFIRSTPRIV && cmd <= (SIOCIWFIRSTPRIV+30)) { | ||
6022 | cmd -= SIOCIWFIRSTPRIV; | ||
6023 | if(pioctl_filter[cmd] == 0xFF) return 0; | ||
6024 | if(pioctl_filter[cmd] & mode) return 0; | ||
6025 | } else { | ||
6026 | return A_ERROR; | ||
6027 | } | ||
6028 | return A_ENOTSUP; | ||
6029 | } | ||
6030 | |||
6031 | int | ||
6032 | is_xioctl_allowed(u8 mode, int cmd) | ||
6033 | { | ||
6034 | if(sizeof(xioctl_filter)-1 < cmd) { | ||
6035 | A_PRINTF("Filter for this cmd=%d not defined\n",cmd); | ||
6036 | return 0; | ||
6037 | } | ||
6038 | if(xioctl_filter[cmd] == 0xFF) return 0; | ||
6039 | if(xioctl_filter[cmd] & mode) return 0; | ||
6040 | return A_ERROR; | ||
6041 | } | ||
6042 | |||
6043 | #ifdef WAPI_ENABLE | ||
6044 | int | ||
6045 | ap_set_wapi_key(struct ar6_softc *ar, void *ikey) | ||
6046 | { | ||
6047 | struct ieee80211req_key *ik = (struct ieee80211req_key *)ikey; | ||
6048 | KEY_USAGE keyUsage = 0; | ||
6049 | int status; | ||
6050 | |||
6051 | if (memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN) == 0) { | ||
6052 | keyUsage = GROUP_USAGE; | ||
6053 | } else { | ||
6054 | keyUsage = PAIRWISE_USAGE; | ||
6055 | } | ||
6056 | A_PRINTF("WAPI_KEY: Type:%d ix:%d mac:%02x:%02x len:%d\n", | ||
6057 | keyUsage, ik->ik_keyix, ik->ik_macaddr[4], ik->ik_macaddr[5], | ||
6058 | ik->ik_keylen); | ||
6059 | |||
6060 | status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, WAPI_CRYPT, keyUsage, | ||
6061 | ik->ik_keylen, (u8 *)&ik->ik_keyrsc, | ||
6062 | ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr, | ||
6063 | SYNC_BOTH_WMIFLAG); | ||
6064 | |||
6065 | if (0 != status) { | ||
6066 | return -EIO; | ||
6067 | } | ||
6068 | return 0; | ||
6069 | } | ||
6070 | #endif | ||
6071 | |||
6072 | void ar6000_peer_event( | ||
6073 | void *context, | ||
6074 | u8 eventCode, | ||
6075 | u8 *macAddr) | ||
6076 | { | ||
6077 | u8 pos; | ||
6078 | |||
6079 | for (pos=0;pos<6;pos++) | ||
6080 | printk("%02x: ",*(macAddr+pos)); | ||
6081 | printk("\n"); | ||
6082 | } | ||
6083 | |||
6084 | #ifdef HTC_TEST_SEND_PKTS | ||
6085 | #define HTC_TEST_DUPLICATE 8 | ||
6086 | static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *dupskb) | ||
6087 | { | ||
6088 | struct ar_cookie *cookie; | ||
6089 | struct ar_cookie *cookieArray[HTC_TEST_DUPLICATE]; | ||
6090 | struct sk_buff *new_skb; | ||
6091 | int i; | ||
6092 | int pkts = 0; | ||
6093 | struct htc_packet_queue pktQueue; | ||
6094 | EPPING_HEADER *eppingHdr; | ||
6095 | |||
6096 | eppingHdr = A_NETBUF_DATA(dupskb); | ||
6097 | |||
6098 | if (eppingHdr->Cmd_h == EPPING_CMD_NO_ECHO) { | ||
6099 | /* skip test if this is already a tx perf test */ | ||
6100 | return; | ||
6101 | } | ||
6102 | |||
6103 | for (i = 0; i < HTC_TEST_DUPLICATE; i++,pkts++) { | ||
6104 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
6105 | cookie = ar6000_alloc_cookie(ar); | ||
6106 | if (cookie != NULL) { | ||
6107 | ar->arTxPending[eid]++; | ||
6108 | ar->arTotalTxDataPending++; | ||
6109 | } | ||
6110 | |||
6111 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
6112 | |||
6113 | if (NULL == cookie) { | ||
6114 | break; | ||
6115 | } | ||
6116 | |||
6117 | new_skb = A_NETBUF_ALLOC(A_NETBUF_LEN(dupskb)); | ||
6118 | |||
6119 | if (new_skb == NULL) { | ||
6120 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
6121 | ar6000_free_cookie(ar,cookie); | ||
6122 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
6123 | break; | ||
6124 | } | ||
6125 | |||
6126 | A_NETBUF_PUT_DATA(new_skb, A_NETBUF_DATA(dupskb), A_NETBUF_LEN(dupskb)); | ||
6127 | cookie->arc_bp[0] = (unsigned long)new_skb; | ||
6128 | cookie->arc_bp[1] = MapNo; | ||
6129 | SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, | ||
6130 | cookie, | ||
6131 | A_NETBUF_DATA(new_skb), | ||
6132 | A_NETBUF_LEN(new_skb), | ||
6133 | eid, | ||
6134 | AR6K_DATA_PKT_TAG); | ||
6135 | |||
6136 | cookieArray[i] = cookie; | ||
6137 | |||
6138 | { | ||
6139 | EPPING_HEADER *pHdr = (EPPING_HEADER *)A_NETBUF_DATA(new_skb); | ||
6140 | pHdr->Cmd_h = EPPING_CMD_NO_ECHO; /* do not echo the packet */ | ||
6141 | } | ||
6142 | } | ||
6143 | |||
6144 | if (pkts == 0) { | ||
6145 | return; | ||
6146 | } | ||
6147 | |||
6148 | INIT_HTC_PACKET_QUEUE(&pktQueue); | ||
6149 | |||
6150 | for (i = 0; i < pkts; i++) { | ||
6151 | HTC_PACKET_ENQUEUE(&pktQueue,&cookieArray[i]->HtcPkt); | ||
6152 | } | ||
6153 | |||
6154 | HTCSendPktsMultiple(ar->arHtcTarget, &pktQueue); | ||
6155 | |||
6156 | } | ||
6157 | #endif | ||
6158 | |||
6159 | #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT | ||
6160 | /* | ||
6161 | * Add support for adding and removing a virtual adapter for soft AP. | ||
6162 | * Some OS requires different adapters names for station and soft AP mode. | ||
6163 | * To support these requirement, create and destroy a netdevice instance | ||
6164 | * when the AP mode is operational. A full fledged support for virual device | ||
6165 | * is not implemented. Rather a virtual interface is created and is linked | ||
6166 | * with the existing physical device instance during the operation of the | ||
6167 | * AP mode. | ||
6168 | */ | ||
6169 | |||
6170 | int ar6000_start_ap_interface(struct ar6_softc *ar) | ||
6171 | { | ||
6172 | struct ar_virtual_interface *arApDev; | ||
6173 | |||
6174 | /* Change net_device to point to AP instance */ | ||
6175 | arApDev = (struct ar_virtual_interface *)ar->arApDev; | ||
6176 | ar->arNetDev = arApDev->arNetDev; | ||
6177 | |||
6178 | return 0; | ||
6179 | } | ||
6180 | |||
6181 | int ar6000_stop_ap_interface(struct ar6_softc *ar) | ||
6182 | { | ||
6183 | struct ar_virtual_interface *arApDev; | ||
6184 | |||
6185 | /* Change net_device to point to sta instance */ | ||
6186 | arApDev = (struct ar_virtual_interface *)ar->arApDev; | ||
6187 | if (arApDev) { | ||
6188 | ar->arNetDev = arApDev->arStaNetDev; | ||
6189 | } | ||
6190 | |||
6191 | return 0; | ||
6192 | } | ||
6193 | |||
6194 | |||
6195 | int ar6000_create_ap_interface(struct ar6_softc *ar, char *ap_ifname) | ||
6196 | { | ||
6197 | struct net_device *dev; | ||
6198 | struct ar_virtual_interface *arApDev; | ||
6199 | |||
6200 | dev = alloc_etherdev(sizeof(struct ar_virtual_interface)); | ||
6201 | if (dev == NULL) { | ||
6202 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: can't alloc etherdev\n")); | ||
6203 | return A_ERROR; | ||
6204 | } | ||
6205 | |||
6206 | ether_setup(dev); | ||
6207 | init_netdev(dev, ap_ifname); | ||
6208 | dev->priv_flags &= ~IFF_TX_SKB_SHARING; | ||
6209 | |||
6210 | if (register_netdev(dev)) { | ||
6211 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: register_netdev failed\n")); | ||
6212 | return A_ERROR; | ||
6213 | } | ||
6214 | |||
6215 | arApDev = netdev_priv(dev); | ||
6216 | arApDev->arDev = ar; | ||
6217 | arApDev->arNetDev = dev; | ||
6218 | arApDev->arStaNetDev = ar->arNetDev; | ||
6219 | |||
6220 | ar->arApDev = arApDev; | ||
6221 | arApNetDev = dev; | ||
6222 | |||
6223 | /* Copy the MAC address */ | ||
6224 | memcpy(dev->dev_addr, ar->arNetDev->dev_addr, AR6000_ETH_ADDR_LEN); | ||
6225 | |||
6226 | return 0; | ||
6227 | } | ||
6228 | |||
6229 | int ar6000_add_ap_interface(struct ar6_softc *ar, char *ap_ifname) | ||
6230 | { | ||
6231 | /* Interface already added, need not proceed further */ | ||
6232 | if (ar->arApDev != NULL) { | ||
6233 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_add_ap_interface: interface already present \n")); | ||
6234 | return 0; | ||
6235 | } | ||
6236 | |||
6237 | if (ar6000_create_ap_interface(ar, ap_ifname) != 0) { | ||
6238 | return A_ERROR; | ||
6239 | } | ||
6240 | |||
6241 | A_PRINTF("Add AP interface %s \n",ap_ifname); | ||
6242 | |||
6243 | return ar6000_start_ap_interface(ar); | ||
6244 | } | ||
6245 | |||
6246 | int ar6000_remove_ap_interface(struct ar6_softc *ar) | ||
6247 | { | ||
6248 | if (arApNetDev) { | ||
6249 | ar6000_stop_ap_interface(ar); | ||
6250 | |||
6251 | unregister_netdev(arApNetDev); | ||
6252 | free_netdev(apApNetDev); | ||
6253 | |||
6254 | A_PRINTF("Remove AP interface\n"); | ||
6255 | } | ||
6256 | ar->arApDev = NULL; | ||
6257 | arApNetDev = NULL; | ||
6258 | |||
6259 | |||
6260 | return 0; | ||
6261 | } | ||
6262 | #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ | ||
6263 | |||
6264 | |||
6265 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
6266 | EXPORT_SYMBOL(setupbtdev); | ||
6267 | #endif | ||
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_pm.c b/drivers/staging/ath6kl/os/linux/ar6000_pm.c new file mode 100644 index 00000000000..1e0ace8b6d1 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/ar6000_pm.c | |||
@@ -0,0 +1,626 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (c) 2004-2010 Atheros Communications Inc. | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * | ||
7 | // | ||
8 | // Permission to use, copy, modify, and/or distribute this software for any | ||
9 | // purpose with or without fee is hereby granted, provided that the above | ||
10 | // copyright notice and this permission notice appear in all copies. | ||
11 | // | ||
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
15 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | // | ||
20 | // | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | * Implementation of system power management | ||
26 | */ | ||
27 | |||
28 | #include "ar6000_drv.h" | ||
29 | #include <linux/inetdevice.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include "wlan_config.h" | ||
32 | |||
33 | #define WOW_ENABLE_MAX_INTERVAL 0 | ||
34 | #define WOW_SET_SCAN_PARAMS 0 | ||
35 | |||
36 | extern unsigned int wmitimeout; | ||
37 | extern wait_queue_head_t arEvent; | ||
38 | |||
39 | #undef ATH_MODULE_NAME | ||
40 | #define ATH_MODULE_NAME pm | ||
41 | #define ATH_DEBUG_PM ATH_DEBUG_MAKE_MODULE_MASK(0) | ||
42 | |||
43 | #ifdef DEBUG | ||
44 | static struct ath_debug_mask_description pm_debug_desc[] = { | ||
45 | { ATH_DEBUG_PM , "System power management"}, | ||
46 | }; | ||
47 | |||
48 | ATH_DEBUG_INSTANTIATE_MODULE_VAR(pm, | ||
49 | "pm", | ||
50 | "System Power Management", | ||
51 | ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_PM, | ||
52 | ATH_DEBUG_DESCRIPTION_COUNT(pm_debug_desc), | ||
53 | pm_debug_desc); | ||
54 | |||
55 | #endif /* DEBUG */ | ||
56 | |||
57 | int ar6000_exit_cut_power_state(struct ar6_softc *ar); | ||
58 | |||
59 | #ifdef CONFIG_PM | ||
60 | static void ar6k_send_asleep_event_to_app(struct ar6_softc *ar, bool asleep) | ||
61 | { | ||
62 | char buf[128]; | ||
63 | union iwreq_data wrqu; | ||
64 | |||
65 | snprintf(buf, sizeof(buf), "HOST_ASLEEP=%s", asleep ? "asleep" : "awake"); | ||
66 | A_MEMZERO(&wrqu, sizeof(wrqu)); | ||
67 | wrqu.data.length = strlen(buf); | ||
68 | wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); | ||
69 | } | ||
70 | |||
71 | static void ar6000_wow_resume(struct ar6_softc *ar) | ||
72 | { | ||
73 | if (ar->arWowState!= WLAN_WOW_STATE_NONE) { | ||
74 | u16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period; | ||
75 | u16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period; | ||
76 | WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {true, false}; | ||
77 | ar->arWowState = WLAN_WOW_STATE_NONE; | ||
78 | if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!= 0) { | ||
79 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n")); | ||
80 | } | ||
81 | #if WOW_SET_SCAN_PARAMS | ||
82 | wmi_scanparams_cmd(ar->arWmi, fg_start_period, | ||
83 | ar->scParams.fg_end_period, | ||
84 | bg_period, | ||
85 | ar->scParams.minact_chdwell_time, | ||
86 | ar->scParams.maxact_chdwell_time, | ||
87 | ar->scParams.pas_chdwell_time, | ||
88 | ar->scParams.shortScanRatio, | ||
89 | ar->scParams.scanCtrlFlags, | ||
90 | ar->scParams.max_dfsch_act_time, | ||
91 | ar->scParams.maxact_scan_per_ssid); | ||
92 | #else | ||
93 | (void)fg_start_period; | ||
94 | (void)bg_period; | ||
95 | #endif | ||
96 | |||
97 | |||
98 | #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ | ||
99 | if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == 0) { | ||
100 | } | ||
101 | #endif | ||
102 | ar6k_send_asleep_event_to_app(ar, false); | ||
103 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Resume WoW successfully\n")); | ||
104 | } else { | ||
105 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WoW does not invoked. skip resume")); | ||
106 | } | ||
107 | ar->arWlanPowerState = WLAN_POWER_STATE_ON; | ||
108 | } | ||
109 | |||
110 | static void ar6000_wow_suspend(struct ar6_softc *ar) | ||
111 | { | ||
112 | #define WOW_LIST_ID 1 | ||
113 | if (ar->arNetworkType != AP_NETWORK) { | ||
114 | /* Setup WoW for unicast & Arp request for our own IP | ||
115 | disable background scan. Set listen interval into 1000 TUs | ||
116 | Enable keepliave for 110 seconds | ||
117 | */ | ||
118 | struct in_ifaddr **ifap = NULL; | ||
119 | struct in_ifaddr *ifa = NULL; | ||
120 | struct in_device *in_dev; | ||
121 | u8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
122 | int status; | ||
123 | WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } }; | ||
124 | WMI_DEL_WOW_PATTERN_CMD delWowCmd; | ||
125 | WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {false, true}; | ||
126 | WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = true, | ||
127 | .hostReqDelay = 500 };/*500 ms delay*/ | ||
128 | |||
129 | if (ar->arWowState!= WLAN_WOW_STATE_NONE) { | ||
130 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("System already go into wow mode!\n")); | ||
131 | return; | ||
132 | } | ||
133 | |||
134 | ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/ | ||
135 | |||
136 | #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ | ||
137 | if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == 0) { | ||
138 | } | ||
139 | #endif | ||
140 | |||
141 | #if WOW_SET_SCAN_PARAMS | ||
142 | status = wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0); | ||
143 | #endif | ||
144 | /* clear up our WoW pattern first */ | ||
145 | delWowCmd.filter_list_id = WOW_LIST_ID; | ||
146 | delWowCmd.filter_id = 0; | ||
147 | wmi_del_wow_pattern_cmd(ar->arWmi, &delWowCmd); | ||
148 | |||
149 | /* setup unicast packet pattern for WoW */ | ||
150 | if (ar->arNetDev->dev_addr[1]) { | ||
151 | addWowCmd.filter_list_id = WOW_LIST_ID; | ||
152 | addWowCmd.filter_size = 6; /* MAC address */ | ||
153 | addWowCmd.filter_offset = 0; | ||
154 | status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size); | ||
155 | if (status) { | ||
156 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n")); | ||
157 | } | ||
158 | } | ||
159 | /* setup ARP request for our own IP */ | ||
160 | if ((in_dev = __in_dev_get_rtnl(ar->arNetDev)) != NULL) { | ||
161 | for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { | ||
162 | if (!strcmp(ar->arNetDev->name, ifa->ifa_label)) { | ||
163 | break; /* found */ | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | if (ifa && ifa->ifa_local) { | ||
168 | WMI_SET_IP_CMD ipCmd; | ||
169 | memset(&ipCmd, 0, sizeof(ipCmd)); | ||
170 | ipCmd.ips[0] = ifa->ifa_local; | ||
171 | status = wmi_set_ip_cmd(ar->arWmi, &ipCmd); | ||
172 | if (status) { | ||
173 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n")); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | #ifndef ATH6K_CONFIG_OTA_MODE | ||
178 | wmi_powermode_cmd(ar->arWmi, REC_POWER); | ||
179 | #endif | ||
180 | |||
181 | status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode); | ||
182 | if (status) { | ||
183 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n")); | ||
184 | } | ||
185 | ar6k_send_asleep_event_to_app(ar, true); | ||
186 | |||
187 | status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode); | ||
188 | if (status) { | ||
189 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n")); | ||
190 | } | ||
191 | |||
192 | ar->arWowState = WLAN_WOW_STATE_SUSPENDING; | ||
193 | if (ar->arTxPending[ar->arControlEp]) { | ||
194 | u32 timeleft = wait_event_interruptible_timeout(arEvent, | ||
195 | ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); | ||
196 | if (!timeleft || signal_pending(current)) { | ||
197 | /* what can I do? wow resume at once */ | ||
198 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi control data %d\n", ar->arTxPending[ar->arControlEp])); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | status = hifWaitForPendingRecv(ar->arHifDevice); | ||
203 | |||
204 | ar->arWowState = WLAN_WOW_STATE_SUSPENDED; | ||
205 | ar->arWlanPowerState = WLAN_POWER_STATE_WOW; | ||
206 | } else { | ||
207 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Not allowed to go to WOW at this moment.\n")); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | int ar6000_suspend_ev(void *context) | ||
212 | { | ||
213 | int status = 0; | ||
214 | struct ar6_softc *ar = (struct ar6_softc *)context; | ||
215 | s16 pmmode = ar->arSuspendConfig; | ||
216 | wow_not_connected: | ||
217 | switch (pmmode) { | ||
218 | case WLAN_SUSPEND_WOW: | ||
219 | if (ar->arWmiReady && ar->arWlanState==WLAN_ENABLED && ar->arConnected) { | ||
220 | ar6000_wow_suspend(ar); | ||
221 | AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for wow mode %d\n", __func__, ar->arWlanPowerState)); | ||
222 | } else { | ||
223 | pmmode = ar->arWow2Config; | ||
224 | goto wow_not_connected; | ||
225 | } | ||
226 | break; | ||
227 | case WLAN_SUSPEND_CUT_PWR: | ||
228 | /* fall through */ | ||
229 | case WLAN_SUSPEND_CUT_PWR_IF_BT_OFF: | ||
230 | /* fall through */ | ||
231 | case WLAN_SUSPEND_DEEP_SLEEP: | ||
232 | /* fall through */ | ||
233 | default: | ||
234 | status = ar6000_update_wlan_pwr_state(ar, WLAN_DISABLED, true); | ||
235 | if (ar->arWlanPowerState==WLAN_POWER_STATE_ON || | ||
236 | ar->arWlanPowerState==WLAN_POWER_STATE_WOW) { | ||
237 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Strange suspend state for not wow mode %d", ar->arWlanPowerState)); | ||
238 | } | ||
239 | AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for %d mode pwr %d status %d\n", __func__, pmmode, ar->arWlanPowerState, status)); | ||
240 | status = (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) ? 0 : A_EBUSY; | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | ar->scan_triggered = 0; | ||
245 | return status; | ||
246 | } | ||
247 | |||
248 | int ar6000_resume_ev(void *context) | ||
249 | { | ||
250 | struct ar6_softc *ar = (struct ar6_softc *)context; | ||
251 | u16 powerState = ar->arWlanPowerState; | ||
252 | |||
253 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: enter previous state %d wowState %d\n", __func__, powerState, ar->arWowState)); | ||
254 | switch (powerState) { | ||
255 | case WLAN_POWER_STATE_WOW: | ||
256 | ar6000_wow_resume(ar); | ||
257 | break; | ||
258 | case WLAN_POWER_STATE_CUT_PWR: | ||
259 | /* fall through */ | ||
260 | case WLAN_POWER_STATE_DEEP_SLEEP: | ||
261 | ar6000_update_wlan_pwr_state(ar, WLAN_ENABLED, true); | ||
262 | AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Resume for %d mode pwr %d\n", __func__, powerState, ar->arWlanPowerState)); | ||
263 | break; | ||
264 | case WLAN_POWER_STATE_ON: | ||
265 | break; | ||
266 | default: | ||
267 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n")); | ||
268 | break; | ||
269 | } | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent) | ||
274 | { | ||
275 | if (ar->arWowState!=WLAN_WOW_STATE_NONE) { | ||
276 | if (ar->arWowState==WLAN_WOW_STATE_SUSPENDING) { | ||
277 | AR_DEBUG_PRINTF(ATH_DEBUG_PM,("\n%s: Received IRQ while we are wow suspending!!!\n\n", __func__)); | ||
278 | return; | ||
279 | } | ||
280 | /* Wow resume from irq interrupt */ | ||
281 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: WoW resume from irq thread status %d\n", __func__, ar->arWlanPowerState)); | ||
282 | ar6000_wow_resume(ar); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | int ar6000_power_change_ev(void *context, u32 config) | ||
287 | { | ||
288 | struct ar6_softc *ar = (struct ar6_softc *)context; | ||
289 | int status = 0; | ||
290 | |||
291 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: power change event callback %d \n", __func__, config)); | ||
292 | switch (config) { | ||
293 | case HIF_DEVICE_POWER_UP: | ||
294 | ar6000_restart_endpoint(ar->arNetDev); | ||
295 | status = 0; | ||
296 | break; | ||
297 | case HIF_DEVICE_POWER_DOWN: | ||
298 | case HIF_DEVICE_POWER_CUT: | ||
299 | status = 0; | ||
300 | break; | ||
301 | } | ||
302 | return status; | ||
303 | } | ||
304 | |||
305 | #endif /* CONFIG_PM */ | ||
306 | |||
307 | int | ||
308 | ar6000_setup_cut_power_state(struct ar6_softc *ar, AR6000_WLAN_STATE state) | ||
309 | { | ||
310 | int status = 0; | ||
311 | HIF_DEVICE_POWER_CHANGE_TYPE config; | ||
312 | |||
313 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Cut power %d %d \n", __func__,state, ar->arWlanPowerState)); | ||
314 | #ifdef CONFIG_PM | ||
315 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff)); | ||
316 | #endif | ||
317 | do { | ||
318 | if (state == WLAN_ENABLED) { | ||
319 | /* Not in cut power state.. exit */ | ||
320 | if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) { | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | /* Change the state to ON */ | ||
325 | ar->arWlanPowerState = WLAN_POWER_STATE_ON; | ||
326 | |||
327 | |||
328 | /* Indicate POWER_UP to HIF */ | ||
329 | config = HIF_DEVICE_POWER_UP; | ||
330 | status = HIFConfigureDevice(ar->arHifDevice, | ||
331 | HIF_DEVICE_POWER_STATE_CHANGE, | ||
332 | &config, | ||
333 | sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); | ||
334 | |||
335 | if (status == A_PENDING) { | ||
336 | } else if (status == 0) { | ||
337 | ar6000_restart_endpoint(ar->arNetDev); | ||
338 | status = 0; | ||
339 | } | ||
340 | } else if (state == WLAN_DISABLED) { | ||
341 | |||
342 | |||
343 | /* Already in cut power state.. exit */ | ||
344 | if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) { | ||
345 | break; | ||
346 | } | ||
347 | ar6000_stop_endpoint(ar->arNetDev, true, false); | ||
348 | |||
349 | config = HIF_DEVICE_POWER_CUT; | ||
350 | status = HIFConfigureDevice(ar->arHifDevice, | ||
351 | HIF_DEVICE_POWER_STATE_CHANGE, | ||
352 | &config, | ||
353 | sizeof(HIF_DEVICE_POWER_CHANGE_TYPE)); | ||
354 | |||
355 | ar->arWlanPowerState = WLAN_POWER_STATE_CUT_PWR; | ||
356 | } | ||
357 | } while (0); | ||
358 | |||
359 | return status; | ||
360 | } | ||
361 | |||
362 | int | ||
363 | ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state) | ||
364 | { | ||
365 | int status = 0; | ||
366 | |||
367 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Deep sleep %d %d \n", __func__,state, ar->arWlanPowerState)); | ||
368 | #ifdef CONFIG_PM | ||
369 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff)); | ||
370 | #endif | ||
371 | do { | ||
372 | WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode; | ||
373 | |||
374 | if (state == WLAN_ENABLED) { | ||
375 | u16 fg_start_period; | ||
376 | |||
377 | /* Not in deep sleep state.. exit */ | ||
378 | if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) { | ||
379 | if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) { | ||
380 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we resume from deep sleep %d\n", ar->arWlanPowerState)); | ||
381 | } | ||
382 | break; | ||
383 | } | ||
384 | |||
385 | fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period; | ||
386 | hostSleepMode.awake = true; | ||
387 | hostSleepMode.asleep = false; | ||
388 | |||
389 | if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != 0) { | ||
390 | break; | ||
391 | } | ||
392 | |||
393 | /* Change the state to ON */ | ||
394 | ar->arWlanPowerState = WLAN_POWER_STATE_ON; | ||
395 | |||
396 | /* Enable foreground scanning */ | ||
397 | if ((status=wmi_scanparams_cmd(ar->arWmi, fg_start_period, | ||
398 | ar->scParams.fg_end_period, | ||
399 | ar->scParams.bg_period, | ||
400 | ar->scParams.minact_chdwell_time, | ||
401 | ar->scParams.maxact_chdwell_time, | ||
402 | ar->scParams.pas_chdwell_time, | ||
403 | ar->scParams.shortScanRatio, | ||
404 | ar->scParams.scanCtrlFlags, | ||
405 | ar->scParams.max_dfsch_act_time, | ||
406 | ar->scParams.maxact_scan_per_ssid)) != 0) | ||
407 | { | ||
408 | break; | ||
409 | } | ||
410 | |||
411 | if (ar->arNetworkType != AP_NETWORK) | ||
412 | { | ||
413 | if (ar->arSsidLen) { | ||
414 | if (ar6000_connect_to_ap(ar) != 0) { | ||
415 | /* no need to report error if connection failed */ | ||
416 | break; | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | } else if (state == WLAN_DISABLED){ | ||
421 | WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = false }; | ||
422 | |||
423 | /* Already in deep sleep state.. exit */ | ||
424 | if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) { | ||
425 | if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) { | ||
426 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we suspend for deep sleep %d\n", ar->arWlanPowerState)); | ||
427 | } | ||
428 | break; | ||
429 | } | ||
430 | |||
431 | if (ar->arNetworkType != AP_NETWORK) | ||
432 | { | ||
433 | /* Disconnect from the AP and disable foreground scanning */ | ||
434 | AR6000_SPIN_LOCK(&ar->arLock, 0); | ||
435 | if (ar->arConnected == true || ar->arConnectPending == true) { | ||
436 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
437 | wmi_disconnect_cmd(ar->arWmi); | ||
438 | } else { | ||
439 | AR6000_SPIN_UNLOCK(&ar->arLock, 0); | ||
440 | } | ||
441 | } | ||
442 | |||
443 | ar->scan_triggered = 0; | ||
444 | |||
445 | if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != 0) { | ||
446 | break; | ||
447 | } | ||
448 | |||
449 | /* make sure we disable wow for deep sleep */ | ||
450 | if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!= 0) | ||
451 | { | ||
452 | break; | ||
453 | } | ||
454 | |||
455 | ar6000_TxDataCleanup(ar); | ||
456 | #ifndef ATH6K_CONFIG_OTA_MODE | ||
457 | wmi_powermode_cmd(ar->arWmi, REC_POWER); | ||
458 | #endif | ||
459 | |||
460 | hostSleepMode.awake = false; | ||
461 | hostSleepMode.asleep = true; | ||
462 | if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!= 0) { | ||
463 | break; | ||
464 | } | ||
465 | if (ar->arTxPending[ar->arControlEp]) { | ||
466 | u32 timeleft = wait_event_interruptible_timeout(arEvent, | ||
467 | ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); | ||
468 | if (!timeleft || signal_pending(current)) { | ||
469 | status = A_ERROR; | ||
470 | break; | ||
471 | } | ||
472 | } | ||
473 | status = hifWaitForPendingRecv(ar->arHifDevice); | ||
474 | |||
475 | ar->arWlanPowerState = WLAN_POWER_STATE_DEEP_SLEEP; | ||
476 | } | ||
477 | } while (0); | ||
478 | |||
479 | if (status) { | ||
480 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enter/exit deep sleep %d\n", state)); | ||
481 | } | ||
482 | |||
483 | return status; | ||
484 | } | ||
485 | |||
486 | int | ||
487 | ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool pmEvent) | ||
488 | { | ||
489 | int status = 0; | ||
490 | u16 powerState, oldPowerState; | ||
491 | AR6000_WLAN_STATE oldstate = ar->arWlanState; | ||
492 | bool wlanOff = ar->arWlanOff; | ||
493 | #ifdef CONFIG_PM | ||
494 | bool btOff = ar->arBTOff; | ||
495 | #endif /* CONFIG_PM */ | ||
496 | |||
497 | if ((state!=WLAN_DISABLED && state!=WLAN_ENABLED)) { | ||
498 | return A_ERROR; | ||
499 | } | ||
500 | |||
501 | if (ar->bIsDestroyProgress) { | ||
502 | return A_EBUSY; | ||
503 | } | ||
504 | |||
505 | if (down_interruptible(&ar->arSem)) { | ||
506 | return A_ERROR; | ||
507 | } | ||
508 | |||
509 | if (ar->bIsDestroyProgress) { | ||
510 | up(&ar->arSem); | ||
511 | return A_EBUSY; | ||
512 | } | ||
513 | |||
514 | ar->arWlanState = wlanOff ? WLAN_DISABLED : state; | ||
515 | oldPowerState = ar->arWlanPowerState; | ||
516 | if (state == WLAN_ENABLED) { | ||
517 | powerState = ar->arWlanPowerState; | ||
518 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to ENABLE^^\n")); | ||
519 | if (!wlanOff) { | ||
520 | if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) { | ||
521 | status = ar6000_setup_deep_sleep_state(ar, WLAN_ENABLED); | ||
522 | } else if (powerState == WLAN_POWER_STATE_CUT_PWR) { | ||
523 | status = ar6000_setup_cut_power_state(ar, WLAN_ENABLED); | ||
524 | } | ||
525 | } | ||
526 | #ifdef CONFIG_PM | ||
527 | else if (pmEvent && wlanOff) { | ||
528 | bool allowCutPwr = ((!ar->arBTSharing) || btOff); | ||
529 | if ((powerState==WLAN_POWER_STATE_CUT_PWR) && (!allowCutPwr)) { | ||
530 | /* Come out of cut power */ | ||
531 | ar6000_setup_cut_power_state(ar, WLAN_ENABLED); | ||
532 | status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED); | ||
533 | } | ||
534 | } | ||
535 | #endif /* CONFIG_PM */ | ||
536 | } else if (state == WLAN_DISABLED) { | ||
537 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to DISABLED~\n")); | ||
538 | powerState = WLAN_POWER_STATE_DEEP_SLEEP; | ||
539 | #ifdef CONFIG_PM | ||
540 | if (pmEvent) { /* disable due to suspend */ | ||
541 | bool suspendCutPwr = (ar->arSuspendConfig == WLAN_SUSPEND_CUT_PWR || | ||
542 | (ar->arSuspendConfig == WLAN_SUSPEND_WOW && | ||
543 | ar->arWow2Config==WLAN_SUSPEND_CUT_PWR)); | ||
544 | bool suspendCutIfBtOff = ((ar->arSuspendConfig == | ||
545 | WLAN_SUSPEND_CUT_PWR_IF_BT_OFF || | ||
546 | (ar->arSuspendConfig == WLAN_SUSPEND_WOW && | ||
547 | ar->arWow2Config==WLAN_SUSPEND_CUT_PWR_IF_BT_OFF)) && | ||
548 | (!ar->arBTSharing || btOff)); | ||
549 | if ((suspendCutPwr) || | ||
550 | (suspendCutIfBtOff) || | ||
551 | (ar->arWlanState==WLAN_POWER_STATE_CUT_PWR)) | ||
552 | { | ||
553 | powerState = WLAN_POWER_STATE_CUT_PWR; | ||
554 | } | ||
555 | } else { | ||
556 | if ((wlanOff) && | ||
557 | (ar->arWlanOffConfig == WLAN_OFF_CUT_PWR) && | ||
558 | (!ar->arBTSharing || btOff)) | ||
559 | { | ||
560 | /* For BT clock sharing designs, CUT_POWER depend on BT state */ | ||
561 | powerState = WLAN_POWER_STATE_CUT_PWR; | ||
562 | } | ||
563 | } | ||
564 | #endif /* CONFIG_PM */ | ||
565 | |||
566 | if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) { | ||
567 | if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) { | ||
568 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Load firmware before set to deep sleep\n")); | ||
569 | ar6000_setup_cut_power_state(ar, WLAN_ENABLED); | ||
570 | } | ||
571 | status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED); | ||
572 | } else if (powerState == WLAN_POWER_STATE_CUT_PWR) { | ||
573 | status = ar6000_setup_cut_power_state(ar, WLAN_DISABLED); | ||
574 | } | ||
575 | |||
576 | } | ||
577 | |||
578 | if (status) { | ||
579 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WLAN state %d\n", ar->arWlanState)); | ||
580 | ar->arWlanState = oldstate; | ||
581 | } else if (status == 0) { | ||
582 | WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent, *pSleepEvent = NULL; | ||
583 | if ((ar->arWlanPowerState == WLAN_POWER_STATE_ON) && (oldPowerState != WLAN_POWER_STATE_ON)) { | ||
584 | wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE; | ||
585 | pSleepEvent = &wmiSleepEvent; | ||
586 | } else if ((ar->arWlanPowerState != WLAN_POWER_STATE_ON) && (oldPowerState == WLAN_POWER_STATE_ON)) { | ||
587 | wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP; | ||
588 | pSleepEvent = &wmiSleepEvent; | ||
589 | } | ||
590 | if (pSleepEvent) { | ||
591 | AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("SENT WLAN Sleep Event %d\n", wmiSleepEvent.sleepState)); | ||
592 | } | ||
593 | } | ||
594 | up(&ar->arSem); | ||
595 | return status; | ||
596 | } | ||
597 | |||
598 | int | ||
599 | ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 enable) | ||
600 | { | ||
601 | #ifdef CONFIG_PM | ||
602 | bool off = (enable == 0); | ||
603 | int status; | ||
604 | if (ar->arBTOff == off) { | ||
605 | return 0; | ||
606 | } | ||
607 | ar->arBTOff = off; | ||
608 | status = ar6000_update_wlan_pwr_state(ar, ar->arWlanOff ? WLAN_DISABLED : WLAN_ENABLED, false); | ||
609 | return status; | ||
610 | #else | ||
611 | return 0; | ||
612 | #endif | ||
613 | } | ||
614 | |||
615 | int | ||
616 | ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state) | ||
617 | { | ||
618 | int status; | ||
619 | bool off = (state == WLAN_DISABLED); | ||
620 | if (ar->arWlanOff == off) { | ||
621 | return 0; | ||
622 | } | ||
623 | ar->arWlanOff = off; | ||
624 | status = ar6000_update_wlan_pwr_state(ar, state, false); | ||
625 | return status; | ||
626 | } | ||
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c b/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c new file mode 100644 index 00000000000..ae7c1dd96d8 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c | |||
@@ -0,0 +1,455 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #include "ar6000_drv.h" | ||
25 | |||
26 | #ifdef HTC_RAW_INTERFACE | ||
27 | |||
28 | static void | ||
29 | ar6000_htc_raw_read_cb(void *Context, struct htc_packet *pPacket) | ||
30 | { | ||
31 | struct ar6_softc *ar = (struct ar6_softc *)Context; | ||
32 | raw_htc_buffer *busy; | ||
33 | HTC_RAW_STREAM_ID streamID; | ||
34 | AR_RAW_HTC_T *arRaw = ar->arRawHtc; | ||
35 | |||
36 | busy = (raw_htc_buffer *)pPacket->pPktContext; | ||
37 | A_ASSERT(busy != NULL); | ||
38 | |||
39 | if (pPacket->Status == A_ECANCELED) { | ||
40 | /* | ||
41 | * HTC provides A_ECANCELED status when it doesn't want to be refilled | ||
42 | * (probably due to a shutdown) | ||
43 | */ | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint); | ||
48 | A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED); | ||
49 | |||
50 | #ifdef CF | ||
51 | if (down_trylock(&arRaw->raw_htc_read_sem[streamID])) { | ||
52 | #else | ||
53 | if (down_interruptible(&arRaw->raw_htc_read_sem[streamID])) { | ||
54 | #endif /* CF */ | ||
55 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n")); | ||
56 | } | ||
57 | |||
58 | A_ASSERT((pPacket->Status != 0) || | ||
59 | (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN))); | ||
60 | |||
61 | busy->length = pPacket->ActualLength + HTC_HEADER_LEN; | ||
62 | busy->currPtr = HTC_HEADER_LEN; | ||
63 | arRaw->read_buffer_available[streamID] = true; | ||
64 | //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("raw read cb: 0x%X 0x%X \n", busy->currPtr,busy->length); | ||
65 | up(&arRaw->raw_htc_read_sem[streamID]); | ||
66 | |||
67 | /* Signal the waiting process */ | ||
68 | AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) read process\n", streamID)); | ||
69 | wake_up_interruptible(&arRaw->raw_htc_read_queue[streamID]); | ||
70 | } | ||
71 | |||
72 | static void | ||
73 | ar6000_htc_raw_write_cb(void *Context, struct htc_packet *pPacket) | ||
74 | { | ||
75 | struct ar6_softc *ar = (struct ar6_softc *)Context; | ||
76 | raw_htc_buffer *free; | ||
77 | HTC_RAW_STREAM_ID streamID; | ||
78 | AR_RAW_HTC_T *arRaw = ar->arRawHtc; | ||
79 | |||
80 | free = (raw_htc_buffer *)pPacket->pPktContext; | ||
81 | A_ASSERT(free != NULL); | ||
82 | |||
83 | if (pPacket->Status == A_ECANCELED) { | ||
84 | /* | ||
85 | * HTC provides A_ECANCELED status when it doesn't want to be refilled | ||
86 | * (probably due to a shutdown) | ||
87 | */ | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint); | ||
92 | A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED); | ||
93 | |||
94 | #ifdef CF | ||
95 | if (down_trylock(&arRaw->raw_htc_write_sem[streamID])) { | ||
96 | #else | ||
97 | if (down_interruptible(&arRaw->raw_htc_write_sem[streamID])) { | ||
98 | #endif | ||
99 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n")); | ||
100 | } | ||
101 | |||
102 | A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN)); | ||
103 | |||
104 | free->length = 0; | ||
105 | arRaw->write_buffer_available[streamID] = true; | ||
106 | up(&arRaw->raw_htc_write_sem[streamID]); | ||
107 | |||
108 | /* Signal the waiting process */ | ||
109 | AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) write process\n", streamID)); | ||
110 | wake_up_interruptible(&arRaw->raw_htc_write_queue[streamID]); | ||
111 | } | ||
112 | |||
113 | /* connect to a service */ | ||
114 | static int ar6000_connect_raw_service(struct ar6_softc *ar, | ||
115 | HTC_RAW_STREAM_ID StreamID) | ||
116 | { | ||
117 | int status; | ||
118 | struct htc_service_connect_resp response; | ||
119 | u8 streamNo; | ||
120 | struct htc_service_connect_req connect; | ||
121 | |||
122 | do { | ||
123 | |||
124 | A_MEMZERO(&connect,sizeof(connect)); | ||
125 | /* pass the stream ID as meta data to the RAW streams service */ | ||
126 | streamNo = (u8)StreamID; | ||
127 | connect.pMetaData = &streamNo; | ||
128 | connect.MetaDataLength = sizeof(u8); | ||
129 | /* these fields are the same for all endpoints */ | ||
130 | connect.EpCallbacks.pContext = ar; | ||
131 | connect.EpCallbacks.EpTxComplete = ar6000_htc_raw_write_cb; | ||
132 | connect.EpCallbacks.EpRecv = ar6000_htc_raw_read_cb; | ||
133 | /* simple interface, we don't need these optional callbacks */ | ||
134 | connect.EpCallbacks.EpRecvRefill = NULL; | ||
135 | connect.EpCallbacks.EpSendFull = NULL; | ||
136 | connect.MaxSendQueueDepth = RAW_HTC_WRITE_BUFFERS_NUM; | ||
137 | |||
138 | /* connect to the raw streams service, we may be able to get 1 or more | ||
139 | * connections, depending on WHAT is running on the target */ | ||
140 | connect.ServiceID = HTC_RAW_STREAMS_SVC; | ||
141 | |||
142 | A_MEMZERO(&response,sizeof(response)); | ||
143 | |||
144 | /* try to connect to the raw stream, it is okay if this fails with | ||
145 | * status HTC_SERVICE_NO_MORE_EP */ | ||
146 | status = HTCConnectService(ar->arHtcTarget, | ||
147 | &connect, | ||
148 | &response); | ||
149 | |||
150 | if (status) { | ||
151 | if (response.ConnectRespCode == HTC_SERVICE_NO_MORE_EP) { | ||
152 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC RAW , No more streams allowed \n")); | ||
153 | status = 0; | ||
154 | } | ||
155 | break; | ||
156 | } | ||
157 | |||
158 | /* set endpoint mapping for the RAW HTC streams */ | ||
159 | arSetRawStream2EndpointIDMap(ar,StreamID,response.Endpoint); | ||
160 | |||
161 | AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("HTC RAW : stream ID: %d, endpoint: %d\n", | ||
162 | StreamID, arRawStream2EndpointID(ar,StreamID))); | ||
163 | |||
164 | } while (false); | ||
165 | |||
166 | return status; | ||
167 | } | ||
168 | |||
169 | int ar6000_htc_raw_open(struct ar6_softc *ar) | ||
170 | { | ||
171 | int status; | ||
172 | int streamID, endPt, count2; | ||
173 | raw_htc_buffer *buffer; | ||
174 | HTC_SERVICE_ID servicepriority; | ||
175 | AR_RAW_HTC_T *arRaw = ar->arRawHtc; | ||
176 | if (!arRaw) { | ||
177 | arRaw = ar->arRawHtc = A_MALLOC(sizeof(AR_RAW_HTC_T)); | ||
178 | if (arRaw) { | ||
179 | A_MEMZERO(arRaw, sizeof(AR_RAW_HTC_T)); | ||
180 | } | ||
181 | } | ||
182 | A_ASSERT(ar->arHtcTarget != NULL); | ||
183 | if (!arRaw) { | ||
184 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Faile to allocate memory for HTC RAW interface\n")); | ||
185 | return -ENOMEM; | ||
186 | } | ||
187 | /* wait for target */ | ||
188 | status = HTCWaitTarget(ar->arHtcTarget); | ||
189 | |||
190 | if (status) { | ||
191 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTCWaitTarget failed (%d)\n", status)); | ||
192 | return -ENODEV; | ||
193 | } | ||
194 | |||
195 | for (endPt = 0; endPt < ENDPOINT_MAX; endPt++) { | ||
196 | arRaw->arEp2RawMapping[endPt] = HTC_RAW_STREAM_NOT_MAPPED; | ||
197 | } | ||
198 | |||
199 | for (streamID = HTC_RAW_STREAM_0; streamID < HTC_RAW_STREAM_NUM_MAX; streamID++) { | ||
200 | /* Initialize the data structures */ | ||
201 | sema_init(&arRaw->raw_htc_read_sem[streamID], 1); | ||
202 | sema_init(&arRaw->raw_htc_write_sem[streamID], 1); | ||
203 | init_waitqueue_head(&arRaw->raw_htc_read_queue[streamID]); | ||
204 | init_waitqueue_head(&arRaw->raw_htc_write_queue[streamID]); | ||
205 | |||
206 | /* try to connect to the raw service */ | ||
207 | status = ar6000_connect_raw_service(ar,streamID); | ||
208 | |||
209 | if (status) { | ||
210 | break; | ||
211 | } | ||
212 | |||
213 | if (arRawStream2EndpointID(ar,streamID) == 0) { | ||
214 | break; | ||
215 | } | ||
216 | |||
217 | for (count2 = 0; count2 < RAW_HTC_READ_BUFFERS_NUM; count2 ++) { | ||
218 | /* Initialize the receive buffers */ | ||
219 | buffer = &arRaw->raw_htc_write_buffer[streamID][count2]; | ||
220 | memset(buffer, 0, sizeof(raw_htc_buffer)); | ||
221 | buffer = &arRaw->raw_htc_read_buffer[streamID][count2]; | ||
222 | memset(buffer, 0, sizeof(raw_htc_buffer)); | ||
223 | |||
224 | SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket, | ||
225 | buffer, | ||
226 | buffer->data, | ||
227 | HTC_RAW_BUFFER_SIZE, | ||
228 | arRawStream2EndpointID(ar,streamID)); | ||
229 | |||
230 | /* Queue buffers to HTC for receive */ | ||
231 | if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != 0) | ||
232 | { | ||
233 | BMIInit(); | ||
234 | return -EIO; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | for (count2 = 0; count2 < RAW_HTC_WRITE_BUFFERS_NUM; count2 ++) { | ||
239 | /* Initialize the receive buffers */ | ||
240 | buffer = &arRaw->raw_htc_write_buffer[streamID][count2]; | ||
241 | memset(buffer, 0, sizeof(raw_htc_buffer)); | ||
242 | } | ||
243 | |||
244 | arRaw->read_buffer_available[streamID] = false; | ||
245 | arRaw->write_buffer_available[streamID] = true; | ||
246 | } | ||
247 | |||
248 | if (status) { | ||
249 | return -EIO; | ||
250 | } | ||
251 | |||
252 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("HTC RAW, number of streams the target supports: %d \n", streamID)); | ||
253 | |||
254 | servicepriority = HTC_RAW_STREAMS_SVC; /* only 1 */ | ||
255 | |||
256 | /* set callbacks and priority list */ | ||
257 | HTCSetCreditDistribution(ar->arHtcTarget, | ||
258 | ar, | ||
259 | NULL, /* use default */ | ||
260 | NULL, /* use default */ | ||
261 | &servicepriority, | ||
262 | 1); | ||
263 | |||
264 | /* Start the HTC component */ | ||
265 | if ((status = HTCStart(ar->arHtcTarget)) != 0) { | ||
266 | BMIInit(); | ||
267 | return -EIO; | ||
268 | } | ||
269 | |||
270 | (ar)->arRawIfInit = true; | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | int ar6000_htc_raw_close(struct ar6_softc *ar) | ||
276 | { | ||
277 | A_PRINTF("ar6000_htc_raw_close called \n"); | ||
278 | HTCStop(ar->arHtcTarget); | ||
279 | |||
280 | /* reset the device */ | ||
281 | ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, false); | ||
282 | /* Initialize the BMI component */ | ||
283 | BMIInit(); | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | raw_htc_buffer * | ||
289 | get_filled_buffer(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID) | ||
290 | { | ||
291 | int count; | ||
292 | raw_htc_buffer *busy; | ||
293 | AR_RAW_HTC_T *arRaw = ar->arRawHtc; | ||
294 | |||
295 | /* Check for data */ | ||
296 | for (count = 0; count < RAW_HTC_READ_BUFFERS_NUM; count ++) { | ||
297 | busy = &arRaw->raw_htc_read_buffer[StreamID][count]; | ||
298 | if (busy->length) { | ||
299 | break; | ||
300 | } | ||
301 | } | ||
302 | if (busy->length) { | ||
303 | arRaw->read_buffer_available[StreamID] = true; | ||
304 | } else { | ||
305 | arRaw->read_buffer_available[StreamID] = false; | ||
306 | } | ||
307 | |||
308 | return busy; | ||
309 | } | ||
310 | |||
311 | ssize_t ar6000_htc_raw_read(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID, | ||
312 | char __user *buffer, size_t length) | ||
313 | { | ||
314 | int readPtr; | ||
315 | raw_htc_buffer *busy; | ||
316 | AR_RAW_HTC_T *arRaw = ar->arRawHtc; | ||
317 | |||
318 | if (arRawStream2EndpointID(ar,StreamID) == 0) { | ||
319 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID)); | ||
320 | return -EFAULT; | ||
321 | } | ||
322 | |||
323 | if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) { | ||
324 | return -ERESTARTSYS; | ||
325 | } | ||
326 | |||
327 | busy = get_filled_buffer(ar,StreamID); | ||
328 | while (!arRaw->read_buffer_available[StreamID]) { | ||
329 | up(&arRaw->raw_htc_read_sem[StreamID]); | ||
330 | |||
331 | /* Wait for the data */ | ||
332 | AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) read process\n", StreamID)); | ||
333 | if (wait_event_interruptible(arRaw->raw_htc_read_queue[StreamID], | ||
334 | arRaw->read_buffer_available[StreamID])) | ||
335 | { | ||
336 | return -EINTR; | ||
337 | } | ||
338 | if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) { | ||
339 | return -ERESTARTSYS; | ||
340 | } | ||
341 | busy = get_filled_buffer(ar,StreamID); | ||
342 | } | ||
343 | |||
344 | /* Read the data */ | ||
345 | readPtr = busy->currPtr; | ||
346 | if (length > busy->length - HTC_HEADER_LEN) { | ||
347 | length = busy->length - HTC_HEADER_LEN; | ||
348 | } | ||
349 | if (copy_to_user(buffer, &busy->data[readPtr], length)) { | ||
350 | up(&arRaw->raw_htc_read_sem[StreamID]); | ||
351 | return -EFAULT; | ||
352 | } | ||
353 | |||
354 | busy->currPtr += length; | ||
355 | |||
356 | if (busy->currPtr == busy->length) | ||
357 | { | ||
358 | busy->currPtr = 0; | ||
359 | busy->length = 0; | ||
360 | HTC_PACKET_RESET_RX(&busy->HTCPacket); | ||
361 | //AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("raw read ioctl: ep for packet:%d \n", busy->HTCPacket.Endpoint)); | ||
362 | HTCAddReceivePkt(ar->arHtcTarget, &busy->HTCPacket); | ||
363 | } | ||
364 | arRaw->read_buffer_available[StreamID] = false; | ||
365 | up(&arRaw->raw_htc_read_sem[StreamID]); | ||
366 | |||
367 | return length; | ||
368 | } | ||
369 | |||
370 | static raw_htc_buffer * | ||
371 | get_free_buffer(struct ar6_softc *ar, HTC_ENDPOINT_ID StreamID) | ||
372 | { | ||
373 | int count; | ||
374 | raw_htc_buffer *free; | ||
375 | AR_RAW_HTC_T *arRaw = ar->arRawHtc; | ||
376 | |||
377 | free = NULL; | ||
378 | for (count = 0; count < RAW_HTC_WRITE_BUFFERS_NUM; count ++) { | ||
379 | free = &arRaw->raw_htc_write_buffer[StreamID][count]; | ||
380 | if (free->length == 0) { | ||
381 | break; | ||
382 | } | ||
383 | } | ||
384 | if (!free->length) { | ||
385 | arRaw->write_buffer_available[StreamID] = true; | ||
386 | } else { | ||
387 | arRaw->write_buffer_available[StreamID] = false; | ||
388 | } | ||
389 | |||
390 | return free; | ||
391 | } | ||
392 | |||
393 | ssize_t ar6000_htc_raw_write(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID, | ||
394 | char __user *buffer, size_t length) | ||
395 | { | ||
396 | int writePtr; | ||
397 | raw_htc_buffer *free; | ||
398 | AR_RAW_HTC_T *arRaw = ar->arRawHtc; | ||
399 | if (arRawStream2EndpointID(ar,StreamID) == 0) { | ||
400 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID)); | ||
401 | return -EFAULT; | ||
402 | } | ||
403 | |||
404 | if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) { | ||
405 | return -ERESTARTSYS; | ||
406 | } | ||
407 | |||
408 | /* Search for a free buffer */ | ||
409 | free = get_free_buffer(ar,StreamID); | ||
410 | |||
411 | /* Check if there is space to write else wait */ | ||
412 | while (!arRaw->write_buffer_available[StreamID]) { | ||
413 | up(&arRaw->raw_htc_write_sem[StreamID]); | ||
414 | |||
415 | /* Wait for buffer to become free */ | ||
416 | AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) write process\n", StreamID)); | ||
417 | if (wait_event_interruptible(arRaw->raw_htc_write_queue[StreamID], | ||
418 | arRaw->write_buffer_available[StreamID])) | ||
419 | { | ||
420 | return -EINTR; | ||
421 | } | ||
422 | if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) { | ||
423 | return -ERESTARTSYS; | ||
424 | } | ||
425 | free = get_free_buffer(ar,StreamID); | ||
426 | } | ||
427 | |||
428 | /* Send the data */ | ||
429 | writePtr = HTC_HEADER_LEN; | ||
430 | if (length > (HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN)) { | ||
431 | length = HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN; | ||
432 | } | ||
433 | |||
434 | if (copy_from_user(&free->data[writePtr], buffer, length)) { | ||
435 | up(&arRaw->raw_htc_read_sem[StreamID]); | ||
436 | return -EFAULT; | ||
437 | } | ||
438 | |||
439 | free->length = length; | ||
440 | |||
441 | SET_HTC_PACKET_INFO_TX(&free->HTCPacket, | ||
442 | free, | ||
443 | &free->data[writePtr], | ||
444 | length, | ||
445 | arRawStream2EndpointID(ar,StreamID), | ||
446 | AR6K_DATA_PKT_TAG); | ||
447 | |||
448 | HTCSendPkt(ar->arHtcTarget,&free->HTCPacket); | ||
449 | |||
450 | arRaw->write_buffer_available[StreamID] = false; | ||
451 | up(&arRaw->raw_htc_write_sem[StreamID]); | ||
452 | |||
453 | return length; | ||
454 | } | ||
455 | #endif /* HTC_RAW_INTERFACE */ | ||
diff --git a/drivers/staging/ath6kl/os/linux/cfg80211.c b/drivers/staging/ath6kl/os/linux/cfg80211.c new file mode 100644 index 00000000000..5fdda4aa2fe --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/cfg80211.c | |||
@@ -0,0 +1,1892 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #include <linux/wireless.h> | ||
25 | #include <linux/ieee80211.h> | ||
26 | #include <net/cfg80211.h> | ||
27 | #include <net/netlink.h> | ||
28 | |||
29 | #include "ar6000_drv.h" | ||
30 | |||
31 | |||
32 | extern A_WAITQUEUE_HEAD arEvent; | ||
33 | extern unsigned int wmitimeout; | ||
34 | extern int reconnect_flag; | ||
35 | |||
36 | |||
37 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ | ||
38 | .bitrate = (_rate), \ | ||
39 | .flags = (_flags), \ | ||
40 | .hw_value = (_rateid), \ | ||
41 | } | ||
42 | |||
43 | #define CHAN2G(_channel, _freq, _flags) { \ | ||
44 | .band = IEEE80211_BAND_2GHZ, \ | ||
45 | .hw_value = (_channel), \ | ||
46 | .center_freq = (_freq), \ | ||
47 | .flags = (_flags), \ | ||
48 | .max_antenna_gain = 0, \ | ||
49 | .max_power = 30, \ | ||
50 | } | ||
51 | |||
52 | #define CHAN5G(_channel, _flags) { \ | ||
53 | .band = IEEE80211_BAND_5GHZ, \ | ||
54 | .hw_value = (_channel), \ | ||
55 | .center_freq = 5000 + (5 * (_channel)), \ | ||
56 | .flags = (_flags), \ | ||
57 | .max_antenna_gain = 0, \ | ||
58 | .max_power = 30, \ | ||
59 | } | ||
60 | |||
61 | static struct | ||
62 | ieee80211_rate ar6k_rates[] = { | ||
63 | RATETAB_ENT(10, 0x1, 0), | ||
64 | RATETAB_ENT(20, 0x2, 0), | ||
65 | RATETAB_ENT(55, 0x4, 0), | ||
66 | RATETAB_ENT(110, 0x8, 0), | ||
67 | RATETAB_ENT(60, 0x10, 0), | ||
68 | RATETAB_ENT(90, 0x20, 0), | ||
69 | RATETAB_ENT(120, 0x40, 0), | ||
70 | RATETAB_ENT(180, 0x80, 0), | ||
71 | RATETAB_ENT(240, 0x100, 0), | ||
72 | RATETAB_ENT(360, 0x200, 0), | ||
73 | RATETAB_ENT(480, 0x400, 0), | ||
74 | RATETAB_ENT(540, 0x800, 0), | ||
75 | }; | ||
76 | |||
77 | #define ar6k_a_rates (ar6k_rates + 4) | ||
78 | #define ar6k_a_rates_size 8 | ||
79 | #define ar6k_g_rates (ar6k_rates + 0) | ||
80 | #define ar6k_g_rates_size 12 | ||
81 | |||
82 | static struct | ||
83 | ieee80211_channel ar6k_2ghz_channels[] = { | ||
84 | CHAN2G(1, 2412, 0), | ||
85 | CHAN2G(2, 2417, 0), | ||
86 | CHAN2G(3, 2422, 0), | ||
87 | CHAN2G(4, 2427, 0), | ||
88 | CHAN2G(5, 2432, 0), | ||
89 | CHAN2G(6, 2437, 0), | ||
90 | CHAN2G(7, 2442, 0), | ||
91 | CHAN2G(8, 2447, 0), | ||
92 | CHAN2G(9, 2452, 0), | ||
93 | CHAN2G(10, 2457, 0), | ||
94 | CHAN2G(11, 2462, 0), | ||
95 | CHAN2G(12, 2467, 0), | ||
96 | CHAN2G(13, 2472, 0), | ||
97 | CHAN2G(14, 2484, 0), | ||
98 | }; | ||
99 | |||
100 | static struct | ||
101 | ieee80211_channel ar6k_5ghz_a_channels[] = { | ||
102 | CHAN5G(34, 0), CHAN5G(36, 0), | ||
103 | CHAN5G(38, 0), CHAN5G(40, 0), | ||
104 | CHAN5G(42, 0), CHAN5G(44, 0), | ||
105 | CHAN5G(46, 0), CHAN5G(48, 0), | ||
106 | CHAN5G(52, 0), CHAN5G(56, 0), | ||
107 | CHAN5G(60, 0), CHAN5G(64, 0), | ||
108 | CHAN5G(100, 0), CHAN5G(104, 0), | ||
109 | CHAN5G(108, 0), CHAN5G(112, 0), | ||
110 | CHAN5G(116, 0), CHAN5G(120, 0), | ||
111 | CHAN5G(124, 0), CHAN5G(128, 0), | ||
112 | CHAN5G(132, 0), CHAN5G(136, 0), | ||
113 | CHAN5G(140, 0), CHAN5G(149, 0), | ||
114 | CHAN5G(153, 0), CHAN5G(157, 0), | ||
115 | CHAN5G(161, 0), CHAN5G(165, 0), | ||
116 | CHAN5G(184, 0), CHAN5G(188, 0), | ||
117 | CHAN5G(192, 0), CHAN5G(196, 0), | ||
118 | CHAN5G(200, 0), CHAN5G(204, 0), | ||
119 | CHAN5G(208, 0), CHAN5G(212, 0), | ||
120 | CHAN5G(216, 0), | ||
121 | }; | ||
122 | |||
123 | static struct | ||
124 | ieee80211_supported_band ar6k_band_2ghz = { | ||
125 | .n_channels = ARRAY_SIZE(ar6k_2ghz_channels), | ||
126 | .channels = ar6k_2ghz_channels, | ||
127 | .n_bitrates = ar6k_g_rates_size, | ||
128 | .bitrates = ar6k_g_rates, | ||
129 | }; | ||
130 | |||
131 | static struct | ||
132 | ieee80211_supported_band ar6k_band_5ghz = { | ||
133 | .n_channels = ARRAY_SIZE(ar6k_5ghz_a_channels), | ||
134 | .channels = ar6k_5ghz_a_channels, | ||
135 | .n_bitrates = ar6k_a_rates_size, | ||
136 | .bitrates = ar6k_a_rates, | ||
137 | }; | ||
138 | |||
139 | static int | ||
140 | ar6k_set_wpa_version(struct ar6_softc *ar, enum nl80211_wpa_versions wpa_version) | ||
141 | { | ||
142 | |||
143 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: %u\n", __func__, wpa_version)); | ||
144 | |||
145 | if (!wpa_version) { | ||
146 | ar->arAuthMode = NONE_AUTH; | ||
147 | } else if (wpa_version & NL80211_WPA_VERSION_1) { | ||
148 | ar->arAuthMode = WPA_AUTH; | ||
149 | } else if (wpa_version & NL80211_WPA_VERSION_2) { | ||
150 | ar->arAuthMode = WPA2_AUTH; | ||
151 | } else { | ||
152 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
153 | ("%s: %u not spported\n", __func__, wpa_version)); | ||
154 | return -ENOTSUPP; | ||
155 | } | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int | ||
161 | ar6k_set_auth_type(struct ar6_softc *ar, enum nl80211_auth_type auth_type) | ||
162 | { | ||
163 | |||
164 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, auth_type)); | ||
165 | |||
166 | switch (auth_type) { | ||
167 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | ||
168 | ar->arDot11AuthMode = OPEN_AUTH; | ||
169 | break; | ||
170 | case NL80211_AUTHTYPE_SHARED_KEY: | ||
171 | ar->arDot11AuthMode = SHARED_AUTH; | ||
172 | break; | ||
173 | case NL80211_AUTHTYPE_NETWORK_EAP: | ||
174 | ar->arDot11AuthMode = LEAP_AUTH; | ||
175 | break; | ||
176 | |||
177 | case NL80211_AUTHTYPE_AUTOMATIC: | ||
178 | ar->arDot11AuthMode = OPEN_AUTH; | ||
179 | ar->arAutoAuthStage = AUTH_OPEN_IN_PROGRESS; | ||
180 | break; | ||
181 | |||
182 | default: | ||
183 | ar->arDot11AuthMode = OPEN_AUTH; | ||
184 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
185 | ("%s: 0x%x not spported\n", __func__, auth_type)); | ||
186 | return -ENOTSUPP; | ||
187 | } | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int | ||
193 | ar6k_set_cipher(struct ar6_softc *ar, u32 cipher, bool ucast) | ||
194 | { | ||
195 | u8 *ar_cipher = ucast ? &ar->arPairwiseCrypto : | ||
196 | &ar->arGroupCrypto; | ||
197 | u8 *ar_cipher_len = ucast ? &ar->arPairwiseCryptoLen : | ||
198 | &ar->arGroupCryptoLen; | ||
199 | |||
200 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
201 | ("%s: cipher 0x%x, ucast %u\n", __func__, cipher, ucast)); | ||
202 | |||
203 | switch (cipher) { | ||
204 | case 0: | ||
205 | case IW_AUTH_CIPHER_NONE: | ||
206 | *ar_cipher = NONE_CRYPT; | ||
207 | *ar_cipher_len = 0; | ||
208 | break; | ||
209 | case WLAN_CIPHER_SUITE_WEP40: | ||
210 | *ar_cipher = WEP_CRYPT; | ||
211 | *ar_cipher_len = 5; | ||
212 | break; | ||
213 | case WLAN_CIPHER_SUITE_WEP104: | ||
214 | *ar_cipher = WEP_CRYPT; | ||
215 | *ar_cipher_len = 13; | ||
216 | break; | ||
217 | case WLAN_CIPHER_SUITE_TKIP: | ||
218 | *ar_cipher = TKIP_CRYPT; | ||
219 | *ar_cipher_len = 0; | ||
220 | break; | ||
221 | case WLAN_CIPHER_SUITE_CCMP: | ||
222 | *ar_cipher = AES_CRYPT; | ||
223 | *ar_cipher_len = 0; | ||
224 | break; | ||
225 | default: | ||
226 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
227 | ("%s: cipher 0x%x not supported\n", __func__, cipher)); | ||
228 | return -ENOTSUPP; | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static void | ||
235 | ar6k_set_key_mgmt(struct ar6_softc *ar, u32 key_mgmt) | ||
236 | { | ||
237 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, key_mgmt)); | ||
238 | |||
239 | if (WLAN_AKM_SUITE_PSK == key_mgmt) { | ||
240 | if (WPA_AUTH == ar->arAuthMode) { | ||
241 | ar->arAuthMode = WPA_PSK_AUTH; | ||
242 | } else if (WPA2_AUTH == ar->arAuthMode) { | ||
243 | ar->arAuthMode = WPA2_PSK_AUTH; | ||
244 | } | ||
245 | } else if (WLAN_AKM_SUITE_8021X != key_mgmt) { | ||
246 | ar->arAuthMode = NONE_AUTH; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static int | ||
251 | ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | ||
252 | struct cfg80211_connect_params *sme) | ||
253 | { | ||
254 | struct ar6_softc *ar = ar6k_priv(dev); | ||
255 | int status; | ||
256 | |||
257 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); | ||
258 | ar->smeState = SME_CONNECTING; | ||
259 | |||
260 | if(ar->arWmiReady == false) { | ||
261 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready yet\n", __func__)); | ||
262 | return -EIO; | ||
263 | } | ||
264 | |||
265 | if(ar->arWlanState == WLAN_DISABLED) { | ||
266 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
267 | return -EIO; | ||
268 | } | ||
269 | |||
270 | if(ar->bIsDestroyProgress) { | ||
271 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: destroy in progress\n", __func__)); | ||
272 | return -EBUSY; | ||
273 | } | ||
274 | |||
275 | if(!sme->ssid_len || IEEE80211_MAX_SSID_LEN < sme->ssid_len) { | ||
276 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ssid invalid\n", __func__)); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | if(ar->arSkipScan == true && | ||
281 | ((sme->channel && sme->channel->center_freq == 0) || | ||
282 | (sme->bssid && !sme->bssid[0] && !sme->bssid[1] && !sme->bssid[2] && | ||
283 | !sme->bssid[3] && !sme->bssid[4] && !sme->bssid[5]))) | ||
284 | { | ||
285 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s:SkipScan: channel or bssid invalid\n", __func__)); | ||
286 | return -EINVAL; | ||
287 | } | ||
288 | |||
289 | if(down_interruptible(&ar->arSem)) { | ||
290 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__)); | ||
291 | return -ERESTARTSYS; | ||
292 | } | ||
293 | |||
294 | if(ar->bIsDestroyProgress) { | ||
295 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, destroy in progress\n", __func__)); | ||
296 | up(&ar->arSem); | ||
297 | return -EBUSY; | ||
298 | } | ||
299 | |||
300 | if(ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) { | ||
301 | /* | ||
302 | * sleep until the command queue drains | ||
303 | */ | ||
304 | wait_event_interruptible_timeout(arEvent, | ||
305 | ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ); | ||
306 | if (signal_pending(current)) { | ||
307 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: cmd queue drain timeout\n", __func__)); | ||
308 | up(&ar->arSem); | ||
309 | return -EINTR; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | if(ar->arConnected == true && | ||
314 | ar->arSsidLen == sme->ssid_len && | ||
315 | !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) { | ||
316 | reconnect_flag = true; | ||
317 | status = wmi_reconnect_cmd(ar->arWmi, | ||
318 | ar->arReqBssid, | ||
319 | ar->arChannelHint); | ||
320 | |||
321 | up(&ar->arSem); | ||
322 | if (status) { | ||
323 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_reconnect_cmd failed\n", __func__)); | ||
324 | return -EIO; | ||
325 | } | ||
326 | return 0; | ||
327 | } else if(ar->arSsidLen == sme->ssid_len && | ||
328 | !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) { | ||
329 | ar6000_disconnect(ar); | ||
330 | } | ||
331 | |||
332 | A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); | ||
333 | ar->arSsidLen = sme->ssid_len; | ||
334 | memcpy(ar->arSsid, sme->ssid, sme->ssid_len); | ||
335 | |||
336 | if(sme->channel){ | ||
337 | ar->arChannelHint = sme->channel->center_freq; | ||
338 | } | ||
339 | |||
340 | A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); | ||
341 | if(sme->bssid){ | ||
342 | if(memcmp(&sme->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) { | ||
343 | memcpy(ar->arReqBssid, sme->bssid, sizeof(ar->arReqBssid)); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | ar6k_set_wpa_version(ar, sme->crypto.wpa_versions); | ||
348 | ar6k_set_auth_type(ar, sme->auth_type); | ||
349 | |||
350 | if(sme->crypto.n_ciphers_pairwise) { | ||
351 | ar6k_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true); | ||
352 | } else { | ||
353 | ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, true); | ||
354 | } | ||
355 | ar6k_set_cipher(ar, sme->crypto.cipher_group, false); | ||
356 | |||
357 | if(sme->crypto.n_akm_suites) { | ||
358 | ar6k_set_key_mgmt(ar, sme->crypto.akm_suites[0]); | ||
359 | } | ||
360 | |||
361 | if((sme->key_len) && | ||
362 | (NONE_AUTH == ar->arAuthMode) && | ||
363 | (WEP_CRYPT == ar->arPairwiseCrypto)) { | ||
364 | struct ar_key *key = NULL; | ||
365 | |||
366 | if(sme->key_idx < WMI_MIN_KEY_INDEX || sme->key_idx > WMI_MAX_KEY_INDEX) { | ||
367 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
368 | ("%s: key index %d out of bounds\n", __func__, sme->key_idx)); | ||
369 | up(&ar->arSem); | ||
370 | return -ENOENT; | ||
371 | } | ||
372 | |||
373 | key = &ar->keys[sme->key_idx]; | ||
374 | key->key_len = sme->key_len; | ||
375 | memcpy(key->key, sme->key, key->key_len); | ||
376 | key->cipher = ar->arPairwiseCrypto; | ||
377 | ar->arDefTxKeyIndex = sme->key_idx; | ||
378 | |||
379 | wmi_addKey_cmd(ar->arWmi, sme->key_idx, | ||
380 | ar->arPairwiseCrypto, | ||
381 | GROUP_USAGE | TX_USAGE, | ||
382 | key->key_len, | ||
383 | NULL, | ||
384 | key->key, KEY_OP_INIT_VAL, NULL, | ||
385 | NO_SYNC_WMIFLAG); | ||
386 | } | ||
387 | |||
388 | if (!ar->arUserBssFilter) { | ||
389 | if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) { | ||
390 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__)); | ||
391 | up(&ar->arSem); | ||
392 | return -EIO; | ||
393 | } | ||
394 | } | ||
395 | |||
396 | ar->arNetworkType = ar->arNextMode; | ||
397 | |||
398 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Connect called with authmode %d dot11 auth %d"\ | ||
399 | " PW crypto %d PW crypto Len %d GRP crypto %d"\ | ||
400 | " GRP crypto Len %d channel hint %u\n", | ||
401 | __func__, ar->arAuthMode, ar->arDot11AuthMode, | ||
402 | ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, | ||
403 | ar->arGroupCrypto, ar->arGroupCryptoLen, ar->arChannelHint)); | ||
404 | |||
405 | reconnect_flag = 0; | ||
406 | status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, | ||
407 | ar->arDot11AuthMode, ar->arAuthMode, | ||
408 | ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, | ||
409 | ar->arGroupCrypto,ar->arGroupCryptoLen, | ||
410 | ar->arSsidLen, ar->arSsid, | ||
411 | ar->arReqBssid, ar->arChannelHint, | ||
412 | ar->arConnectCtrlFlags); | ||
413 | |||
414 | up(&ar->arSem); | ||
415 | |||
416 | if (A_EINVAL == status) { | ||
417 | A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); | ||
418 | ar->arSsidLen = 0; | ||
419 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Invalid request\n", __func__)); | ||
420 | return -ENOENT; | ||
421 | } else if (status) { | ||
422 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_connect_cmd failed\n", __func__)); | ||
423 | return -EIO; | ||
424 | } | ||
425 | |||
426 | if ((!(ar->arConnectCtrlFlags & CONNECT_DO_WPA_OFFLOAD)) && | ||
427 | ((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode))) | ||
428 | { | ||
429 | A_TIMEOUT_MS(&ar->disconnect_timer, A_DISCONNECT_TIMER_INTERVAL, 0); | ||
430 | } | ||
431 | |||
432 | ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD; | ||
433 | ar->arConnectPending = true; | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | void | ||
439 | ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel, | ||
440 | u8 *bssid, u16 listenInterval, | ||
441 | u16 beaconInterval,NETWORK_TYPE networkType, | ||
442 | u8 beaconIeLen, u8 assocReqLen, | ||
443 | u8 assocRespLen, u8 *assocInfo) | ||
444 | { | ||
445 | u16 size = 0; | ||
446 | u16 capability = 0; | ||
447 | struct cfg80211_bss *bss = NULL; | ||
448 | struct ieee80211_mgmt *mgmt = NULL; | ||
449 | struct ieee80211_channel *ibss_channel = NULL; | ||
450 | s32 signal = 50 * 100; | ||
451 | u8 ie_buf_len = 0; | ||
452 | unsigned char ie_buf[256]; | ||
453 | unsigned char *ptr_ie_buf = ie_buf; | ||
454 | unsigned char *ieeemgmtbuf = NULL; | ||
455 | u8 source_mac[ATH_MAC_LEN]; | ||
456 | |||
457 | u8 assocReqIeOffset = sizeof(u16) + /* capinfo*/ | ||
458 | sizeof(u16); /* listen interval */ | ||
459 | u8 assocRespIeOffset = sizeof(u16) + /* capinfo*/ | ||
460 | sizeof(u16) + /* status Code */ | ||
461 | sizeof(u16); /* associd */ | ||
462 | u8 *assocReqIe = assocInfo + beaconIeLen + assocReqIeOffset; | ||
463 | u8 *assocRespIe = assocInfo + beaconIeLen + assocReqLen + assocRespIeOffset; | ||
464 | |||
465 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); | ||
466 | |||
467 | assocReqLen -= assocReqIeOffset; | ||
468 | assocRespLen -= assocRespIeOffset; | ||
469 | |||
470 | ar->arAutoAuthStage = AUTH_IDLE; | ||
471 | |||
472 | if((ADHOC_NETWORK & networkType)) { | ||
473 | if(NL80211_IFTYPE_ADHOC != ar->wdev->iftype) { | ||
474 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
475 | ("%s: ath6k not in ibss mode\n", __func__)); | ||
476 | return; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | if((INFRA_NETWORK & networkType)) { | ||
481 | if(NL80211_IFTYPE_STATION != ar->wdev->iftype) { | ||
482 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
483 | ("%s: ath6k not in station mode\n", __func__)); | ||
484 | return; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | /* Before informing the join/connect event, make sure that | ||
489 | * bss entry is present in scan list, if it not present | ||
490 | * construct and insert into scan list, otherwise that | ||
491 | * event will be dropped on the way by cfg80211, due to | ||
492 | * this keys will not be plumbed in case of WEP and | ||
493 | * application will not be aware of join/connect status. */ | ||
494 | bss = cfg80211_get_bss(ar->wdev->wiphy, NULL, bssid, | ||
495 | ar->wdev->ssid, ar->wdev->ssid_len, | ||
496 | ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS), | ||
497 | ((ADHOC_NETWORK & networkType) ? WLAN_CAPABILITY_IBSS : WLAN_CAPABILITY_ESS)); | ||
498 | |||
499 | /* | ||
500 | * Earlier we were updating the cfg about bss by making a beacon frame | ||
501 | * only if the entry for bss is not there. This can have some issue if | ||
502 | * ROAM event is generated and a heavy traffic is ongoing. The ROAM | ||
503 | * event is handled through a work queue and by the time it really gets | ||
504 | * handled, BSS would have been aged out. So it is better to update the | ||
505 | * cfg about BSS irrespective of its entry being present right now or | ||
506 | * not. | ||
507 | */ | ||
508 | |||
509 | if (ADHOC_NETWORK & networkType) { | ||
510 | /* construct 802.11 mgmt beacon */ | ||
511 | if(ptr_ie_buf) { | ||
512 | *ptr_ie_buf++ = WLAN_EID_SSID; | ||
513 | *ptr_ie_buf++ = ar->arSsidLen; | ||
514 | memcpy(ptr_ie_buf, ar->arSsid, ar->arSsidLen); | ||
515 | ptr_ie_buf +=ar->arSsidLen; | ||
516 | |||
517 | *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS; | ||
518 | *ptr_ie_buf++ = 2; /* length */ | ||
519 | *ptr_ie_buf++ = 0; /* ATIM window */ | ||
520 | *ptr_ie_buf++ = 0; /* ATIM window */ | ||
521 | |||
522 | /* TODO: update ibss params and include supported rates, | ||
523 | * DS param set, extened support rates, wmm. */ | ||
524 | |||
525 | ie_buf_len = ptr_ie_buf - ie_buf; | ||
526 | } | ||
527 | |||
528 | capability |= IEEE80211_CAPINFO_IBSS; | ||
529 | if(WEP_CRYPT == ar->arPairwiseCrypto) { | ||
530 | capability |= IEEE80211_CAPINFO_PRIVACY; | ||
531 | } | ||
532 | memcpy(source_mac, ar->arNetDev->dev_addr, ATH_MAC_LEN); | ||
533 | ptr_ie_buf = ie_buf; | ||
534 | } else { | ||
535 | capability = *(u16 *)(&assocInfo[beaconIeLen]); | ||
536 | memcpy(source_mac, bssid, ATH_MAC_LEN); | ||
537 | ptr_ie_buf = assocReqIe; | ||
538 | ie_buf_len = assocReqLen; | ||
539 | } | ||
540 | |||
541 | size = offsetof(struct ieee80211_mgmt, u) | ||
542 | + sizeof(mgmt->u.beacon) | ||
543 | + ie_buf_len; | ||
544 | |||
545 | ieeemgmtbuf = A_MALLOC_NOWAIT(size); | ||
546 | if(!ieeemgmtbuf) { | ||
547 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
548 | ("%s: ieeeMgmtbuf alloc error\n", __func__)); | ||
549 | cfg80211_put_bss(bss); | ||
550 | return; | ||
551 | } | ||
552 | |||
553 | A_MEMZERO(ieeemgmtbuf, size); | ||
554 | mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; | ||
555 | mgmt->frame_control = (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); | ||
556 | memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN); | ||
557 | memcpy(mgmt->sa, source_mac, ATH_MAC_LEN); | ||
558 | memcpy(mgmt->bssid, bssid, ATH_MAC_LEN); | ||
559 | mgmt->u.beacon.beacon_int = beaconInterval; | ||
560 | mgmt->u.beacon.capab_info = capability; | ||
561 | memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len); | ||
562 | |||
563 | ibss_channel = ieee80211_get_channel(ar->wdev->wiphy, (int)channel); | ||
564 | |||
565 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
566 | ("%s: inform bss with bssid %pM channel %d beaconInterval %d " | ||
567 | "capability 0x%x\n", __func__, mgmt->bssid, | ||
568 | ibss_channel->hw_value, beaconInterval, capability)); | ||
569 | |||
570 | bss = cfg80211_inform_bss_frame(ar->wdev->wiphy, | ||
571 | ibss_channel, mgmt, | ||
572 | le16_to_cpu(size), | ||
573 | signal, GFP_KERNEL); | ||
574 | kfree(ieeemgmtbuf); | ||
575 | cfg80211_put_bss(bss); | ||
576 | |||
577 | if((ADHOC_NETWORK & networkType)) { | ||
578 | cfg80211_ibss_joined(ar->arNetDev, bssid, GFP_KERNEL); | ||
579 | return; | ||
580 | } | ||
581 | |||
582 | if (false == ar->arConnected) { | ||
583 | /* inform connect result to cfg80211 */ | ||
584 | ar->smeState = SME_DISCONNECTED; | ||
585 | cfg80211_connect_result(ar->arNetDev, bssid, | ||
586 | assocReqIe, assocReqLen, | ||
587 | assocRespIe, assocRespLen, | ||
588 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | ||
589 | } else { | ||
590 | /* inform roam event to cfg80211 */ | ||
591 | cfg80211_roamed(ar->arNetDev, ibss_channel, bssid, | ||
592 | assocReqIe, assocReqLen, | ||
593 | assocRespIe, assocRespLen, | ||
594 | GFP_KERNEL); | ||
595 | } | ||
596 | } | ||
597 | |||
598 | static int | ||
599 | ar6k_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, | ||
600 | u16 reason_code) | ||
601 | { | ||
602 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
603 | |||
604 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason_code)); | ||
605 | |||
606 | if(ar->arWmiReady == false) { | ||
607 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
608 | return -EIO; | ||
609 | } | ||
610 | |||
611 | if(ar->arWlanState == WLAN_DISABLED) { | ||
612 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
613 | return -EIO; | ||
614 | } | ||
615 | |||
616 | if(ar->bIsDestroyProgress) { | ||
617 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, destroy in progress\n", __func__)); | ||
618 | return -EBUSY; | ||
619 | } | ||
620 | |||
621 | if(down_interruptible(&ar->arSem)) { | ||
622 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__)); | ||
623 | return -ERESTARTSYS; | ||
624 | } | ||
625 | |||
626 | reconnect_flag = 0; | ||
627 | ar6000_disconnect(ar); | ||
628 | A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); | ||
629 | ar->arSsidLen = 0; | ||
630 | |||
631 | if (ar->arSkipScan == false) { | ||
632 | A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); | ||
633 | } | ||
634 | |||
635 | up(&ar->arSem); | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | void | ||
641 | ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason, | ||
642 | u8 *bssid, u8 assocRespLen, | ||
643 | u8 *assocInfo, u16 protocolReasonStatus) | ||
644 | { | ||
645 | |||
646 | u16 status; | ||
647 | |||
648 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason)); | ||
649 | |||
650 | if (ar->scan_request) { | ||
651 | cfg80211_scan_done(ar->scan_request, true); | ||
652 | ar->scan_request = NULL; | ||
653 | } | ||
654 | if((ADHOC_NETWORK & ar->arNetworkType)) { | ||
655 | if(NL80211_IFTYPE_ADHOC != ar->wdev->iftype) { | ||
656 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
657 | ("%s: ath6k not in ibss mode\n", __func__)); | ||
658 | return; | ||
659 | } | ||
660 | A_MEMZERO(bssid, ETH_ALEN); | ||
661 | cfg80211_ibss_joined(ar->arNetDev, bssid, GFP_KERNEL); | ||
662 | return; | ||
663 | } | ||
664 | |||
665 | if((INFRA_NETWORK & ar->arNetworkType)) { | ||
666 | if(NL80211_IFTYPE_STATION != ar->wdev->iftype) { | ||
667 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
668 | ("%s: ath6k not in station mode\n", __func__)); | ||
669 | return; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | if(true == ar->arConnectPending) { | ||
674 | if(NO_NETWORK_AVAIL == reason) { | ||
675 | /* connect cmd failed */ | ||
676 | wmi_disconnect_cmd(ar->arWmi); | ||
677 | } else if (reason == DISCONNECT_CMD) { | ||
678 | if (ar->arAutoAuthStage) { | ||
679 | /* | ||
680 | * If the current auth algorithm is open try shared | ||
681 | * and make autoAuthStage idle. We do not make it | ||
682 | * leap for now being. | ||
683 | */ | ||
684 | if (ar->arDot11AuthMode == OPEN_AUTH) { | ||
685 | struct ar_key *key = NULL; | ||
686 | key = &ar->keys[ar->arDefTxKeyIndex]; | ||
687 | if (down_interruptible(&ar->arSem)) { | ||
688 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: busy, couldn't get access\n", __func__)); | ||
689 | return; | ||
690 | } | ||
691 | |||
692 | |||
693 | ar->arDot11AuthMode = SHARED_AUTH; | ||
694 | ar->arAutoAuthStage = AUTH_IDLE; | ||
695 | |||
696 | wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, | ||
697 | ar->arPairwiseCrypto, | ||
698 | GROUP_USAGE | TX_USAGE, | ||
699 | key->key_len, | ||
700 | NULL, | ||
701 | key->key, KEY_OP_INIT_VAL, NULL, | ||
702 | NO_SYNC_WMIFLAG); | ||
703 | |||
704 | status = wmi_connect_cmd(ar->arWmi, | ||
705 | ar->arNetworkType, | ||
706 | ar->arDot11AuthMode, | ||
707 | ar->arAuthMode, | ||
708 | ar->arPairwiseCrypto, | ||
709 | ar->arPairwiseCryptoLen, | ||
710 | ar->arGroupCrypto, | ||
711 | ar->arGroupCryptoLen, | ||
712 | ar->arSsidLen, | ||
713 | ar->arSsid, | ||
714 | ar->arReqBssid, | ||
715 | ar->arChannelHint, | ||
716 | ar->arConnectCtrlFlags); | ||
717 | up(&ar->arSem); | ||
718 | |||
719 | } else if (ar->arDot11AuthMode == SHARED_AUTH) { | ||
720 | /* should not reach here */ | ||
721 | } | ||
722 | } else { | ||
723 | ar->arConnectPending = false; | ||
724 | if (ar->smeState == SME_CONNECTING) { | ||
725 | cfg80211_connect_result(ar->arNetDev, bssid, | ||
726 | NULL, 0, | ||
727 | NULL, 0, | ||
728 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
729 | GFP_KERNEL); | ||
730 | } else { | ||
731 | cfg80211_disconnected(ar->arNetDev, | ||
732 | reason, | ||
733 | NULL, 0, | ||
734 | GFP_KERNEL); | ||
735 | } | ||
736 | ar->smeState = SME_DISCONNECTED; | ||
737 | } | ||
738 | } | ||
739 | } else { | ||
740 | if (reason != DISCONNECT_CMD) | ||
741 | wmi_disconnect_cmd(ar->arWmi); | ||
742 | } | ||
743 | } | ||
744 | |||
745 | void | ||
746 | ar6k_cfg80211_scan_node(void *arg, bss_t *ni) | ||
747 | { | ||
748 | struct wiphy *wiphy = (struct wiphy *)arg; | ||
749 | u16 size; | ||
750 | unsigned char *ieeemgmtbuf = NULL; | ||
751 | struct ieee80211_mgmt *mgmt; | ||
752 | struct ieee80211_channel *channel; | ||
753 | struct ieee80211_supported_band *band; | ||
754 | struct ieee80211_common_ie *cie; | ||
755 | s32 signal; | ||
756 | int freq; | ||
757 | |||
758 | cie = &ni->ni_cie; | ||
759 | |||
760 | #define CHAN_IS_11A(x) (!((x >= 2412) && (x <= 2484))) | ||
761 | if(CHAN_IS_11A(cie->ie_chan)) { | ||
762 | /* 11a */ | ||
763 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; | ||
764 | } else if((cie->ie_erp) || (cie->ie_xrates)) { | ||
765 | /* 11g */ | ||
766 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
767 | } else { | ||
768 | /* 11b */ | ||
769 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
770 | } | ||
771 | |||
772 | size = ni->ni_framelen + offsetof(struct ieee80211_mgmt, u); | ||
773 | ieeemgmtbuf = A_MALLOC_NOWAIT(size); | ||
774 | if(!ieeemgmtbuf) | ||
775 | { | ||
776 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ieeeMgmtbuf alloc error\n", __func__)); | ||
777 | return; | ||
778 | } | ||
779 | |||
780 | /* Note: | ||
781 | TODO: Update target to include 802.11 mac header while sending bss info. | ||
782 | Target removes 802.11 mac header while sending the bss info to host, | ||
783 | cfg80211 needs it, for time being just filling the da, sa and bssid fields alone. | ||
784 | */ | ||
785 | mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf; | ||
786 | memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN); | ||
787 | memcpy(mgmt->sa, ni->ni_macaddr, ATH_MAC_LEN); | ||
788 | memcpy(mgmt->bssid, ni->ni_macaddr, ATH_MAC_LEN); | ||
789 | memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u), | ||
790 | ni->ni_buf, ni->ni_framelen); | ||
791 | |||
792 | freq = cie->ie_chan; | ||
793 | channel = ieee80211_get_channel(wiphy, freq); | ||
794 | signal = ni->ni_snr * 100; | ||
795 | |||
796 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
797 | ("%s: bssid %pM channel %d freq %d size %d\n", __func__, | ||
798 | mgmt->bssid, channel->hw_value, freq, size)); | ||
799 | cfg80211_inform_bss_frame(wiphy, channel, mgmt, | ||
800 | le16_to_cpu(size), | ||
801 | signal, GFP_KERNEL); | ||
802 | |||
803 | kfree (ieeemgmtbuf); | ||
804 | } | ||
805 | |||
806 | static int | ||
807 | ar6k_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | ||
808 | struct cfg80211_scan_request *request) | ||
809 | { | ||
810 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); | ||
811 | int ret = 0; | ||
812 | u32 forceFgScan = 0; | ||
813 | |||
814 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); | ||
815 | |||
816 | if(ar->arWmiReady == false) { | ||
817 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
818 | return -EIO; | ||
819 | } | ||
820 | |||
821 | if(ar->arWlanState == WLAN_DISABLED) { | ||
822 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
823 | return -EIO; | ||
824 | } | ||
825 | |||
826 | if (!ar->arUserBssFilter) { | ||
827 | if (wmi_bssfilter_cmd(ar->arWmi, | ||
828 | (ar->arConnected ? ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), | ||
829 | 0) != 0) { | ||
830 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__)); | ||
831 | return -EIO; | ||
832 | } | ||
833 | } | ||
834 | |||
835 | if(request->n_ssids && | ||
836 | request->ssids[0].ssid_len) { | ||
837 | u8 i; | ||
838 | |||
839 | if(request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) { | ||
840 | request->n_ssids = MAX_PROBED_SSID_INDEX - 1; | ||
841 | } | ||
842 | |||
843 | for (i = 0; i < request->n_ssids; i++) { | ||
844 | wmi_probedSsid_cmd(ar->arWmi, i+1, SPECIFIC_SSID_FLAG, | ||
845 | request->ssids[i].ssid_len, | ||
846 | request->ssids[i].ssid); | ||
847 | } | ||
848 | } | ||
849 | |||
850 | if(ar->arConnected) { | ||
851 | forceFgScan = 1; | ||
852 | } | ||
853 | |||
854 | if(wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, forceFgScan, false, \ | ||
855 | 0, 0, 0, NULL) != 0) { | ||
856 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_startscan_cmd failed\n", __func__)); | ||
857 | ret = -EIO; | ||
858 | } | ||
859 | |||
860 | ar->scan_request = request; | ||
861 | |||
862 | return ret; | ||
863 | } | ||
864 | |||
865 | void | ||
866 | ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status) | ||
867 | { | ||
868 | |||
869 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: status %d\n", __func__, status)); | ||
870 | |||
871 | if (!ar->scan_request) | ||
872 | return; | ||
873 | |||
874 | if ((status == A_ECANCELED) || (status == A_EBUSY)) { | ||
875 | cfg80211_scan_done(ar->scan_request, true); | ||
876 | goto out; | ||
877 | } | ||
878 | |||
879 | /* Translate data to cfg80211 mgmt format */ | ||
880 | wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy); | ||
881 | |||
882 | cfg80211_scan_done(ar->scan_request, false); | ||
883 | |||
884 | if(ar->scan_request->n_ssids && | ||
885 | ar->scan_request->ssids[0].ssid_len) { | ||
886 | u8 i; | ||
887 | |||
888 | for (i = 0; i < ar->scan_request->n_ssids; i++) { | ||
889 | wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG, | ||
890 | 0, NULL); | ||
891 | } | ||
892 | } | ||
893 | |||
894 | out: | ||
895 | ar->scan_request = NULL; | ||
896 | } | ||
897 | |||
898 | static int | ||
899 | ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | ||
900 | u8 key_index, bool pairwise, const u8 *mac_addr, | ||
901 | struct key_params *params) | ||
902 | { | ||
903 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); | ||
904 | struct ar_key *key = NULL; | ||
905 | u8 key_usage; | ||
906 | u8 key_type; | ||
907 | int status = 0; | ||
908 | |||
909 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s:\n", __func__)); | ||
910 | |||
911 | if(ar->arWmiReady == false) { | ||
912 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
913 | return -EIO; | ||
914 | } | ||
915 | |||
916 | if(ar->arWlanState == WLAN_DISABLED) { | ||
917 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
918 | return -EIO; | ||
919 | } | ||
920 | |||
921 | if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { | ||
922 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
923 | ("%s: key index %d out of bounds\n", __func__, key_index)); | ||
924 | return -ENOENT; | ||
925 | } | ||
926 | |||
927 | key = &ar->keys[key_index]; | ||
928 | A_MEMZERO(key, sizeof(struct ar_key)); | ||
929 | |||
930 | if(!mac_addr || is_broadcast_ether_addr(mac_addr)) { | ||
931 | key_usage = GROUP_USAGE; | ||
932 | } else { | ||
933 | key_usage = PAIRWISE_USAGE; | ||
934 | } | ||
935 | |||
936 | if(params) { | ||
937 | if(params->key_len > WLAN_MAX_KEY_LEN || | ||
938 | params->seq_len > IW_ENCODE_SEQ_MAX_SIZE) | ||
939 | return -EINVAL; | ||
940 | |||
941 | key->key_len = params->key_len; | ||
942 | memcpy(key->key, params->key, key->key_len); | ||
943 | key->seq_len = params->seq_len; | ||
944 | memcpy(key->seq, params->seq, key->seq_len); | ||
945 | key->cipher = params->cipher; | ||
946 | } | ||
947 | |||
948 | switch (key->cipher) { | ||
949 | case WLAN_CIPHER_SUITE_WEP40: | ||
950 | case WLAN_CIPHER_SUITE_WEP104: | ||
951 | key_type = WEP_CRYPT; | ||
952 | break; | ||
953 | |||
954 | case WLAN_CIPHER_SUITE_TKIP: | ||
955 | key_type = TKIP_CRYPT; | ||
956 | break; | ||
957 | |||
958 | case WLAN_CIPHER_SUITE_CCMP: | ||
959 | key_type = AES_CRYPT; | ||
960 | break; | ||
961 | |||
962 | default: | ||
963 | return -ENOTSUPP; | ||
964 | } | ||
965 | |||
966 | if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) && | ||
967 | (GROUP_USAGE & key_usage)) | ||
968 | { | ||
969 | A_UNTIMEOUT(&ar->disconnect_timer); | ||
970 | } | ||
971 | |||
972 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
973 | ("%s: index %d, key_len %d, key_type 0x%x,"\ | ||
974 | " key_usage 0x%x, seq_len %d\n", | ||
975 | __func__, key_index, key->key_len, key_type, | ||
976 | key_usage, key->seq_len)); | ||
977 | |||
978 | ar->arDefTxKeyIndex = key_index; | ||
979 | status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, key_type, key_usage, | ||
980 | key->key_len, key->seq, key->key, KEY_OP_INIT_VAL, | ||
981 | (u8 *)mac_addr, SYNC_BOTH_WMIFLAG); | ||
982 | |||
983 | |||
984 | if (status) { | ||
985 | return -EIO; | ||
986 | } | ||
987 | |||
988 | return 0; | ||
989 | } | ||
990 | |||
991 | static int | ||
992 | ar6k_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | ||
993 | u8 key_index, bool pairwise, const u8 *mac_addr) | ||
994 | { | ||
995 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); | ||
996 | |||
997 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); | ||
998 | |||
999 | if(ar->arWmiReady == false) { | ||
1000 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1001 | return -EIO; | ||
1002 | } | ||
1003 | |||
1004 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1005 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1006 | return -EIO; | ||
1007 | } | ||
1008 | |||
1009 | if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { | ||
1010 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
1011 | ("%s: key index %d out of bounds\n", __func__, key_index)); | ||
1012 | return -ENOENT; | ||
1013 | } | ||
1014 | |||
1015 | if(!ar->keys[key_index].key_len) { | ||
1016 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d is empty\n", __func__, key_index)); | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | ar->keys[key_index].key_len = 0; | ||
1021 | |||
1022 | return wmi_deleteKey_cmd(ar->arWmi, key_index); | ||
1023 | } | ||
1024 | |||
1025 | |||
1026 | static int | ||
1027 | ar6k_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | ||
1028 | u8 key_index, bool pairwise, const u8 *mac_addr, | ||
1029 | void *cookie, | ||
1030 | void (*callback)(void *cookie, struct key_params*)) | ||
1031 | { | ||
1032 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); | ||
1033 | struct ar_key *key = NULL; | ||
1034 | struct key_params params; | ||
1035 | |||
1036 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); | ||
1037 | |||
1038 | if(ar->arWmiReady == false) { | ||
1039 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1040 | return -EIO; | ||
1041 | } | ||
1042 | |||
1043 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1044 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1045 | return -EIO; | ||
1046 | } | ||
1047 | |||
1048 | if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { | ||
1049 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
1050 | ("%s: key index %d out of bounds\n", __func__, key_index)); | ||
1051 | return -ENOENT; | ||
1052 | } | ||
1053 | |||
1054 | key = &ar->keys[key_index]; | ||
1055 | A_MEMZERO(¶ms, sizeof(params)); | ||
1056 | params.cipher = key->cipher; | ||
1057 | params.key_len = key->key_len; | ||
1058 | params.seq_len = key->seq_len; | ||
1059 | params.seq = key->seq; | ||
1060 | params.key = key->key; | ||
1061 | |||
1062 | callback(cookie, ¶ms); | ||
1063 | |||
1064 | return key->key_len ? 0 : -ENOENT; | ||
1065 | } | ||
1066 | |||
1067 | |||
1068 | static int | ||
1069 | ar6k_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, | ||
1070 | u8 key_index, bool unicast, bool multicast) | ||
1071 | { | ||
1072 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); | ||
1073 | struct ar_key *key = NULL; | ||
1074 | int status = 0; | ||
1075 | u8 key_usage; | ||
1076 | |||
1077 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); | ||
1078 | |||
1079 | if(ar->arWmiReady == false) { | ||
1080 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1081 | return -EIO; | ||
1082 | } | ||
1083 | |||
1084 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1085 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1086 | return -EIO; | ||
1087 | } | ||
1088 | |||
1089 | if(key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { | ||
1090 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
1091 | ("%s: key index %d out of bounds\n", | ||
1092 | __func__, key_index)); | ||
1093 | return -ENOENT; | ||
1094 | } | ||
1095 | |||
1096 | if(!ar->keys[key_index].key_len) { | ||
1097 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: invalid key index %d\n", | ||
1098 | __func__, key_index)); | ||
1099 | return -EINVAL; | ||
1100 | } | ||
1101 | |||
1102 | ar->arDefTxKeyIndex = key_index; | ||
1103 | key = &ar->keys[ar->arDefTxKeyIndex]; | ||
1104 | key_usage = GROUP_USAGE; | ||
1105 | if (WEP_CRYPT == ar->arPairwiseCrypto) { | ||
1106 | key_usage |= TX_USAGE; | ||
1107 | } | ||
1108 | |||
1109 | status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, | ||
1110 | ar->arPairwiseCrypto, key_usage, | ||
1111 | key->key_len, key->seq, key->key, KEY_OP_INIT_VAL, | ||
1112 | NULL, SYNC_BOTH_WMIFLAG); | ||
1113 | if (status) { | ||
1114 | return -EIO; | ||
1115 | } | ||
1116 | |||
1117 | return 0; | ||
1118 | } | ||
1119 | |||
1120 | static int | ||
1121 | ar6k_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *ndev, | ||
1122 | u8 key_index) | ||
1123 | { | ||
1124 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev); | ||
1125 | |||
1126 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index)); | ||
1127 | |||
1128 | if(ar->arWmiReady == false) { | ||
1129 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1130 | return -EIO; | ||
1131 | } | ||
1132 | |||
1133 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1134 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1135 | return -EIO; | ||
1136 | } | ||
1137 | |||
1138 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__)); | ||
1139 | return -ENOTSUPP; | ||
1140 | } | ||
1141 | |||
1142 | void | ||
1143 | ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast) | ||
1144 | { | ||
1145 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | ||
1146 | ("%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast)); | ||
1147 | |||
1148 | cfg80211_michael_mic_failure(ar->arNetDev, ar->arBssid, | ||
1149 | (ismcast ? NL80211_KEYTYPE_GROUP : NL80211_KEYTYPE_PAIRWISE), | ||
1150 | keyid, NULL, GFP_KERNEL); | ||
1151 | } | ||
1152 | |||
1153 | static int | ||
1154 | ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | ||
1155 | { | ||
1156 | struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy); | ||
1157 | |||
1158 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: changed 0x%x\n", __func__, changed)); | ||
1159 | |||
1160 | if(ar->arWmiReady == false) { | ||
1161 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1162 | return -EIO; | ||
1163 | } | ||
1164 | |||
1165 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1166 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1167 | return -EIO; | ||
1168 | } | ||
1169 | |||
1170 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | ||
1171 | if (wmi_set_rts_cmd(ar->arWmi,wiphy->rts_threshold) != 0){ | ||
1172 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_set_rts_cmd failed\n", __func__)); | ||
1173 | return -EIO; | ||
1174 | } | ||
1175 | } | ||
1176 | |||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | static int | ||
1181 | ar6k_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, | ||
1182 | const u8 *peer, | ||
1183 | const struct cfg80211_bitrate_mask *mask) | ||
1184 | { | ||
1185 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Setting rates: Not supported\n")); | ||
1186 | return -EIO; | ||
1187 | } | ||
1188 | |||
1189 | /* The type nl80211_tx_power_setting replaces the following data type from 2.6.36 onwards */ | ||
1190 | static int | ||
1191 | ar6k_cfg80211_set_txpower(struct wiphy *wiphy, enum nl80211_tx_power_setting type, int dbm) | ||
1192 | { | ||
1193 | struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy); | ||
1194 | u8 ar_dbm; | ||
1195 | |||
1196 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x, dbm %d\n", __func__, type, dbm)); | ||
1197 | |||
1198 | if(ar->arWmiReady == false) { | ||
1199 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1200 | return -EIO; | ||
1201 | } | ||
1202 | |||
1203 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1204 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1205 | return -EIO; | ||
1206 | } | ||
1207 | |||
1208 | ar->arTxPwrSet = false; | ||
1209 | switch(type) { | ||
1210 | case NL80211_TX_POWER_AUTOMATIC: | ||
1211 | return 0; | ||
1212 | case NL80211_TX_POWER_LIMITED: | ||
1213 | ar->arTxPwr = ar_dbm = dbm; | ||
1214 | ar->arTxPwrSet = true; | ||
1215 | break; | ||
1216 | default: | ||
1217 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x not supported\n", __func__, type)); | ||
1218 | return -EOPNOTSUPP; | ||
1219 | } | ||
1220 | |||
1221 | wmi_set_txPwr_cmd(ar->arWmi, ar_dbm); | ||
1222 | |||
1223 | return 0; | ||
1224 | } | ||
1225 | |||
1226 | static int | ||
1227 | ar6k_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) | ||
1228 | { | ||
1229 | struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy); | ||
1230 | |||
1231 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); | ||
1232 | |||
1233 | if(ar->arWmiReady == false) { | ||
1234 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1235 | return -EIO; | ||
1236 | } | ||
1237 | |||
1238 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1239 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1240 | return -EIO; | ||
1241 | } | ||
1242 | |||
1243 | if((ar->arConnected == true)) { | ||
1244 | ar->arTxPwr = 0; | ||
1245 | |||
1246 | if(wmi_get_txPwr_cmd(ar->arWmi) != 0) { | ||
1247 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_get_txPwr_cmd failed\n", __func__)); | ||
1248 | return -EIO; | ||
1249 | } | ||
1250 | |||
1251 | wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, 5 * HZ); | ||
1252 | |||
1253 | if(signal_pending(current)) { | ||
1254 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Target did not respond\n", __func__)); | ||
1255 | return -EINTR; | ||
1256 | } | ||
1257 | } | ||
1258 | |||
1259 | *dbm = ar->arTxPwr; | ||
1260 | return 0; | ||
1261 | } | ||
1262 | |||
1263 | static int | ||
1264 | ar6k_cfg80211_set_power_mgmt(struct wiphy *wiphy, | ||
1265 | struct net_device *dev, | ||
1266 | bool pmgmt, int timeout) | ||
1267 | { | ||
1268 | struct ar6_softc *ar = ar6k_priv(dev); | ||
1269 | WMI_POWER_MODE_CMD pwrMode; | ||
1270 | |||
1271 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: pmgmt %d, timeout %d\n", __func__, pmgmt, timeout)); | ||
1272 | |||
1273 | if(ar->arWmiReady == false) { | ||
1274 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1275 | return -EIO; | ||
1276 | } | ||
1277 | |||
1278 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1279 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1280 | return -EIO; | ||
1281 | } | ||
1282 | |||
1283 | if(pmgmt) { | ||
1284 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Max Perf\n", __func__)); | ||
1285 | pwrMode.powerMode = REC_POWER; | ||
1286 | } else { | ||
1287 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Rec Power\n", __func__)); | ||
1288 | pwrMode.powerMode = MAX_PERF_POWER; | ||
1289 | } | ||
1290 | |||
1291 | if(wmi_powermode_cmd(ar->arWmi, pwrMode.powerMode) != 0) { | ||
1292 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_powermode_cmd failed\n", __func__)); | ||
1293 | return -EIO; | ||
1294 | } | ||
1295 | |||
1296 | return 0; | ||
1297 | } | ||
1298 | |||
1299 | static struct net_device * | ||
1300 | ar6k_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name, | ||
1301 | enum nl80211_iftype type, u32 *flags, | ||
1302 | struct vif_params *params) | ||
1303 | { | ||
1304 | |||
1305 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__)); | ||
1306 | |||
1307 | /* Multiple virtual interface is not supported. | ||
1308 | * The default interface supports STA and IBSS type | ||
1309 | */ | ||
1310 | return ERR_PTR(-EOPNOTSUPP); | ||
1311 | } | ||
1312 | |||
1313 | static int | ||
1314 | ar6k_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) | ||
1315 | { | ||
1316 | |||
1317 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: not supported\n", __func__)); | ||
1318 | |||
1319 | /* Multiple virtual interface is not supported. | ||
1320 | * The default interface supports STA and IBSS type | ||
1321 | */ | ||
1322 | return -EOPNOTSUPP; | ||
1323 | } | ||
1324 | |||
1325 | static int | ||
1326 | ar6k_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | ||
1327 | enum nl80211_iftype type, u32 *flags, | ||
1328 | struct vif_params *params) | ||
1329 | { | ||
1330 | struct ar6_softc *ar = ar6k_priv(ndev); | ||
1331 | struct wireless_dev *wdev = ar->wdev; | ||
1332 | |||
1333 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type %u\n", __func__, type)); | ||
1334 | |||
1335 | if(ar->arWmiReady == false) { | ||
1336 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1337 | return -EIO; | ||
1338 | } | ||
1339 | |||
1340 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1341 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1342 | return -EIO; | ||
1343 | } | ||
1344 | |||
1345 | switch (type) { | ||
1346 | case NL80211_IFTYPE_STATION: | ||
1347 | ar->arNextMode = INFRA_NETWORK; | ||
1348 | break; | ||
1349 | case NL80211_IFTYPE_ADHOC: | ||
1350 | ar->arNextMode = ADHOC_NETWORK; | ||
1351 | break; | ||
1352 | default: | ||
1353 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: type %u\n", __func__, type)); | ||
1354 | return -EOPNOTSUPP; | ||
1355 | } | ||
1356 | |||
1357 | wdev->iftype = type; | ||
1358 | |||
1359 | return 0; | ||
1360 | } | ||
1361 | |||
1362 | static int | ||
1363 | ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | ||
1364 | struct cfg80211_ibss_params *ibss_param) | ||
1365 | { | ||
1366 | struct ar6_softc *ar = ar6k_priv(dev); | ||
1367 | int status; | ||
1368 | |||
1369 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); | ||
1370 | |||
1371 | if(ar->arWmiReady == false) { | ||
1372 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1373 | return -EIO; | ||
1374 | } | ||
1375 | |||
1376 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1377 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1378 | return -EIO; | ||
1379 | } | ||
1380 | |||
1381 | if(!ibss_param->ssid_len || IEEE80211_MAX_SSID_LEN < ibss_param->ssid_len) { | ||
1382 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ssid invalid\n", __func__)); | ||
1383 | return -EINVAL; | ||
1384 | } | ||
1385 | |||
1386 | ar->arSsidLen = ibss_param->ssid_len; | ||
1387 | memcpy(ar->arSsid, ibss_param->ssid, ar->arSsidLen); | ||
1388 | |||
1389 | if(ibss_param->channel) { | ||
1390 | ar->arChannelHint = ibss_param->channel->center_freq; | ||
1391 | } | ||
1392 | |||
1393 | if(ibss_param->channel_fixed) { | ||
1394 | /* TODO: channel_fixed: The channel should be fixed, do not search for | ||
1395 | * IBSSs to join on other channels. Target firmware does not support this | ||
1396 | * feature, needs to be updated.*/ | ||
1397 | } | ||
1398 | |||
1399 | A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); | ||
1400 | if(ibss_param->bssid) { | ||
1401 | if(memcmp(&ibss_param->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) { | ||
1402 | memcpy(ar->arReqBssid, ibss_param->bssid, sizeof(ar->arReqBssid)); | ||
1403 | } | ||
1404 | } | ||
1405 | |||
1406 | ar6k_set_wpa_version(ar, 0); | ||
1407 | ar6k_set_auth_type(ar, NL80211_AUTHTYPE_OPEN_SYSTEM); | ||
1408 | |||
1409 | if(ibss_param->privacy) { | ||
1410 | ar6k_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, true); | ||
1411 | ar6k_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, false); | ||
1412 | } else { | ||
1413 | ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, true); | ||
1414 | ar6k_set_cipher(ar, IW_AUTH_CIPHER_NONE, false); | ||
1415 | } | ||
1416 | |||
1417 | ar->arNetworkType = ar->arNextMode; | ||
1418 | |||
1419 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: Connect called with authmode %d dot11 auth %d"\ | ||
1420 | " PW crypto %d PW crypto Len %d GRP crypto %d"\ | ||
1421 | " GRP crypto Len %d channel hint %u\n", | ||
1422 | __func__, ar->arAuthMode, ar->arDot11AuthMode, | ||
1423 | ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, | ||
1424 | ar->arGroupCrypto, ar->arGroupCryptoLen, ar->arChannelHint)); | ||
1425 | |||
1426 | status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, | ||
1427 | ar->arDot11AuthMode, ar->arAuthMode, | ||
1428 | ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, | ||
1429 | ar->arGroupCrypto,ar->arGroupCryptoLen, | ||
1430 | ar->arSsidLen, ar->arSsid, | ||
1431 | ar->arReqBssid, ar->arChannelHint, | ||
1432 | ar->arConnectCtrlFlags); | ||
1433 | ar->arConnectPending = true; | ||
1434 | |||
1435 | return 0; | ||
1436 | } | ||
1437 | |||
1438 | static int | ||
1439 | ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | ||
1440 | { | ||
1441 | struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev); | ||
1442 | |||
1443 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); | ||
1444 | |||
1445 | if(ar->arWmiReady == false) { | ||
1446 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__)); | ||
1447 | return -EIO; | ||
1448 | } | ||
1449 | |||
1450 | if(ar->arWlanState == WLAN_DISABLED) { | ||
1451 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wlan disabled\n", __func__)); | ||
1452 | return -EIO; | ||
1453 | } | ||
1454 | |||
1455 | ar6000_disconnect(ar); | ||
1456 | A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); | ||
1457 | ar->arSsidLen = 0; | ||
1458 | |||
1459 | return 0; | ||
1460 | } | ||
1461 | |||
1462 | #ifdef CONFIG_NL80211_TESTMODE | ||
1463 | enum ar6k_testmode_attr { | ||
1464 | __AR6K_TM_ATTR_INVALID = 0, | ||
1465 | AR6K_TM_ATTR_CMD = 1, | ||
1466 | AR6K_TM_ATTR_DATA = 2, | ||
1467 | |||
1468 | /* keep last */ | ||
1469 | __AR6K_TM_ATTR_AFTER_LAST, | ||
1470 | AR6K_TM_ATTR_MAX = __AR6K_TM_ATTR_AFTER_LAST - 1 | ||
1471 | }; | ||
1472 | |||
1473 | enum ar6k_testmode_cmd { | ||
1474 | AR6K_TM_CMD_TCMD = 0, | ||
1475 | AR6K_TM_CMD_RX_REPORT = 1, | ||
1476 | }; | ||
1477 | |||
1478 | #define AR6K_TM_DATA_MAX_LEN 5000 | ||
1479 | |||
1480 | static const struct nla_policy ar6k_testmode_policy[AR6K_TM_ATTR_MAX + 1] = { | ||
1481 | [AR6K_TM_ATTR_CMD] = { .type = NLA_U32 }, | ||
1482 | [AR6K_TM_ATTR_DATA] = { .type = NLA_BINARY, | ||
1483 | .len = AR6K_TM_DATA_MAX_LEN }, | ||
1484 | }; | ||
1485 | |||
1486 | void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf, | ||
1487 | int buf_len) | ||
1488 | { | ||
1489 | if (down_interruptible(&ar->arSem)) | ||
1490 | return; | ||
1491 | |||
1492 | kfree(ar->tcmd_rx_report); | ||
1493 | |||
1494 | ar->tcmd_rx_report = kmemdup(buf, buf_len, GFP_KERNEL); | ||
1495 | ar->tcmd_rx_report_len = buf_len; | ||
1496 | |||
1497 | up(&ar->arSem); | ||
1498 | |||
1499 | wake_up(&arEvent); | ||
1500 | } | ||
1501 | |||
1502 | static int ar6000_testmode_rx_report(struct ar6_softc *ar, void *buf, | ||
1503 | int buf_len, struct sk_buff *skb) | ||
1504 | { | ||
1505 | int ret = 0; | ||
1506 | long left; | ||
1507 | |||
1508 | if (down_interruptible(&ar->arSem)) | ||
1509 | return -ERESTARTSYS; | ||
1510 | |||
1511 | if (ar->arWmiReady == false) { | ||
1512 | ret = -EIO; | ||
1513 | goto out; | ||
1514 | } | ||
1515 | |||
1516 | if (ar->bIsDestroyProgress) { | ||
1517 | ret = -EBUSY; | ||
1518 | goto out; | ||
1519 | } | ||
1520 | |||
1521 | WARN_ON(ar->tcmd_rx_report != NULL); | ||
1522 | WARN_ON(ar->tcmd_rx_report_len > 0); | ||
1523 | |||
1524 | if (wmi_test_cmd(ar->arWmi, buf, buf_len) < 0) { | ||
1525 | up(&ar->arSem); | ||
1526 | return -EIO; | ||
1527 | } | ||
1528 | |||
1529 | left = wait_event_interruptible_timeout(arEvent, | ||
1530 | ar->tcmd_rx_report != NULL, | ||
1531 | wmitimeout * HZ); | ||
1532 | |||
1533 | if (left == 0) { | ||
1534 | ret = -ETIMEDOUT; | ||
1535 | goto out; | ||
1536 | } else if (left < 0) { | ||
1537 | ret = left; | ||
1538 | goto out; | ||
1539 | } | ||
1540 | |||
1541 | if (ar->tcmd_rx_report == NULL || ar->tcmd_rx_report_len == 0) { | ||
1542 | ret = -EINVAL; | ||
1543 | goto out; | ||
1544 | } | ||
1545 | |||
1546 | NLA_PUT(skb, AR6K_TM_ATTR_DATA, ar->tcmd_rx_report_len, | ||
1547 | ar->tcmd_rx_report); | ||
1548 | |||
1549 | kfree(ar->tcmd_rx_report); | ||
1550 | ar->tcmd_rx_report = NULL; | ||
1551 | |||
1552 | out: | ||
1553 | up(&ar->arSem); | ||
1554 | |||
1555 | return ret; | ||
1556 | |||
1557 | nla_put_failure: | ||
1558 | ret = -ENOBUFS; | ||
1559 | goto out; | ||
1560 | } | ||
1561 | |||
1562 | static int ar6k_testmode_cmd(struct wiphy *wiphy, void *data, int len) | ||
1563 | { | ||
1564 | struct ar6_softc *ar = wiphy_priv(wiphy); | ||
1565 | struct nlattr *tb[AR6K_TM_ATTR_MAX + 1]; | ||
1566 | int err, buf_len, reply_len; | ||
1567 | struct sk_buff *skb; | ||
1568 | void *buf; | ||
1569 | |||
1570 | err = nla_parse(tb, AR6K_TM_ATTR_MAX, data, len, | ||
1571 | ar6k_testmode_policy); | ||
1572 | if (err) | ||
1573 | return err; | ||
1574 | |||
1575 | if (!tb[AR6K_TM_ATTR_CMD]) | ||
1576 | return -EINVAL; | ||
1577 | |||
1578 | switch (nla_get_u32(tb[AR6K_TM_ATTR_CMD])) { | ||
1579 | case AR6K_TM_CMD_TCMD: | ||
1580 | if (!tb[AR6K_TM_ATTR_DATA]) | ||
1581 | return -EINVAL; | ||
1582 | |||
1583 | buf = nla_data(tb[AR6K_TM_ATTR_DATA]); | ||
1584 | buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]); | ||
1585 | |||
1586 | wmi_test_cmd(ar->arWmi, buf, buf_len); | ||
1587 | |||
1588 | return 0; | ||
1589 | |||
1590 | break; | ||
1591 | case AR6K_TM_CMD_RX_REPORT: | ||
1592 | if (!tb[AR6K_TM_ATTR_DATA]) | ||
1593 | return -EINVAL; | ||
1594 | |||
1595 | buf = nla_data(tb[AR6K_TM_ATTR_DATA]); | ||
1596 | buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]); | ||
1597 | |||
1598 | reply_len = nla_total_size(AR6K_TM_DATA_MAX_LEN); | ||
1599 | skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); | ||
1600 | if (!skb) | ||
1601 | return -ENOMEM; | ||
1602 | |||
1603 | err = ar6000_testmode_rx_report(ar, buf, buf_len, skb); | ||
1604 | if (err < 0) { | ||
1605 | kfree_skb(skb); | ||
1606 | return err; | ||
1607 | } | ||
1608 | |||
1609 | return cfg80211_testmode_reply(skb); | ||
1610 | default: | ||
1611 | return -EOPNOTSUPP; | ||
1612 | } | ||
1613 | } | ||
1614 | #endif | ||
1615 | |||
1616 | static const | ||
1617 | u32 cipher_suites[] = { | ||
1618 | WLAN_CIPHER_SUITE_WEP40, | ||
1619 | WLAN_CIPHER_SUITE_WEP104, | ||
1620 | WLAN_CIPHER_SUITE_TKIP, | ||
1621 | WLAN_CIPHER_SUITE_CCMP, | ||
1622 | }; | ||
1623 | |||
1624 | bool is_rate_legacy(s32 rate) | ||
1625 | { | ||
1626 | static const s32 legacy[] = { 1000, 2000, 5500, 11000, | ||
1627 | 6000, 9000, 12000, 18000, 24000, | ||
1628 | 36000, 48000, 54000 }; | ||
1629 | u8 i; | ||
1630 | |||
1631 | for (i = 0; i < ARRAY_SIZE(legacy); i++) { | ||
1632 | if (rate == legacy[i]) | ||
1633 | return true; | ||
1634 | } | ||
1635 | |||
1636 | return false; | ||
1637 | } | ||
1638 | |||
1639 | bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi) | ||
1640 | { | ||
1641 | static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000, | ||
1642 | 52000, 58500, 65000, 72200 }; | ||
1643 | u8 i; | ||
1644 | |||
1645 | for (i = 0; i < ARRAY_SIZE(ht20); i++) { | ||
1646 | if (rate == ht20[i]) { | ||
1647 | if (i == ARRAY_SIZE(ht20) - 1) | ||
1648 | /* last rate uses sgi */ | ||
1649 | *sgi = true; | ||
1650 | else | ||
1651 | *sgi = false; | ||
1652 | |||
1653 | *mcs = i; | ||
1654 | return true; | ||
1655 | } | ||
1656 | } | ||
1657 | return false; | ||
1658 | } | ||
1659 | |||
1660 | bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi) | ||
1661 | { | ||
1662 | static const s32 ht40[] = { 13500, 27000, 40500, 54000, | ||
1663 | 81000, 108000, 121500, 135000, | ||
1664 | 150000 }; | ||
1665 | u8 i; | ||
1666 | |||
1667 | for (i = 0; i < ARRAY_SIZE(ht40); i++) { | ||
1668 | if (rate == ht40[i]) { | ||
1669 | if (i == ARRAY_SIZE(ht40) - 1) | ||
1670 | /* last rate uses sgi */ | ||
1671 | *sgi = true; | ||
1672 | else | ||
1673 | *sgi = false; | ||
1674 | |||
1675 | *mcs = i; | ||
1676 | return true; | ||
1677 | } | ||
1678 | } | ||
1679 | |||
1680 | return false; | ||
1681 | } | ||
1682 | |||
1683 | static int ar6k_get_station(struct wiphy *wiphy, struct net_device *dev, | ||
1684 | u8 *mac, struct station_info *sinfo) | ||
1685 | { | ||
1686 | struct ar6_softc *ar = ar6k_priv(dev); | ||
1687 | long left; | ||
1688 | bool sgi; | ||
1689 | s32 rate; | ||
1690 | int ret; | ||
1691 | u8 mcs; | ||
1692 | |||
1693 | if (memcmp(mac, ar->arBssid, ETH_ALEN) != 0) | ||
1694 | return -ENOENT; | ||
1695 | |||
1696 | if (down_interruptible(&ar->arSem)) | ||
1697 | return -EBUSY; | ||
1698 | |||
1699 | ar->statsUpdatePending = true; | ||
1700 | |||
1701 | ret = wmi_get_stats_cmd(ar->arWmi); | ||
1702 | |||
1703 | if (ret != 0) { | ||
1704 | up(&ar->arSem); | ||
1705 | return -EIO; | ||
1706 | } | ||
1707 | |||
1708 | left = wait_event_interruptible_timeout(arEvent, | ||
1709 | ar->statsUpdatePending == false, | ||
1710 | wmitimeout * HZ); | ||
1711 | |||
1712 | up(&ar->arSem); | ||
1713 | |||
1714 | if (left == 0) | ||
1715 | return -ETIMEDOUT; | ||
1716 | else if (left < 0) | ||
1717 | return left; | ||
1718 | |||
1719 | if (ar->arTargetStats.rx_bytes) { | ||
1720 | sinfo->rx_bytes = ar->arTargetStats.rx_bytes; | ||
1721 | sinfo->filled |= STATION_INFO_RX_BYTES; | ||
1722 | sinfo->rx_packets = ar->arTargetStats.rx_packets; | ||
1723 | sinfo->filled |= STATION_INFO_RX_PACKETS; | ||
1724 | } | ||
1725 | |||
1726 | if (ar->arTargetStats.tx_bytes) { | ||
1727 | sinfo->tx_bytes = ar->arTargetStats.tx_bytes; | ||
1728 | sinfo->filled |= STATION_INFO_TX_BYTES; | ||
1729 | sinfo->tx_packets = ar->arTargetStats.tx_packets; | ||
1730 | sinfo->filled |= STATION_INFO_TX_PACKETS; | ||
1731 | } | ||
1732 | |||
1733 | sinfo->signal = ar->arTargetStats.cs_rssi; | ||
1734 | sinfo->filled |= STATION_INFO_SIGNAL; | ||
1735 | |||
1736 | rate = ar->arTargetStats.tx_unicast_rate; | ||
1737 | |||
1738 | if (is_rate_legacy(rate)) { | ||
1739 | sinfo->txrate.legacy = rate / 100; | ||
1740 | } else if (is_rate_ht20(rate, &mcs, &sgi)) { | ||
1741 | if (sgi) { | ||
1742 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
1743 | sinfo->txrate.mcs = mcs - 1; | ||
1744 | } else { | ||
1745 | sinfo->txrate.mcs = mcs; | ||
1746 | } | ||
1747 | |||
1748 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | ||
1749 | } else if (is_rate_ht40(rate, &mcs, &sgi)) { | ||
1750 | if (sgi) { | ||
1751 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
1752 | sinfo->txrate.mcs = mcs - 1; | ||
1753 | } else { | ||
1754 | sinfo->txrate.mcs = mcs; | ||
1755 | } | ||
1756 | |||
1757 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
1758 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | ||
1759 | } else { | ||
1760 | WARN(1, "invalid rate: %d", rate); | ||
1761 | return 0; | ||
1762 | } | ||
1763 | |||
1764 | sinfo->filled |= STATION_INFO_TX_BITRATE; | ||
1765 | |||
1766 | return 0; | ||
1767 | } | ||
1768 | |||
1769 | static int ar6k_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, | ||
1770 | struct cfg80211_pmksa *pmksa) | ||
1771 | { | ||
1772 | struct ar6_softc *ar = ar6k_priv(netdev); | ||
1773 | return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, true); | ||
1774 | } | ||
1775 | |||
1776 | static int ar6k_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, | ||
1777 | struct cfg80211_pmksa *pmksa) | ||
1778 | { | ||
1779 | struct ar6_softc *ar = ar6k_priv(netdev); | ||
1780 | return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, false); | ||
1781 | } | ||
1782 | |||
1783 | static int ar6k_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) | ||
1784 | { | ||
1785 | struct ar6_softc *ar = ar6k_priv(netdev); | ||
1786 | if (ar->arConnected) | ||
1787 | return wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, false); | ||
1788 | return 0; | ||
1789 | } | ||
1790 | |||
1791 | static struct | ||
1792 | cfg80211_ops ar6k_cfg80211_ops = { | ||
1793 | .change_virtual_intf = ar6k_cfg80211_change_iface, | ||
1794 | .add_virtual_intf = ar6k_cfg80211_add_virtual_intf, | ||
1795 | .del_virtual_intf = ar6k_cfg80211_del_virtual_intf, | ||
1796 | .scan = ar6k_cfg80211_scan, | ||
1797 | .connect = ar6k_cfg80211_connect, | ||
1798 | .disconnect = ar6k_cfg80211_disconnect, | ||
1799 | .add_key = ar6k_cfg80211_add_key, | ||
1800 | .get_key = ar6k_cfg80211_get_key, | ||
1801 | .del_key = ar6k_cfg80211_del_key, | ||
1802 | .set_default_key = ar6k_cfg80211_set_default_key, | ||
1803 | .set_default_mgmt_key = ar6k_cfg80211_set_default_mgmt_key, | ||
1804 | .set_wiphy_params = ar6k_cfg80211_set_wiphy_params, | ||
1805 | .set_bitrate_mask = ar6k_cfg80211_set_bitrate_mask, | ||
1806 | .set_tx_power = ar6k_cfg80211_set_txpower, | ||
1807 | .get_tx_power = ar6k_cfg80211_get_txpower, | ||
1808 | .set_power_mgmt = ar6k_cfg80211_set_power_mgmt, | ||
1809 | .join_ibss = ar6k_cfg80211_join_ibss, | ||
1810 | .leave_ibss = ar6k_cfg80211_leave_ibss, | ||
1811 | .get_station = ar6k_get_station, | ||
1812 | .set_pmksa = ar6k_set_pmksa, | ||
1813 | .del_pmksa = ar6k_del_pmksa, | ||
1814 | .flush_pmksa = ar6k_flush_pmksa, | ||
1815 | CFG80211_TESTMODE_CMD(ar6k_testmode_cmd) | ||
1816 | }; | ||
1817 | |||
1818 | struct wireless_dev * | ||
1819 | ar6k_cfg80211_init(struct device *dev) | ||
1820 | { | ||
1821 | int ret = 0; | ||
1822 | struct wireless_dev *wdev; | ||
1823 | |||
1824 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); | ||
1825 | |||
1826 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
1827 | if(!wdev) { | ||
1828 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
1829 | ("%s: Couldn't allocate wireless device\n", __func__)); | ||
1830 | return ERR_PTR(-ENOMEM); | ||
1831 | } | ||
1832 | |||
1833 | /* create a new wiphy for use with cfg80211 */ | ||
1834 | wdev->wiphy = wiphy_new(&ar6k_cfg80211_ops, sizeof(struct ar6_softc)); | ||
1835 | if(!wdev->wiphy) { | ||
1836 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
1837 | ("%s: Couldn't allocate wiphy device\n", __func__)); | ||
1838 | kfree(wdev); | ||
1839 | return ERR_PTR(-ENOMEM); | ||
1840 | } | ||
1841 | |||
1842 | /* set device pointer for wiphy */ | ||
1843 | set_wiphy_dev(wdev->wiphy, dev); | ||
1844 | |||
1845 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
1846 | BIT(NL80211_IFTYPE_ADHOC); | ||
1847 | /* max num of ssids that can be probed during scanning */ | ||
1848 | wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; | ||
1849 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar6k_band_2ghz; | ||
1850 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar6k_band_5ghz; | ||
1851 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
1852 | |||
1853 | wdev->wiphy->cipher_suites = cipher_suites; | ||
1854 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
1855 | |||
1856 | ret = wiphy_register(wdev->wiphy); | ||
1857 | if(ret < 0) { | ||
1858 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | ||
1859 | ("%s: Couldn't register wiphy device\n", __func__)); | ||
1860 | wiphy_free(wdev->wiphy); | ||
1861 | return ERR_PTR(ret); | ||
1862 | } | ||
1863 | |||
1864 | return wdev; | ||
1865 | } | ||
1866 | |||
1867 | void | ||
1868 | ar6k_cfg80211_deinit(struct ar6_softc *ar) | ||
1869 | { | ||
1870 | struct wireless_dev *wdev = ar->wdev; | ||
1871 | |||
1872 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__)); | ||
1873 | |||
1874 | if(ar->scan_request) { | ||
1875 | cfg80211_scan_done(ar->scan_request, true); | ||
1876 | ar->scan_request = NULL; | ||
1877 | } | ||
1878 | |||
1879 | if(!wdev) | ||
1880 | return; | ||
1881 | |||
1882 | wiphy_unregister(wdev->wiphy); | ||
1883 | wiphy_free(wdev->wiphy); | ||
1884 | kfree(wdev); | ||
1885 | } | ||
1886 | |||
1887 | |||
1888 | |||
1889 | |||
1890 | |||
1891 | |||
1892 | |||
diff --git a/drivers/staging/ath6kl/os/linux/export_hci_transport.c b/drivers/staging/ath6kl/os/linux/export_hci_transport.c new file mode 100644 index 00000000000..430998edacc --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/export_hci_transport.c | |||
@@ -0,0 +1,124 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. | ||
3 | // | ||
4 | // | ||
5 | // Permission to use, copy, modify, and/or distribute this software for any | ||
6 | // purpose with or without fee is hereby granted, provided that the above | ||
7 | // copyright notice and this permission notice appear in all copies. | ||
8 | // | ||
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | // | ||
17 | // | ||
18 | //------------------------------------------------------------------------------ | ||
19 | //============================================================================== | ||
20 | // HCI bridge implementation | ||
21 | // | ||
22 | // Author(s): ="Atheros" | ||
23 | //============================================================================== | ||
24 | #include <a_config.h> | ||
25 | #include <athdefs.h> | ||
26 | #include "a_osapi.h" | ||
27 | #include "htc_api.h" | ||
28 | #include "a_drv.h" | ||
29 | #include "hif.h" | ||
30 | #include "common_drv.h" | ||
31 | #include "a_debug.h" | ||
32 | #include "hci_transport_api.h" | ||
33 | |||
34 | #include "AR6002/hw4.0/hw/apb_athr_wlan_map.h" | ||
35 | #include "AR6002/hw4.0/hw/uart_reg.h" | ||
36 | #include "AR6002/hw4.0/hw/rtc_wlan_reg.h" | ||
37 | |||
38 | HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo); | ||
39 | void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans); | ||
40 | int (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue); | ||
41 | int (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous); | ||
42 | void (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans); | ||
43 | int (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans); | ||
44 | int (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); | ||
45 | int (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, | ||
46 | struct htc_packet *pPacket, | ||
47 | int MaxPollMS); | ||
48 | int (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud); | ||
49 | int (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); | ||
50 | |||
51 | extern struct hci_transport_callbacks ar6kHciTransCallbacks; | ||
52 | |||
53 | int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks) | ||
54 | { | ||
55 | ar6kHciTransCallbacks = *hciTransCallbacks; | ||
56 | |||
57 | _HCI_TransportAttach = HCI_TransportAttach; | ||
58 | _HCI_TransportDetach = HCI_TransportDetach; | ||
59 | _HCI_TransportAddReceivePkts = HCI_TransportAddReceivePkts; | ||
60 | _HCI_TransportSendPkt = HCI_TransportSendPkt; | ||
61 | _HCI_TransportStop = HCI_TransportStop; | ||
62 | _HCI_TransportStart = HCI_TransportStart; | ||
63 | _HCI_TransportEnableDisableAsyncRecv = HCI_TransportEnableDisableAsyncRecv; | ||
64 | _HCI_TransportRecvHCIEventSync = HCI_TransportRecvHCIEventSync; | ||
65 | _HCI_TransportSetBaudRate = HCI_TransportSetBaudRate; | ||
66 | _HCI_TransportEnablePowerMgmt = HCI_TransportEnablePowerMgmt; | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | int | ||
72 | ar6000_get_hif_dev(struct hif_device *device, void *config) | ||
73 | { | ||
74 | int status; | ||
75 | |||
76 | status = HIFConfigureDevice(device, | ||
77 | HIF_DEVICE_GET_OS_DEVICE, | ||
78 | (struct hif_device_os_device_info *)config, | ||
79 | sizeof(struct hif_device_os_device_info)); | ||
80 | return status; | ||
81 | } | ||
82 | |||
83 | int ar6000_set_uart_config(struct hif_device *hifDevice, | ||
84 | u32 scale, | ||
85 | u32 step) | ||
86 | { | ||
87 | u32 regAddress; | ||
88 | u32 regVal; | ||
89 | int status; | ||
90 | |||
91 | regAddress = WLAN_UART_BASE_ADDRESS | UART_CLKDIV_ADDRESS; | ||
92 | regVal = ((u32)scale << 16) | step; | ||
93 | /* change the HCI UART scale/step values through the diagnostic window */ | ||
94 | status = ar6000_WriteRegDiag(hifDevice, ®Address, ®Val); | ||
95 | |||
96 | return status; | ||
97 | } | ||
98 | |||
99 | int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data) | ||
100 | { | ||
101 | u32 regAddress; | ||
102 | int status; | ||
103 | |||
104 | regAddress = WLAN_RTC_BASE_ADDRESS | WLAN_CPU_CLOCK_ADDRESS; | ||
105 | /* read CPU clock settings*/ | ||
106 | status = ar6000_ReadRegDiag(hifDevice, ®Address, data); | ||
107 | |||
108 | return status; | ||
109 | } | ||
110 | |||
111 | EXPORT_SYMBOL(ar6000_register_hci_transport); | ||
112 | EXPORT_SYMBOL(ar6000_get_hif_dev); | ||
113 | EXPORT_SYMBOL(ar6000_set_uart_config); | ||
114 | EXPORT_SYMBOL(ar6000_get_core_clock_config); | ||
115 | EXPORT_SYMBOL(_HCI_TransportAttach); | ||
116 | EXPORT_SYMBOL(_HCI_TransportDetach); | ||
117 | EXPORT_SYMBOL(_HCI_TransportAddReceivePkts); | ||
118 | EXPORT_SYMBOL(_HCI_TransportSendPkt); | ||
119 | EXPORT_SYMBOL(_HCI_TransportStop); | ||
120 | EXPORT_SYMBOL(_HCI_TransportStart); | ||
121 | EXPORT_SYMBOL(_HCI_TransportEnableDisableAsyncRecv); | ||
122 | EXPORT_SYMBOL(_HCI_TransportRecvHCIEventSync); | ||
123 | EXPORT_SYMBOL(_HCI_TransportSetBaudRate); | ||
124 | EXPORT_SYMBOL(_HCI_TransportEnablePowerMgmt); | ||
diff --git a/drivers/staging/ath6kl/os/linux/hci_bridge.c b/drivers/staging/ath6kl/os/linux/hci_bridge.c new file mode 100644 index 00000000000..6087edcb1d6 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/hci_bridge.c | |||
@@ -0,0 +1,1141 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. | ||
3 | // | ||
4 | // | ||
5 | // Permission to use, copy, modify, and/or distribute this software for any | ||
6 | // purpose with or without fee is hereby granted, provided that the above | ||
7 | // copyright notice and this permission notice appear in all copies. | ||
8 | // | ||
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | // | ||
17 | // | ||
18 | //------------------------------------------------------------------------------ | ||
19 | //============================================================================== | ||
20 | // HCI bridge implementation | ||
21 | // | ||
22 | // Author(s): ="Atheros" | ||
23 | //============================================================================== | ||
24 | |||
25 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
26 | #include <linux/etherdevice.h> | ||
27 | #include <a_config.h> | ||
28 | #include <athdefs.h> | ||
29 | #include "a_osapi.h" | ||
30 | #include "htc_api.h" | ||
31 | #include "wmi.h" | ||
32 | #include "a_drv.h" | ||
33 | #include "hif.h" | ||
34 | #include "common_drv.h" | ||
35 | #include "a_debug.h" | ||
36 | #define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) | ||
37 | #define ATH_DEBUG_HCI_RECV ATH_DEBUG_MAKE_MODULE_MASK(7) | ||
38 | #define ATH_DEBUG_HCI_SEND ATH_DEBUG_MAKE_MODULE_MASK(8) | ||
39 | #define ATH_DEBUG_HCI_DUMP ATH_DEBUG_MAKE_MODULE_MASK(9) | ||
40 | #else | ||
41 | #include "ar6000_drv.h" | ||
42 | #endif /* EXPORT_HCI_BRIDGE_INTERFACE */ | ||
43 | |||
44 | #ifdef ATH_AR6K_ENABLE_GMBOX | ||
45 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
46 | #include "export_hci_transport.h" | ||
47 | #else | ||
48 | #include "hci_transport_api.h" | ||
49 | #endif | ||
50 | #include "epping_test.h" | ||
51 | #include "gmboxif.h" | ||
52 | #include "ar3kconfig.h" | ||
53 | #include <net/bluetooth/bluetooth.h> | ||
54 | #include <net/bluetooth/hci_core.h> | ||
55 | |||
56 | /* only build on newer kernels which have BT configured */ | ||
57 | #if defined(CONFIG_BT_MODULE) || defined(CONFIG_BT) | ||
58 | #define CONFIG_BLUEZ_HCI_BRIDGE | ||
59 | #endif | ||
60 | |||
61 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
62 | unsigned int ar3khcibaud = 0; | ||
63 | unsigned int hciuartscale = 0; | ||
64 | unsigned int hciuartstep = 0; | ||
65 | |||
66 | module_param(ar3khcibaud, int, 0644); | ||
67 | module_param(hciuartscale, int, 0644); | ||
68 | module_param(hciuartstep, int, 0644); | ||
69 | #else | ||
70 | extern unsigned int ar3khcibaud; | ||
71 | extern unsigned int hciuartscale; | ||
72 | extern unsigned int hciuartstep; | ||
73 | #endif /* EXPORT_HCI_BRIDGE_INTERFACE */ | ||
74 | |||
75 | struct ar6k_hci_bridge_info { | ||
76 | void *pHCIDev; /* HCI bridge device */ | ||
77 | struct hci_transport_properties HCIProps; /* HCI bridge props */ | ||
78 | struct hci_dev *pBtStackHCIDev; /* BT Stack HCI dev */ | ||
79 | bool HciNormalMode; /* Actual HCI mode enabled (non-TEST)*/ | ||
80 | bool HciRegistered; /* HCI device registered with stack */ | ||
81 | struct htc_packet_queue HTCPacketStructHead; | ||
82 | u8 *pHTCStructAlloc; | ||
83 | spinlock_t BridgeLock; | ||
84 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
85 | struct hci_transport_misc_handles HCITransHdl; | ||
86 | #else | ||
87 | struct ar6_softc *ar; | ||
88 | #endif /* EXPORT_HCI_BRIDGE_INTERFACE */ | ||
89 | }; | ||
90 | |||
91 | #define MAX_ACL_RECV_BUFS 16 | ||
92 | #define MAX_EVT_RECV_BUFS 8 | ||
93 | #define MAX_HCI_WRITE_QUEUE_DEPTH 32 | ||
94 | #define MAX_ACL_RECV_LENGTH 1200 | ||
95 | #define MAX_EVT_RECV_LENGTH 257 | ||
96 | #define TX_PACKET_RSV_OFFSET 32 | ||
97 | #define NUM_HTC_PACKET_STRUCTS ((MAX_ACL_RECV_BUFS + MAX_EVT_RECV_BUFS + MAX_HCI_WRITE_QUEUE_DEPTH) * 2) | ||
98 | |||
99 | #define HCI_GET_OP_CODE(p) (((u16)((p)[1])) << 8) | ((u16)((p)[0])) | ||
100 | |||
101 | extern unsigned int setupbtdev; | ||
102 | struct ar3k_config_info ar3kconfig; | ||
103 | |||
104 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
105 | struct ar6k_hci_bridge_info *g_pHcidevInfo; | ||
106 | #endif | ||
107 | |||
108 | static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo); | ||
109 | static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo); | ||
110 | static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo); | ||
111 | static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo, | ||
112 | HCI_TRANSPORT_PACKET_TYPE Type, | ||
113 | struct sk_buff *skb); | ||
114 | static struct sk_buff *bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length); | ||
115 | static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb); | ||
116 | |||
117 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
118 | int ar6000_setup_hci(void *ar); | ||
119 | void ar6000_cleanup_hci(void *ar); | ||
120 | int hci_test_send(void *ar, struct sk_buff *skb); | ||
121 | #else | ||
122 | int ar6000_setup_hci(struct ar6_softc *ar); | ||
123 | void ar6000_cleanup_hci(struct ar6_softc *ar); | ||
124 | /* HCI bridge testing */ | ||
125 | int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb); | ||
126 | #endif /* EXPORT_HCI_BRIDGE_INTERFACE */ | ||
127 | |||
128 | #define LOCK_BRIDGE(dev) spin_lock_bh(&(dev)->BridgeLock) | ||
129 | #define UNLOCK_BRIDGE(dev) spin_unlock_bh(&(dev)->BridgeLock) | ||
130 | |||
131 | static inline void FreeBtOsBuf(struct ar6k_hci_bridge_info *pHcidevInfo, void *osbuf) | ||
132 | { | ||
133 | if (pHcidevInfo->HciNormalMode) { | ||
134 | bt_free_buffer(pHcidevInfo, (struct sk_buff *)osbuf); | ||
135 | } else { | ||
136 | /* in test mode, these are just ordinary netbuf allocations */ | ||
137 | A_NETBUF_FREE(osbuf); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | static void FreeHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo, struct htc_packet *pPacket) | ||
142 | { | ||
143 | LOCK_BRIDGE(pHcidevInfo); | ||
144 | HTC_PACKET_ENQUEUE(&pHcidevInfo->HTCPacketStructHead,pPacket); | ||
145 | UNLOCK_BRIDGE(pHcidevInfo); | ||
146 | } | ||
147 | |||
148 | static struct htc_packet * AllocHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo) | ||
149 | { | ||
150 | struct htc_packet *pPacket = NULL; | ||
151 | LOCK_BRIDGE(pHcidevInfo); | ||
152 | pPacket = HTC_PACKET_DEQUEUE(&pHcidevInfo->HTCPacketStructHead); | ||
153 | UNLOCK_BRIDGE(pHcidevInfo); | ||
154 | return pPacket; | ||
155 | } | ||
156 | |||
157 | #define BLOCK_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1)) | ||
158 | |||
159 | static void RefillRecvBuffers(struct ar6k_hci_bridge_info *pHcidevInfo, | ||
160 | HCI_TRANSPORT_PACKET_TYPE Type, | ||
161 | int NumBuffers) | ||
162 | { | ||
163 | int length, i; | ||
164 | void *osBuf = NULL; | ||
165 | struct htc_packet_queue queue; | ||
166 | struct htc_packet *pPacket; | ||
167 | |||
168 | INIT_HTC_PACKET_QUEUE(&queue); | ||
169 | |||
170 | if (Type == HCI_ACL_TYPE) { | ||
171 | if (pHcidevInfo->HciNormalMode) { | ||
172 | length = HCI_MAX_FRAME_SIZE; | ||
173 | } else { | ||
174 | length = MAX_ACL_RECV_LENGTH; | ||
175 | } | ||
176 | } else { | ||
177 | length = MAX_EVT_RECV_LENGTH; | ||
178 | } | ||
179 | |||
180 | /* add on transport head and tail room */ | ||
181 | length += pHcidevInfo->HCIProps.HeadRoom + pHcidevInfo->HCIProps.TailRoom; | ||
182 | /* round up to the required I/O padding */ | ||
183 | length = BLOCK_ROUND_UP_PWR2(length,pHcidevInfo->HCIProps.IOBlockPad); | ||
184 | |||
185 | for (i = 0; i < NumBuffers; i++) { | ||
186 | |||
187 | if (pHcidevInfo->HciNormalMode) { | ||
188 | osBuf = bt_alloc_buffer(pHcidevInfo,length); | ||
189 | } else { | ||
190 | osBuf = A_NETBUF_ALLOC(length); | ||
191 | } | ||
192 | |||
193 | if (NULL == osBuf) { | ||
194 | break; | ||
195 | } | ||
196 | |||
197 | pPacket = AllocHTCStruct(pHcidevInfo); | ||
198 | if (NULL == pPacket) { | ||
199 | FreeBtOsBuf(pHcidevInfo,osBuf); | ||
200 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); | ||
201 | break; | ||
202 | } | ||
203 | |||
204 | SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),length,Type); | ||
205 | /* add to queue */ | ||
206 | HTC_PACKET_ENQUEUE(&queue,pPacket); | ||
207 | } | ||
208 | |||
209 | if (i > 0) { | ||
210 | HCI_TransportAddReceivePkts(pHcidevInfo->pHCIDev, &queue); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | #define HOST_INTEREST_ITEM_ADDRESS(ar, item) \ | ||
215 | (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \ | ||
216 | (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0)) | ||
217 | static int ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE HCIHandle, | ||
218 | struct hci_transport_properties *pProps, | ||
219 | void *pContext) | ||
220 | { | ||
221 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; | ||
222 | int status; | ||
223 | u32 address, hci_uart_pwr_mgmt_params; | ||
224 | // struct ar3k_config_info ar3kconfig; | ||
225 | |||
226 | pHcidevInfo->pHCIDev = HCIHandle; | ||
227 | |||
228 | memcpy(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps)); | ||
229 | |||
230 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n", | ||
231 | (unsigned long)HCIHandle, | ||
232 | pHcidevInfo->HCIProps.HeadRoom, | ||
233 | pHcidevInfo->HCIProps.TailRoom, | ||
234 | pHcidevInfo->HCIProps.IOBlockPad)); | ||
235 | |||
236 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
237 | A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)->hard_header_len); | ||
238 | #else | ||
239 | A_ASSERT((pProps->HeadRoom + pProps->TailRoom) <= pHcidevInfo->ar->arNetDev->hard_header_len); | ||
240 | #endif | ||
241 | |||
242 | /* provide buffers */ | ||
243 | RefillRecvBuffers(pHcidevInfo, HCI_ACL_TYPE, MAX_ACL_RECV_BUFS); | ||
244 | RefillRecvBuffers(pHcidevInfo, HCI_EVENT_TYPE, MAX_EVT_RECV_BUFS); | ||
245 | |||
246 | do { | ||
247 | /* start transport */ | ||
248 | status = HCI_TransportStart(pHcidevInfo->pHCIDev); | ||
249 | |||
250 | if (status) { | ||
251 | break; | ||
252 | } | ||
253 | |||
254 | if (!pHcidevInfo->HciNormalMode) { | ||
255 | /* in test mode, no need to go any further */ | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | // The delay is required when AR6K is driving the BT reset line | ||
260 | // where time is needed after the BT chip is out of reset (HCI_TransportStart) | ||
261 | // and before the first HCI command is issued (AR3KConfigure) | ||
262 | // FIXME | ||
263 | // The delay should be configurable and be only applied when AR6K driving the BT | ||
264 | // reset line. This could be done by some module parameter or based on some HW config | ||
265 | // info. For now apply 100ms delay blindly | ||
266 | A_MDELAY(100); | ||
267 | |||
268 | A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig)); | ||
269 | ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev; | ||
270 | ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps; | ||
271 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
272 | ar3kconfig.pHIFDevice = (struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice); | ||
273 | #else | ||
274 | ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice; | ||
275 | #endif | ||
276 | ar3kconfig.pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev; | ||
277 | |||
278 | if (ar3khcibaud != 0) { | ||
279 | /* user wants ar3k baud rate change */ | ||
280 | ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD; | ||
281 | ar3kconfig.Flags |= AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY; | ||
282 | ar3kconfig.AR3KBaudRate = ar3khcibaud; | ||
283 | } | ||
284 | |||
285 | if ((hciuartscale != 0) || (hciuartstep != 0)) { | ||
286 | /* user wants to tune HCI bridge UART scale/step values */ | ||
287 | ar3kconfig.AR6KScale = (u16)hciuartscale; | ||
288 | ar3kconfig.AR6KStep = (u16)hciuartstep; | ||
289 | ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP; | ||
290 | } | ||
291 | |||
292 | /* Fetch the address of the hi_hci_uart_pwr_mgmt_params instance in the host interest area */ | ||
293 | address = TARG_VTOP(pHcidevInfo->ar->arTargetType, | ||
294 | HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar, hi_hci_uart_pwr_mgmt_params)); | ||
295 | status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params); | ||
296 | if (0 == status) { | ||
297 | ar3kconfig.PwrMgmtEnabled = (hci_uart_pwr_mgmt_params & 0x1); | ||
298 | ar3kconfig.IdleTimeout = (hci_uart_pwr_mgmt_params & 0xFFFF0000) >> 16; | ||
299 | ar3kconfig.WakeupTimeout = (hci_uart_pwr_mgmt_params & 0xFF00) >> 8; | ||
300 | } else { | ||
301 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to read hci_uart_pwr_mgmt_params! \n")); | ||
302 | } | ||
303 | /* configure the AR3K device */ | ||
304 | memcpy(ar3kconfig.bdaddr,pHcidevInfo->ar->bdaddr,6); | ||
305 | status = AR3KConfigure(&ar3kconfig); | ||
306 | if (status) { | ||
307 | break; | ||
308 | } | ||
309 | |||
310 | /* Make sure both AR6K and AR3K have power management enabled */ | ||
311 | if (ar3kconfig.PwrMgmtEnabled) { | ||
312 | status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, true); | ||
313 | if (status) { | ||
314 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n")); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | status = bt_register_hci(pHcidevInfo); | ||
319 | |||
320 | } while (false); | ||
321 | |||
322 | return status; | ||
323 | } | ||
324 | |||
325 | static void ar6000_hci_transport_failure(void *pContext, int Status) | ||
326 | { | ||
327 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; | ||
328 | |||
329 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: transport failure! \n")); | ||
330 | |||
331 | if (pHcidevInfo->HciNormalMode) { | ||
332 | /* TODO .. */ | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static void ar6000_hci_transport_removed(void *pContext) | ||
337 | { | ||
338 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; | ||
339 | |||
340 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: transport removed. \n")); | ||
341 | |||
342 | A_ASSERT(pHcidevInfo->pHCIDev != NULL); | ||
343 | |||
344 | HCI_TransportDetach(pHcidevInfo->pHCIDev); | ||
345 | bt_cleanup_hci(pHcidevInfo); | ||
346 | pHcidevInfo->pHCIDev = NULL; | ||
347 | } | ||
348 | |||
349 | static void ar6000_hci_send_complete(void *pContext, struct htc_packet *pPacket) | ||
350 | { | ||
351 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; | ||
352 | void *osbuf = pPacket->pPktContext; | ||
353 | A_ASSERT(osbuf != NULL); | ||
354 | A_ASSERT(pHcidevInfo != NULL); | ||
355 | |||
356 | if (pPacket->Status) { | ||
357 | if ((pPacket->Status != A_ECANCELED) && (pPacket->Status != A_NO_RESOURCE)) { | ||
358 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Send Packet Failed: %d \n",pPacket->Status)); | ||
359 | } | ||
360 | } | ||
361 | |||
362 | FreeHTCStruct(pHcidevInfo,pPacket); | ||
363 | FreeBtOsBuf(pHcidevInfo,osbuf); | ||
364 | |||
365 | } | ||
366 | |||
367 | static void ar6000_hci_pkt_recv(void *pContext, struct htc_packet *pPacket) | ||
368 | { | ||
369 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; | ||
370 | struct sk_buff *skb; | ||
371 | |||
372 | A_ASSERT(pHcidevInfo != NULL); | ||
373 | skb = (struct sk_buff *)pPacket->pPktContext; | ||
374 | A_ASSERT(skb != NULL); | ||
375 | |||
376 | do { | ||
377 | |||
378 | if (pPacket->Status) { | ||
379 | break; | ||
380 | } | ||
381 | |||
382 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, | ||
383 | ("HCI Bridge, packet received type : %d len:%d \n", | ||
384 | HCI_GET_PACKET_TYPE(pPacket),pPacket->ActualLength)); | ||
385 | |||
386 | /* set the actual buffer position in the os buffer, HTC recv buffers posted to HCI are set | ||
387 | * to fill the front of the buffer */ | ||
388 | A_NETBUF_PUT(skb,pPacket->ActualLength + pHcidevInfo->HCIProps.HeadRoom); | ||
389 | A_NETBUF_PULL(skb,pHcidevInfo->HCIProps.HeadRoom); | ||
390 | |||
391 | if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) { | ||
392 | AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("<<< Recv HCI %s packet len:%d \n", | ||
393 | (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) ? "EVENT" : "ACL", | ||
394 | skb->len)); | ||
395 | AR_DEBUG_PRINTBUF(skb->data, skb->len,"BT HCI RECV Packet Dump"); | ||
396 | } | ||
397 | |||
398 | if (pHcidevInfo->HciNormalMode) { | ||
399 | /* indicate the packet */ | ||
400 | if (bt_indicate_recv(pHcidevInfo,HCI_GET_PACKET_TYPE(pPacket),skb)) { | ||
401 | /* bt stack accepted the packet */ | ||
402 | skb = NULL; | ||
403 | } | ||
404 | break; | ||
405 | } | ||
406 | |||
407 | /* for testing, indicate packet to the network stack */ | ||
408 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
409 | skb->dev = (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice); | ||
410 | if ((((struct net_device *)pHcidevInfo->HCITransHdl.netDevice)->flags & IFF_UP) == IFF_UP) { | ||
411 | skb->protocol = eth_type_trans(skb, (struct net_device *)(pHcidevInfo->HCITransHdl.netDevice)); | ||
412 | #else | ||
413 | skb->dev = pHcidevInfo->ar->arNetDev; | ||
414 | if ((pHcidevInfo->ar->arNetDev->flags & IFF_UP) == IFF_UP) { | ||
415 | skb->protocol = eth_type_trans(skb, pHcidevInfo->ar->arNetDev); | ||
416 | #endif | ||
417 | netif_rx(skb); | ||
418 | skb = NULL; | ||
419 | } | ||
420 | |||
421 | } while (false); | ||
422 | |||
423 | FreeHTCStruct(pHcidevInfo,pPacket); | ||
424 | |||
425 | if (skb != NULL) { | ||
426 | /* packet was not accepted, free it */ | ||
427 | FreeBtOsBuf(pHcidevInfo,skb); | ||
428 | } | ||
429 | |||
430 | } | ||
431 | |||
432 | static void ar6000_hci_pkt_refill(void *pContext, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable) | ||
433 | { | ||
434 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; | ||
435 | int refillCount; | ||
436 | |||
437 | if (Type == HCI_ACL_TYPE) { | ||
438 | refillCount = MAX_ACL_RECV_BUFS - BuffersAvailable; | ||
439 | } else { | ||
440 | refillCount = MAX_EVT_RECV_BUFS - BuffersAvailable; | ||
441 | } | ||
442 | |||
443 | if (refillCount > 0) { | ||
444 | RefillRecvBuffers(pHcidevInfo,Type,refillCount); | ||
445 | } | ||
446 | |||
447 | } | ||
448 | |||
449 | static HCI_SEND_FULL_ACTION ar6000_hci_pkt_send_full(void *pContext, struct htc_packet *pPacket) | ||
450 | { | ||
451 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext; | ||
452 | HCI_SEND_FULL_ACTION action = HCI_SEND_FULL_KEEP; | ||
453 | |||
454 | if (!pHcidevInfo->HciNormalMode) { | ||
455 | /* for epping testing, check packet tag, some epping packets are | ||
456 | * special and cannot be dropped */ | ||
457 | if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_DATA_PKT_TAG) { | ||
458 | action = HCI_SEND_FULL_DROP; | ||
459 | } | ||
460 | } | ||
461 | |||
462 | return action; | ||
463 | } | ||
464 | |||
465 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
466 | int ar6000_setup_hci(void *ar) | ||
467 | #else | ||
468 | int ar6000_setup_hci(struct ar6_softc *ar) | ||
469 | #endif | ||
470 | { | ||
471 | struct hci_transport_config_info config; | ||
472 | int status = 0; | ||
473 | int i; | ||
474 | struct htc_packet *pPacket; | ||
475 | struct ar6k_hci_bridge_info *pHcidevInfo; | ||
476 | |||
477 | |||
478 | do { | ||
479 | |||
480 | pHcidevInfo = (struct ar6k_hci_bridge_info *)A_MALLOC(sizeof(struct ar6k_hci_bridge_info)); | ||
481 | |||
482 | if (NULL == pHcidevInfo) { | ||
483 | status = A_NO_MEMORY; | ||
484 | break; | ||
485 | } | ||
486 | |||
487 | A_MEMZERO(pHcidevInfo, sizeof(struct ar6k_hci_bridge_info)); | ||
488 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
489 | g_pHcidevInfo = pHcidevInfo; | ||
490 | pHcidevInfo->HCITransHdl = *(struct hci_transport_misc_handles *)ar; | ||
491 | #else | ||
492 | ar->hcidev_info = pHcidevInfo; | ||
493 | pHcidevInfo->ar = ar; | ||
494 | #endif | ||
495 | spin_lock_init(&pHcidevInfo->BridgeLock); | ||
496 | INIT_HTC_PACKET_QUEUE(&pHcidevInfo->HTCPacketStructHead); | ||
497 | |||
498 | ar->exitCallback = AR3KConfigureExit; | ||
499 | |||
500 | status = bt_setup_hci(pHcidevInfo); | ||
501 | if (status) { | ||
502 | break; | ||
503 | } | ||
504 | |||
505 | if (pHcidevInfo->HciNormalMode) { | ||
506 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in normal mode... \n")); | ||
507 | } else { | ||
508 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in test mode... \n")); | ||
509 | } | ||
510 | |||
511 | pHcidevInfo->pHTCStructAlloc = (u8 *)A_MALLOC((sizeof(struct htc_packet)) * NUM_HTC_PACKET_STRUCTS); | ||
512 | |||
513 | if (NULL == pHcidevInfo->pHTCStructAlloc) { | ||
514 | status = A_NO_MEMORY; | ||
515 | break; | ||
516 | } | ||
517 | |||
518 | pPacket = (struct htc_packet *)pHcidevInfo->pHTCStructAlloc; | ||
519 | for (i = 0; i < NUM_HTC_PACKET_STRUCTS; i++,pPacket++) { | ||
520 | FreeHTCStruct(pHcidevInfo,pPacket); | ||
521 | } | ||
522 | |||
523 | A_MEMZERO(&config,sizeof(struct hci_transport_config_info)); | ||
524 | config.ACLRecvBufferWaterMark = MAX_ACL_RECV_BUFS / 2; | ||
525 | config.EventRecvBufferWaterMark = MAX_EVT_RECV_BUFS / 2; | ||
526 | config.MaxSendQueueDepth = MAX_HCI_WRITE_QUEUE_DEPTH; | ||
527 | config.pContext = pHcidevInfo; | ||
528 | config.TransportFailure = ar6000_hci_transport_failure; | ||
529 | config.TransportReady = ar6000_hci_transport_ready; | ||
530 | config.TransportRemoved = ar6000_hci_transport_removed; | ||
531 | config.pHCISendComplete = ar6000_hci_send_complete; | ||
532 | config.pHCIPktRecv = ar6000_hci_pkt_recv; | ||
533 | config.pHCIPktRecvRefill = ar6000_hci_pkt_refill; | ||
534 | config.pHCISendFull = ar6000_hci_pkt_send_full; | ||
535 | |||
536 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
537 | pHcidevInfo->pHCIDev = HCI_TransportAttach(pHcidevInfo->HCITransHdl.htcHandle, &config); | ||
538 | #else | ||
539 | pHcidevInfo->pHCIDev = HCI_TransportAttach(ar->arHtcTarget, &config); | ||
540 | #endif | ||
541 | |||
542 | if (NULL == pHcidevInfo->pHCIDev) { | ||
543 | status = A_ERROR; | ||
544 | } | ||
545 | |||
546 | } while (false); | ||
547 | |||
548 | if (status) { | ||
549 | if (pHcidevInfo != NULL) { | ||
550 | if (NULL == pHcidevInfo->pHCIDev) { | ||
551 | /* GMBOX may not be present in older chips */ | ||
552 | /* just return success */ | ||
553 | status = 0; | ||
554 | } | ||
555 | } | ||
556 | ar6000_cleanup_hci(ar); | ||
557 | } | ||
558 | |||
559 | return status; | ||
560 | } | ||
561 | |||
562 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
563 | void ar6000_cleanup_hci(void *ar) | ||
564 | #else | ||
565 | void ar6000_cleanup_hci(struct ar6_softc *ar) | ||
566 | #endif | ||
567 | { | ||
568 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
569 | struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo; | ||
570 | #else | ||
571 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info; | ||
572 | #endif | ||
573 | |||
574 | if (pHcidevInfo != NULL) { | ||
575 | bt_cleanup_hci(pHcidevInfo); | ||
576 | |||
577 | if (pHcidevInfo->pHCIDev != NULL) { | ||
578 | HCI_TransportStop(pHcidevInfo->pHCIDev); | ||
579 | HCI_TransportDetach(pHcidevInfo->pHCIDev); | ||
580 | pHcidevInfo->pHCIDev = NULL; | ||
581 | } | ||
582 | |||
583 | if (pHcidevInfo->pHTCStructAlloc != NULL) { | ||
584 | kfree(pHcidevInfo->pHTCStructAlloc); | ||
585 | pHcidevInfo->pHTCStructAlloc = NULL; | ||
586 | } | ||
587 | |||
588 | kfree(pHcidevInfo); | ||
589 | #ifndef EXPORT_HCI_BRIDGE_INTERFACE | ||
590 | ar->hcidev_info = NULL; | ||
591 | #endif | ||
592 | } | ||
593 | |||
594 | |||
595 | } | ||
596 | |||
597 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
598 | int hci_test_send(void *ar, struct sk_buff *skb) | ||
599 | #else | ||
600 | int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb) | ||
601 | #endif | ||
602 | { | ||
603 | int status = 0; | ||
604 | int length; | ||
605 | EPPING_HEADER *pHeader; | ||
606 | struct htc_packet *pPacket; | ||
607 | HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; | ||
608 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
609 | struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo; | ||
610 | #else | ||
611 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info; | ||
612 | #endif | ||
613 | |||
614 | do { | ||
615 | |||
616 | if (NULL == pHcidevInfo) { | ||
617 | status = A_ERROR; | ||
618 | break; | ||
619 | } | ||
620 | |||
621 | if (NULL == pHcidevInfo->pHCIDev) { | ||
622 | status = A_ERROR; | ||
623 | break; | ||
624 | } | ||
625 | |||
626 | if (pHcidevInfo->HciNormalMode) { | ||
627 | /* this interface cannot run when normal WMI is running */ | ||
628 | status = A_ERROR; | ||
629 | break; | ||
630 | } | ||
631 | |||
632 | pHeader = (EPPING_HEADER *)A_NETBUF_DATA(skb); | ||
633 | |||
634 | if (!IS_EPPING_PACKET(pHeader)) { | ||
635 | status = A_EINVAL; | ||
636 | break; | ||
637 | } | ||
638 | |||
639 | if (IS_EPING_PACKET_NO_DROP(pHeader)) { | ||
640 | htc_tag = AR6K_CONTROL_PKT_TAG; | ||
641 | } | ||
642 | |||
643 | length = sizeof(EPPING_HEADER) + pHeader->DataLength; | ||
644 | |||
645 | pPacket = AllocHTCStruct(pHcidevInfo); | ||
646 | if (NULL == pPacket) { | ||
647 | status = A_NO_MEMORY; | ||
648 | break; | ||
649 | } | ||
650 | |||
651 | SET_HTC_PACKET_INFO_TX(pPacket, | ||
652 | skb, | ||
653 | A_NETBUF_DATA(skb), | ||
654 | length, | ||
655 | HCI_ACL_TYPE, /* send every thing out as ACL */ | ||
656 | htc_tag); | ||
657 | |||
658 | HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false); | ||
659 | pPacket = NULL; | ||
660 | |||
661 | } while (false); | ||
662 | |||
663 | return status; | ||
664 | } | ||
665 | |||
666 | void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig) | ||
667 | { | ||
668 | struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info; | ||
669 | struct ar3k_config_info *config = (struct ar3k_config_info *)ar3kconfig; | ||
670 | |||
671 | config->pHCIDev = pHcidevInfo->pHCIDev; | ||
672 | config->pHCIProps = &pHcidevInfo->HCIProps; | ||
673 | config->pHIFDevice = ar->arHifDevice; | ||
674 | config->pBtStackHCIDev = pHcidevInfo->pBtStackHCIDev; | ||
675 | config->Flags |= AR3K_CONFIG_FLAG_SET_AR3K_BAUD; | ||
676 | config->AR3KBaudRate = 115200; | ||
677 | } | ||
678 | |||
679 | #ifdef CONFIG_BLUEZ_HCI_BRIDGE | ||
680 | /*** BT Stack Entrypoints *******/ | ||
681 | |||
682 | /* | ||
683 | * bt_open - open a handle to the device | ||
684 | */ | ||
685 | static int bt_open(struct hci_dev *hdev) | ||
686 | { | ||
687 | |||
688 | AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_open - enter - x\n")); | ||
689 | set_bit(HCI_RUNNING, &hdev->flags); | ||
690 | set_bit(HCI_UP, &hdev->flags); | ||
691 | set_bit(HCI_INIT, &hdev->flags); | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | /* | ||
696 | * bt_close - close handle to the device | ||
697 | */ | ||
698 | static int bt_close(struct hci_dev *hdev) | ||
699 | { | ||
700 | AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_close - enter\n")); | ||
701 | clear_bit(HCI_RUNNING, &hdev->flags); | ||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | /* | ||
706 | * bt_send_frame - send data frames | ||
707 | */ | ||
708 | static int bt_send_frame(struct sk_buff *skb) | ||
709 | { | ||
710 | struct hci_dev *hdev = (struct hci_dev *)skb->dev; | ||
711 | HCI_TRANSPORT_PACKET_TYPE type; | ||
712 | struct ar6k_hci_bridge_info *pHcidevInfo; | ||
713 | struct htc_packet *pPacket; | ||
714 | int status = 0; | ||
715 | struct sk_buff *txSkb = NULL; | ||
716 | |||
717 | if (!hdev) { | ||
718 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_send_frame - no device\n")); | ||
719 | return -ENODEV; | ||
720 | } | ||
721 | |||
722 | if (!test_bit(HCI_RUNNING, &hdev->flags)) { | ||
723 | AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_send_frame - not open\n")); | ||
724 | return -EBUSY; | ||
725 | } | ||
726 | |||
727 | pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data; | ||
728 | A_ASSERT(pHcidevInfo != NULL); | ||
729 | |||
730 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("+bt_send_frame type: %d \n",bt_cb(skb)->pkt_type)); | ||
731 | type = HCI_COMMAND_TYPE; | ||
732 | |||
733 | switch (bt_cb(skb)->pkt_type) { | ||
734 | case HCI_COMMAND_PKT: | ||
735 | type = HCI_COMMAND_TYPE; | ||
736 | hdev->stat.cmd_tx++; | ||
737 | break; | ||
738 | |||
739 | case HCI_ACLDATA_PKT: | ||
740 | type = HCI_ACL_TYPE; | ||
741 | hdev->stat.acl_tx++; | ||
742 | break; | ||
743 | |||
744 | case HCI_SCODATA_PKT: | ||
745 | /* we don't support SCO over the bridge */ | ||
746 | kfree_skb(skb); | ||
747 | return 0; | ||
748 | default: | ||
749 | A_ASSERT(false); | ||
750 | kfree_skb(skb); | ||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) { | ||
755 | AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(">>> Send HCI %s packet len: %d\n", | ||
756 | (type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL", | ||
757 | skb->len)); | ||
758 | if (type == HCI_COMMAND_TYPE) { | ||
759 | u16 opcode = HCI_GET_OP_CODE(skb->data); | ||
760 | AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" HCI Command: OGF:0x%X OCF:0x%X \r\n", | ||
761 | opcode >> 10, opcode & 0x3FF)); | ||
762 | } | ||
763 | AR_DEBUG_PRINTBUF(skb->data,skb->len,"BT HCI SEND Packet Dump"); | ||
764 | } | ||
765 | |||
766 | do { | ||
767 | |||
768 | txSkb = bt_skb_alloc(TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom + | ||
769 | pHcidevInfo->HCIProps.TailRoom + skb->len, | ||
770 | GFP_ATOMIC); | ||
771 | |||
772 | if (txSkb == NULL) { | ||
773 | status = A_NO_MEMORY; | ||
774 | break; | ||
775 | } | ||
776 | |||
777 | bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type; | ||
778 | txSkb->dev = (void *)pHcidevInfo->pBtStackHCIDev; | ||
779 | skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom); | ||
780 | memcpy(txSkb->data, skb->data, skb->len); | ||
781 | skb_put(txSkb,skb->len); | ||
782 | |||
783 | pPacket = AllocHTCStruct(pHcidevInfo); | ||
784 | if (NULL == pPacket) { | ||
785 | status = A_NO_MEMORY; | ||
786 | break; | ||
787 | } | ||
788 | |||
789 | /* HCI packet length here doesn't include the 1-byte transport header which | ||
790 | * will be handled by the HCI transport layer. Enough headroom has already | ||
791 | * been reserved above for the transport header | ||
792 | */ | ||
793 | SET_HTC_PACKET_INFO_TX(pPacket, | ||
794 | txSkb, | ||
795 | txSkb->data, | ||
796 | txSkb->len, | ||
797 | type, | ||
798 | AR6K_CONTROL_PKT_TAG); /* HCI packets cannot be dropped */ | ||
799 | |||
800 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: bt_send_frame skb:0x%lX \n",(unsigned long)txSkb)); | ||
801 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: type:%d, Total Length:%d Bytes \n", | ||
802 | type, txSkb->len)); | ||
803 | |||
804 | status = HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false); | ||
805 | pPacket = NULL; | ||
806 | txSkb = NULL; | ||
807 | |||
808 | } while (false); | ||
809 | |||
810 | if (txSkb != NULL) { | ||
811 | kfree_skb(txSkb); | ||
812 | } | ||
813 | |||
814 | kfree_skb(skb); | ||
815 | |||
816 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("-bt_send_frame \n")); | ||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | /* | ||
821 | * bt_ioctl - ioctl processing | ||
822 | */ | ||
823 | static int bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
824 | { | ||
825 | AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_ioctl - enter\n")); | ||
826 | return -ENOIOCTLCMD; | ||
827 | } | ||
828 | |||
829 | /* | ||
830 | * bt_flush - flush outstandingbpackets | ||
831 | */ | ||
832 | static int bt_flush(struct hci_dev *hdev) | ||
833 | { | ||
834 | struct ar6k_hci_bridge_info *pHcidevInfo; | ||
835 | |||
836 | AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_flush - enter\n")); | ||
837 | |||
838 | pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data; | ||
839 | |||
840 | /* TODO??? */ | ||
841 | |||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | |||
846 | /* | ||
847 | * bt_destruct - | ||
848 | */ | ||
849 | static void bt_destruct(struct hci_dev *hdev) | ||
850 | { | ||
851 | AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_destruct - enter\n")); | ||
852 | /* nothing to do here */ | ||
853 | } | ||
854 | |||
855 | static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) | ||
856 | { | ||
857 | int status = 0; | ||
858 | struct hci_dev *pHciDev = NULL; | ||
859 | struct hif_device_os_device_info osDevInfo; | ||
860 | |||
861 | if (!setupbtdev) { | ||
862 | return 0; | ||
863 | } | ||
864 | |||
865 | do { | ||
866 | |||
867 | A_MEMZERO(&osDevInfo,sizeof(osDevInfo)); | ||
868 | /* get the underlying OS device */ | ||
869 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
870 | status = ar6000_get_hif_dev((struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice), | ||
871 | &osDevInfo); | ||
872 | #else | ||
873 | status = HIFConfigureDevice(pHcidevInfo->ar->arHifDevice, | ||
874 | HIF_DEVICE_GET_OS_DEVICE, | ||
875 | &osDevInfo, | ||
876 | sizeof(osDevInfo)); | ||
877 | #endif | ||
878 | |||
879 | if (status) { | ||
880 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to OS device info from HIF\n")); | ||
881 | break; | ||
882 | } | ||
883 | |||
884 | /* allocate a BT HCI struct for this device */ | ||
885 | pHciDev = hci_alloc_dev(); | ||
886 | if (NULL == pHciDev) { | ||
887 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge - failed to allocate bt struct \n")); | ||
888 | status = A_NO_MEMORY; | ||
889 | break; | ||
890 | } | ||
891 | /* save the device, we'll register this later */ | ||
892 | pHcidevInfo->pBtStackHCIDev = pHciDev; | ||
893 | SET_HCIDEV_DEV(pHciDev,osDevInfo.pOSDevice); | ||
894 | SET_HCI_BUS_TYPE(pHciDev, HCI_VIRTUAL, HCI_BREDR); | ||
895 | pHciDev->driver_data = pHcidevInfo; | ||
896 | pHciDev->open = bt_open; | ||
897 | pHciDev->close = bt_close; | ||
898 | pHciDev->send = bt_send_frame; | ||
899 | pHciDev->ioctl = bt_ioctl; | ||
900 | pHciDev->flush = bt_flush; | ||
901 | pHciDev->destruct = bt_destruct; | ||
902 | pHciDev->owner = THIS_MODULE; | ||
903 | /* driver is running in normal BT mode */ | ||
904 | pHcidevInfo->HciNormalMode = true; | ||
905 | |||
906 | } while (false); | ||
907 | |||
908 | if (status) { | ||
909 | bt_cleanup_hci(pHcidevInfo); | ||
910 | } | ||
911 | |||
912 | return status; | ||
913 | } | ||
914 | |||
915 | static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) | ||
916 | { | ||
917 | int err; | ||
918 | |||
919 | if (pHcidevInfo->HciRegistered) { | ||
920 | pHcidevInfo->HciRegistered = false; | ||
921 | clear_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags); | ||
922 | clear_bit(HCI_UP, &pHcidevInfo->pBtStackHCIDev->flags); | ||
923 | clear_bit(HCI_INIT, &pHcidevInfo->pBtStackHCIDev->flags); | ||
924 | A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL); | ||
925 | /* unregister */ | ||
926 | if ((err = hci_unregister_dev(pHcidevInfo->pBtStackHCIDev)) < 0) { | ||
927 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to unregister with bluetooth %d\n",err)); | ||
928 | } | ||
929 | } | ||
930 | |||
931 | kfree(pHcidevInfo->pBtStackHCIDev); | ||
932 | pHcidevInfo->pBtStackHCIDev = NULL; | ||
933 | } | ||
934 | |||
935 | static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo) | ||
936 | { | ||
937 | int err; | ||
938 | int status = 0; | ||
939 | |||
940 | do { | ||
941 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: registering HCI... \n")); | ||
942 | A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL); | ||
943 | /* mark that we are registered */ | ||
944 | pHcidevInfo->HciRegistered = true; | ||
945 | if ((err = hci_register_dev(pHcidevInfo->pBtStackHCIDev)) < 0) { | ||
946 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to register with bluetooth %d\n",err)); | ||
947 | pHcidevInfo->HciRegistered = false; | ||
948 | status = A_ERROR; | ||
949 | break; | ||
950 | } | ||
951 | |||
952 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: HCI registered \n")); | ||
953 | |||
954 | } while (false); | ||
955 | |||
956 | return status; | ||
957 | } | ||
958 | |||
959 | static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo, | ||
960 | HCI_TRANSPORT_PACKET_TYPE Type, | ||
961 | struct sk_buff *skb) | ||
962 | { | ||
963 | u8 btType; | ||
964 | int len; | ||
965 | bool success = false; | ||
966 | BT_HCI_EVENT_HEADER *pEvent; | ||
967 | |||
968 | do { | ||
969 | |||
970 | if (!test_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags)) { | ||
971 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HCI Bridge: bt_indicate_recv - not running\n")); | ||
972 | break; | ||
973 | } | ||
974 | |||
975 | switch (Type) { | ||
976 | case HCI_ACL_TYPE: | ||
977 | btType = HCI_ACLDATA_PKT; | ||
978 | break; | ||
979 | case HCI_EVENT_TYPE: | ||
980 | btType = HCI_EVENT_PKT; | ||
981 | break; | ||
982 | default: | ||
983 | btType = 0; | ||
984 | A_ASSERT(false); | ||
985 | break; | ||
986 | } | ||
987 | |||
988 | if (0 == btType) { | ||
989 | break; | ||
990 | } | ||
991 | |||
992 | /* set the final type */ | ||
993 | bt_cb(skb)->pkt_type = btType; | ||
994 | /* set dev */ | ||
995 | skb->dev = (void *)pHcidevInfo->pBtStackHCIDev; | ||
996 | len = skb->len; | ||
997 | |||
998 | if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_RECV)) { | ||
999 | if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) { | ||
1000 | pEvent = (BT_HCI_EVENT_HEADER *)skb->data; | ||
1001 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, ("BT HCI EventCode: %d, len:%d \n", | ||
1002 | pEvent->EventCode, pEvent->ParamLength)); | ||
1003 | } | ||
1004 | } | ||
1005 | |||
1006 | /* pass receive packet up the stack */ | ||
1007 | if (hci_recv_frame(skb) != 0) { | ||
1008 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: hci_recv_frame failed \n")); | ||
1009 | break; | ||
1010 | } else { | ||
1011 | AR_DEBUG_PRINTF(ATH_DEBUG_HCI_RECV, | ||
1012 | ("HCI Bridge: Indicated RCV of type:%d, Length:%d \n",btType,len)); | ||
1013 | } | ||
1014 | |||
1015 | success = true; | ||
1016 | |||
1017 | } while (false); | ||
1018 | |||
1019 | return success; | ||
1020 | } | ||
1021 | |||
1022 | static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) | ||
1023 | { | ||
1024 | struct sk_buff *skb; | ||
1025 | /* in normal HCI mode we need to alloc from the bt core APIs */ | ||
1026 | skb = bt_skb_alloc(Length, GFP_ATOMIC); | ||
1027 | if (NULL == skb) { | ||
1028 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc bt sk_buff \n")); | ||
1029 | } | ||
1030 | return skb; | ||
1031 | } | ||
1032 | |||
1033 | static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb) | ||
1034 | { | ||
1035 | kfree_skb(skb); | ||
1036 | } | ||
1037 | |||
1038 | #else // { CONFIG_BLUEZ_HCI_BRIDGE | ||
1039 | |||
1040 | /* stubs when we only want to test the HCI bridging Interface without the HT stack */ | ||
1041 | static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) | ||
1042 | { | ||
1043 | return 0; | ||
1044 | } | ||
1045 | static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo) | ||
1046 | { | ||
1047 | |||
1048 | } | ||
1049 | static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo) | ||
1050 | { | ||
1051 | A_ASSERT(false); | ||
1052 | return A_ERROR; | ||
1053 | } | ||
1054 | |||
1055 | static bool bt_indicate_recv(struct ar6k_hci_bridge_info *pHcidevInfo, | ||
1056 | HCI_TRANSPORT_PACKET_TYPE Type, | ||
1057 | struct sk_buff *skb) | ||
1058 | { | ||
1059 | A_ASSERT(false); | ||
1060 | return false; | ||
1061 | } | ||
1062 | |||
1063 | static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) | ||
1064 | { | ||
1065 | A_ASSERT(false); | ||
1066 | return NULL; | ||
1067 | } | ||
1068 | static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb) | ||
1069 | { | ||
1070 | A_ASSERT(false); | ||
1071 | } | ||
1072 | |||
1073 | #endif // } CONFIG_BLUEZ_HCI_BRIDGE | ||
1074 | |||
1075 | #else // { ATH_AR6K_ENABLE_GMBOX | ||
1076 | |||
1077 | /* stubs when GMBOX support is not needed */ | ||
1078 | |||
1079 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
1080 | int ar6000_setup_hci(void *ar) | ||
1081 | #else | ||
1082 | int ar6000_setup_hci(struct ar6_softc *ar) | ||
1083 | #endif | ||
1084 | { | ||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
1089 | void ar6000_cleanup_hci(void *ar) | ||
1090 | #else | ||
1091 | void ar6000_cleanup_hci(struct ar6_softc *ar) | ||
1092 | #endif | ||
1093 | { | ||
1094 | return; | ||
1095 | } | ||
1096 | |||
1097 | #ifndef EXPORT_HCI_BRIDGE_INTERFACE | ||
1098 | void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig) | ||
1099 | { | ||
1100 | return; | ||
1101 | } | ||
1102 | #endif | ||
1103 | |||
1104 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
1105 | int hci_test_send(void *ar, struct sk_buff *skb) | ||
1106 | #else | ||
1107 | int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb) | ||
1108 | #endif | ||
1109 | { | ||
1110 | return -EOPNOTSUPP; | ||
1111 | } | ||
1112 | |||
1113 | #endif // } ATH_AR6K_ENABLE_GMBOX | ||
1114 | |||
1115 | |||
1116 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
1117 | static int __init | ||
1118 | hcibridge_init_module(void) | ||
1119 | { | ||
1120 | int status; | ||
1121 | struct hci_transport_callbacks hciTransCallbacks; | ||
1122 | |||
1123 | hciTransCallbacks.setupTransport = ar6000_setup_hci; | ||
1124 | hciTransCallbacks.cleanupTransport = ar6000_cleanup_hci; | ||
1125 | |||
1126 | status = ar6000_register_hci_transport(&hciTransCallbacks); | ||
1127 | if (status) | ||
1128 | return -ENODEV; | ||
1129 | |||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | static void __exit | ||
1134 | hcibridge_cleanup_module(void) | ||
1135 | { | ||
1136 | } | ||
1137 | |||
1138 | module_init(hcibridge_init_module); | ||
1139 | module_exit(hcibridge_cleanup_module); | ||
1140 | MODULE_LICENSE("Dual BSD/GPL"); | ||
1141 | #endif | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h new file mode 100644 index 00000000000..80cef77738f --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h | |||
@@ -0,0 +1,776 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #ifndef _AR6000_H_ | ||
25 | #define _AR6000_H_ | ||
26 | |||
27 | #include <linux/init.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/spinlock.h> | ||
30 | #include <linux/if_ether.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <net/iw_handler.h> | ||
33 | #include <linux/if_arp.h> | ||
34 | #include <linux/ip.h> | ||
35 | #include <linux/wireless.h> | ||
36 | #include <net/cfg80211.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <asm/io.h> | ||
39 | |||
40 | #include <a_config.h> | ||
41 | #include <athdefs.h> | ||
42 | #include "a_osapi.h" | ||
43 | #include "htc_api.h" | ||
44 | #include "wmi.h" | ||
45 | #include "a_drv.h" | ||
46 | #include "bmi.h" | ||
47 | #include <ieee80211.h> | ||
48 | #include <ieee80211_ioctl.h> | ||
49 | #include <wlan_api.h> | ||
50 | #include <wmi_api.h> | ||
51 | #include "pkt_log.h" | ||
52 | #include "aggr_recv_api.h" | ||
53 | #include <host_version.h> | ||
54 | #include <linux/rtnetlink.h> | ||
55 | #include <linux/moduleparam.h> | ||
56 | #include "ar6000_api.h" | ||
57 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
58 | #include <testcmd.h> | ||
59 | #endif | ||
60 | #include <linux/firmware.h> | ||
61 | |||
62 | #include "targaddrs.h" | ||
63 | #include "dbglog_api.h" | ||
64 | #include "ar6000_diag.h" | ||
65 | #include "common_drv.h" | ||
66 | #include "roaming.h" | ||
67 | #include "hci_transport_api.h" | ||
68 | #define ATH_MODULE_NAME driver | ||
69 | #include "a_debug.h" | ||
70 | #include "hw/apb_map.h" | ||
71 | #include "hw/rtc_reg.h" | ||
72 | #include "hw/mbox_reg.h" | ||
73 | #include "gpio_reg.h" | ||
74 | |||
75 | #define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0) | ||
76 | #define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1) | ||
77 | #define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2) | ||
78 | #define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3) | ||
79 | #define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4) | ||
80 | #define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5) | ||
81 | #define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) | ||
82 | #define ATH_DEBUG_HCI_RECV ATH_DEBUG_MAKE_MODULE_MASK(7) | ||
83 | #define ATH_DEBUG_HCI_SEND ATH_DEBUG_MAKE_MODULE_MASK(8) | ||
84 | #define ATH_DEBUG_HCI_DUMP ATH_DEBUG_MAKE_MODULE_MASK(9) | ||
85 | |||
86 | #ifndef __dev_put | ||
87 | #define __dev_put(dev) dev_put(dev) | ||
88 | #endif | ||
89 | |||
90 | |||
91 | #define USER_SAVEDKEYS_STAT_INIT 0 | ||
92 | #define USER_SAVEDKEYS_STAT_RUN 1 | ||
93 | |||
94 | // TODO this needs to move into the AR_SOFTC struct | ||
95 | struct USER_SAVEDKEYS { | ||
96 | struct ieee80211req_key ucast_ik; | ||
97 | struct ieee80211req_key bcast_ik; | ||
98 | CRYPTO_TYPE keyType; | ||
99 | bool keyOk; | ||
100 | }; | ||
101 | |||
102 | #define DBG_INFO 0x00000001 | ||
103 | #define DBG_ERROR 0x00000002 | ||
104 | #define DBG_WARNING 0x00000004 | ||
105 | #define DBG_SDIO 0x00000008 | ||
106 | #define DBG_HIF 0x00000010 | ||
107 | #define DBG_HTC 0x00000020 | ||
108 | #define DBG_WMI 0x00000040 | ||
109 | #define DBG_WMI2 0x00000080 | ||
110 | #define DBG_DRIVER 0x00000100 | ||
111 | |||
112 | #define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING) | ||
113 | |||
114 | |||
115 | int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); | ||
116 | int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data); | ||
117 | |||
118 | #ifdef __cplusplus | ||
119 | extern "C" { | ||
120 | #endif | ||
121 | |||
122 | #define MAX_AR6000 1 | ||
123 | #define AR6000_MAX_RX_BUFFERS 16 | ||
124 | #define AR6000_BUFFER_SIZE 1664 | ||
125 | #define AR6000_MAX_AMSDU_RX_BUFFERS 4 | ||
126 | #define AR6000_AMSDU_REFILL_THRESHOLD 3 | ||
127 | #define AR6000_AMSDU_BUFFER_SIZE (WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH + 128) | ||
128 | #define AR6000_MAX_RX_MESSAGE_SIZE (max(WMI_MAX_NORMAL_RX_DATA_FRAME_LENGTH,WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH)) | ||
129 | |||
130 | #define AR6000_TX_TIMEOUT 10 | ||
131 | #define AR6000_ETH_ADDR_LEN 6 | ||
132 | #define AR6000_MAX_ENDPOINTS 4 | ||
133 | #define MAX_NODE_NUM 15 | ||
134 | /* MAX_HI_COOKIE_NUM are reserved for high priority traffic */ | ||
135 | #define MAX_DEF_COOKIE_NUM 180 | ||
136 | #define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */ | ||
137 | #define MAX_COOKIE_NUM (MAX_DEF_COOKIE_NUM + MAX_HI_COOKIE_NUM) | ||
138 | |||
139 | /* MAX_DEFAULT_SEND_QUEUE_DEPTH is used to set the default queue depth for the | ||
140 | * WMM send queues. If a queue exceeds this depth htc will query back to the | ||
141 | * OS specific layer by calling EpSendFull(). This gives the OS layer the | ||
142 | * opportunity to drop the packet if desired. Therefore changing | ||
143 | * MAX_DEFAULT_SEND_QUEUE_DEPTH does not affect resource utilization but | ||
144 | * does impact the threshold used to identify if a packet should be | ||
145 | * dropped. */ | ||
146 | #define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC) | ||
147 | |||
148 | #define AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT 1 | ||
149 | #define AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT 1 | ||
150 | #define A_DISCONNECT_TIMER_INTERVAL 10 * 1000 | ||
151 | #define A_DEFAULT_LISTEN_INTERVAL 100 | ||
152 | #define A_MAX_WOW_LISTEN_INTERVAL 1000 | ||
153 | |||
154 | enum { | ||
155 | DRV_HB_CHALLENGE = 0, | ||
156 | APP_HB_CHALLENGE | ||
157 | }; | ||
158 | |||
159 | enum { | ||
160 | WLAN_INIT_MODE_NONE = 0, | ||
161 | WLAN_INIT_MODE_USR, | ||
162 | WLAN_INIT_MODE_UDEV, | ||
163 | WLAN_INIT_MODE_DRV | ||
164 | }; | ||
165 | |||
166 | /* Suspend - configuration */ | ||
167 | enum { | ||
168 | WLAN_SUSPEND_CUT_PWR = 0, | ||
169 | WLAN_SUSPEND_DEEP_SLEEP, | ||
170 | WLAN_SUSPEND_WOW, | ||
171 | WLAN_SUSPEND_CUT_PWR_IF_BT_OFF | ||
172 | }; | ||
173 | |||
174 | /* WiFi OFF - configuration */ | ||
175 | enum { | ||
176 | WLAN_OFF_CUT_PWR = 0, | ||
177 | WLAN_OFF_DEEP_SLEEP, | ||
178 | }; | ||
179 | |||
180 | /* WLAN low power state */ | ||
181 | enum { | ||
182 | WLAN_POWER_STATE_ON = 0, | ||
183 | WLAN_POWER_STATE_CUT_PWR = 1, | ||
184 | WLAN_POWER_STATE_DEEP_SLEEP, | ||
185 | WLAN_POWER_STATE_WOW | ||
186 | }; | ||
187 | |||
188 | /* WLAN WoW State */ | ||
189 | enum { | ||
190 | WLAN_WOW_STATE_NONE = 0, | ||
191 | WLAN_WOW_STATE_SUSPENDED, | ||
192 | WLAN_WOW_STATE_SUSPENDING | ||
193 | }; | ||
194 | |||
195 | |||
196 | typedef enum _AR6K_BIN_FILE { | ||
197 | AR6K_OTP_FILE, | ||
198 | AR6K_FIRMWARE_FILE, | ||
199 | AR6K_PATCH_FILE, | ||
200 | AR6K_BOARD_DATA_FILE, | ||
201 | } AR6K_BIN_FILE; | ||
202 | |||
203 | #ifdef SETUPHCI_ENABLED | ||
204 | #define SETUPHCI_DEFAULT 1 | ||
205 | #else | ||
206 | #define SETUPHCI_DEFAULT 0 | ||
207 | #endif /* SETUPHCI_ENABLED */ | ||
208 | |||
209 | #ifdef SETUPBTDEV_ENABLED | ||
210 | #define SETUPBTDEV_DEFAULT 1 | ||
211 | #else | ||
212 | #define SETUPBTDEV_DEFAULT 0 | ||
213 | #endif /* SETUPBTDEV_ENABLED */ | ||
214 | |||
215 | #ifdef ENABLEUARTPRINT_SET | ||
216 | #define ENABLEUARTPRINT_DEFAULT 1 | ||
217 | #else | ||
218 | #define ENABLEUARTPRINT_DEFAULT 0 | ||
219 | #endif /* ENABLEARTPRINT_SET */ | ||
220 | |||
221 | #ifdef ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER | ||
222 | #define NOHIFSCATTERSUPPORT_DEFAULT 1 | ||
223 | #else /* ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER */ | ||
224 | #define NOHIFSCATTERSUPPORT_DEFAULT 0 | ||
225 | #endif /* ATH6KL_CONFIG_HIF_VIRTUAL_SCATTER */ | ||
226 | |||
227 | |||
228 | #if defined(CONFIG_ATH6KL_ENABLE_COEXISTENCE) | ||
229 | |||
230 | #ifdef CONFIG_AR600x_BT_QCOM | ||
231 | #define ATH6KL_BT_DEV 1 | ||
232 | #elif defined(CONFIG_AR600x_BT_CSR) | ||
233 | #define ATH6KL_BT_DEV 2 | ||
234 | #else | ||
235 | #define ATH6KL_BT_DEV 3 | ||
236 | #endif | ||
237 | |||
238 | #ifdef CONFIG_AR600x_DUAL_ANTENNA | ||
239 | #define ATH6KL_BT_ANTENNA 2 | ||
240 | #else | ||
241 | #define ATH6KL_BT_ANTENNA 1 | ||
242 | #endif | ||
243 | |||
244 | #endif /* CONFIG_ATH6KL_ENABLE_COEXISTENCE */ | ||
245 | |||
246 | #ifdef AR600x_BT_AR3001 | ||
247 | #define AR3KHCIBAUD_DEFAULT 3000000 | ||
248 | #define HCIUARTSCALE_DEFAULT 1 | ||
249 | #define HCIUARTSTEP_DEFAULT 8937 | ||
250 | #else | ||
251 | #define AR3KHCIBAUD_DEFAULT 0 | ||
252 | #define HCIUARTSCALE_DEFAULT 0 | ||
253 | #define HCIUARTSTEP_DEFAULT 0 | ||
254 | #endif /* AR600x_BT_AR3001 */ | ||
255 | |||
256 | #define WLAN_INIT_MODE_DEFAULT WLAN_INIT_MODE_DRV | ||
257 | |||
258 | #define AR6K_PATCH_DOWNLOAD_ADDRESS(_param, _ver) do { \ | ||
259 | if ((_ver) == AR6003_REV1_VERSION) { \ | ||
260 | (_param) = AR6003_REV1_PATCH_DOWNLOAD_ADDRESS; \ | ||
261 | } else if ((_ver) == AR6003_REV2_VERSION) { \ | ||
262 | (_param) = AR6003_REV2_PATCH_DOWNLOAD_ADDRESS; \ | ||
263 | } else { \ | ||
264 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ | ||
265 | A_ASSERT(0); \ | ||
266 | } \ | ||
267 | } while (0) | ||
268 | |||
269 | #define AR6K_DATA_DOWNLOAD_ADDRESS(_param, _ver) do { \ | ||
270 | if ((_ver) == AR6003_REV1_VERSION) { \ | ||
271 | (_param) = AR6003_REV1_DATA_DOWNLOAD_ADDRESS; \ | ||
272 | } else if ((_ver) == AR6003_REV2_VERSION) { \ | ||
273 | (_param) = AR6003_REV2_DATA_DOWNLOAD_ADDRESS; \ | ||
274 | } else { \ | ||
275 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ | ||
276 | A_ASSERT(0); \ | ||
277 | } \ | ||
278 | } while (0) | ||
279 | |||
280 | #define AR6K_DATASET_PATCH_ADDRESS(_param, _ver) do { \ | ||
281 | if ((_ver) == AR6003_REV2_VERSION) { \ | ||
282 | (_param) = AR6003_REV2_DATASET_PATCH_ADDRESS; \ | ||
283 | } else if ((_ver) == AR6003_REV3_VERSION) { \ | ||
284 | (_param) = AR6003_REV3_DATASET_PATCH_ADDRESS; \ | ||
285 | } else { \ | ||
286 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ | ||
287 | A_ASSERT(0); \ | ||
288 | } \ | ||
289 | } while (0) | ||
290 | |||
291 | #define AR6K_APP_LOAD_ADDRESS(_param, _ver) do { \ | ||
292 | if ((_ver) == AR6003_REV2_VERSION) { \ | ||
293 | (_param) = AR6003_REV2_APP_LOAD_ADDRESS; \ | ||
294 | } else if ((_ver) == AR6003_REV3_VERSION) { \ | ||
295 | (_param) = AR6003_REV3_APP_LOAD_ADDRESS; \ | ||
296 | } else { \ | ||
297 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ | ||
298 | A_ASSERT(0); \ | ||
299 | } \ | ||
300 | } while (0) | ||
301 | |||
302 | #define AR6K_APP_START_OVERRIDE_ADDRESS(_param, _ver) do { \ | ||
303 | if ((_ver) == AR6003_REV2_VERSION) { \ | ||
304 | (_param) = AR6003_REV2_APP_START_OVERRIDE; \ | ||
305 | } else if ((_ver) == AR6003_REV3_VERSION) { \ | ||
306 | (_param) = AR6003_REV3_APP_START_OVERRIDE; \ | ||
307 | } else { \ | ||
308 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown Version: %d\n", _ver)); \ | ||
309 | A_ASSERT(0); \ | ||
310 | } \ | ||
311 | } while (0) | ||
312 | |||
313 | /* AR6003 1.0 definitions */ | ||
314 | #define AR6003_REV1_VERSION 0x300002ba | ||
315 | #define AR6003_REV1_DATA_DOWNLOAD_ADDRESS AR6003_REV1_OTP_DATA_ADDRESS | ||
316 | #define AR6003_REV1_PATCH_DOWNLOAD_ADDRESS 0x57ea6c | ||
317 | #define AR6003_REV1_OTP_FILE "ath6k/AR6003/hw1.0/otp.bin.z77" | ||
318 | #define AR6003_REV1_FIRMWARE_FILE "ath6k/AR6003/hw1.0/athwlan.bin.z77" | ||
319 | #define AR6003_REV1_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw1.0/athtcmd_ram.bin" | ||
320 | #define AR6003_REV1_ART_FIRMWARE_FILE "ath6k/AR6003/hw1.0/device.bin" | ||
321 | #define AR6003_REV1_PATCH_FILE "ath6k/AR6003/hw1.0/data.patch.bin" | ||
322 | #define AR6003_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw1.0/endpointping.bin" | ||
323 | #ifdef CONFIG_AR600x_SD31_XXX | ||
324 | #define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.SD31.bin" | ||
325 | #elif defined(CONFIG_AR600x_SD32_XXX) | ||
326 | #define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.SD32.bin" | ||
327 | #elif defined(CONFIG_AR600x_WB31_XXX) | ||
328 | #define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.WB31.bin" | ||
329 | #else | ||
330 | #define AR6003_REV1_BOARD_DATA_FILE "ath6k/AR6003/hw1.0/bdata.CUSTOM.bin" | ||
331 | #endif /* Board Data File */ | ||
332 | |||
333 | /* AR6003 2.0 definitions */ | ||
334 | #define AR6003_REV2_VERSION 0x30000384 | ||
335 | #define AR6003_REV2_DATA_DOWNLOAD_ADDRESS AR6003_REV2_OTP_DATA_ADDRESS | ||
336 | #define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910 | ||
337 | #define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" | ||
338 | #define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" | ||
339 | #define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" | ||
340 | #define AR6003_REV2_ART_FIRMWARE_FILE "ath6k/AR6003/hw2.0/device.bin" | ||
341 | #define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" | ||
342 | #define AR6003_REV2_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw2.0/endpointping.bin" | ||
343 | #ifdef CONFIG_AR600x_SD31_XXX | ||
344 | #define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin" | ||
345 | #elif defined(CONFIG_AR600x_SD32_XXX) | ||
346 | #define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD32.bin" | ||
347 | #elif defined(CONFIG_AR600x_WB31_XXX) | ||
348 | #define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.WB31.bin" | ||
349 | #else | ||
350 | #define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.CUSTOM.bin" | ||
351 | #endif /* Board Data File */ | ||
352 | |||
353 | /* AR6003 3.0 definitions */ | ||
354 | #define AR6003_REV3_VERSION 0x30000582 | ||
355 | #define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" | ||
356 | #define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" | ||
357 | #define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" | ||
358 | #define AR6003_REV3_ART_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/device.bin" | ||
359 | #define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" | ||
360 | #define AR6003_REV3_EPPING_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/endpointping.bin" | ||
361 | #ifdef CONFIG_AR600x_SD31_XXX | ||
362 | #define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" | ||
363 | #elif defined(CONFIG_AR600x_SD32_XXX) | ||
364 | #define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.SD32.bin" | ||
365 | #elif defined(CONFIG_AR600x_WB31_XXX) | ||
366 | #define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.WB31.bin" | ||
367 | #else | ||
368 | #define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.CUSTOM.bin" | ||
369 | #endif /* Board Data File */ | ||
370 | |||
371 | |||
372 | /* Power states */ | ||
373 | enum { | ||
374 | WLAN_PWR_CTRL_UP = 0, | ||
375 | WLAN_PWR_CTRL_CUT_PWR, | ||
376 | WLAN_PWR_CTRL_DEEP_SLEEP, | ||
377 | WLAN_PWR_CTRL_WOW, | ||
378 | WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED | ||
379 | }; | ||
380 | |||
381 | /* HTC RAW streams */ | ||
382 | typedef enum _HTC_RAW_STREAM_ID { | ||
383 | HTC_RAW_STREAM_NOT_MAPPED = -1, | ||
384 | HTC_RAW_STREAM_0 = 0, | ||
385 | HTC_RAW_STREAM_1 = 1, | ||
386 | HTC_RAW_STREAM_2 = 2, | ||
387 | HTC_RAW_STREAM_3 = 3, | ||
388 | HTC_RAW_STREAM_NUM_MAX | ||
389 | } HTC_RAW_STREAM_ID; | ||
390 | |||
391 | #define RAW_HTC_READ_BUFFERS_NUM 4 | ||
392 | #define RAW_HTC_WRITE_BUFFERS_NUM 4 | ||
393 | |||
394 | #define HTC_RAW_BUFFER_SIZE 1664 | ||
395 | |||
396 | typedef struct { | ||
397 | int currPtr; | ||
398 | int length; | ||
399 | unsigned char data[HTC_RAW_BUFFER_SIZE]; | ||
400 | struct htc_packet HTCPacket; | ||
401 | } raw_htc_buffer; | ||
402 | |||
403 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
404 | /* | ||
405 | * add TCMD_MODE besides wmi and bypasswmi | ||
406 | * in TCMD_MODE, only few TCMD releated wmi commands | ||
407 | * counld be hanlder | ||
408 | */ | ||
409 | enum { | ||
410 | AR6000_WMI_MODE = 0, | ||
411 | AR6000_BYPASS_MODE, | ||
412 | AR6000_TCMD_MODE, | ||
413 | AR6000_WLAN_MODE | ||
414 | }; | ||
415 | #endif /* CONFIG_HOST_TCMD_SUPPORT */ | ||
416 | |||
417 | struct ar_wep_key { | ||
418 | u8 arKeyIndex; | ||
419 | u8 arKeyLen; | ||
420 | u8 arKey[64]; | ||
421 | } ; | ||
422 | |||
423 | struct ar_key { | ||
424 | u8 key[WLAN_MAX_KEY_LEN]; | ||
425 | u8 key_len; | ||
426 | u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; | ||
427 | u8 seq_len; | ||
428 | u32 cipher; | ||
429 | }; | ||
430 | |||
431 | enum { | ||
432 | SME_DISCONNECTED, | ||
433 | SME_CONNECTING, | ||
434 | SME_CONNECTED | ||
435 | }; | ||
436 | |||
437 | struct ar_node_mapping { | ||
438 | u8 macAddress[6]; | ||
439 | u8 epId; | ||
440 | u8 txPending; | ||
441 | }; | ||
442 | |||
443 | struct ar_cookie { | ||
444 | unsigned long arc_bp[2]; /* Must be first field */ | ||
445 | struct htc_packet HtcPkt; /* HTC packet wrapper */ | ||
446 | struct ar_cookie *arc_list_next; | ||
447 | }; | ||
448 | |||
449 | struct ar_hb_chlng_resp { | ||
450 | A_TIMER timer; | ||
451 | u32 frequency; | ||
452 | u32 seqNum; | ||
453 | bool outstanding; | ||
454 | u8 missCnt; | ||
455 | u8 missThres; | ||
456 | }; | ||
457 | |||
458 | /* Per STA data, used in AP mode */ | ||
459 | /*TODO: All this should move to OS independent dir */ | ||
460 | |||
461 | #define STA_PWR_MGMT_MASK 0x1 | ||
462 | #define STA_PWR_MGMT_SHIFT 0x0 | ||
463 | #define STA_PWR_MGMT_AWAKE 0x0 | ||
464 | #define STA_PWR_MGMT_SLEEP 0x1 | ||
465 | |||
466 | #define STA_SET_PWR_SLEEP(sta) (sta->flags |= (STA_PWR_MGMT_MASK << STA_PWR_MGMT_SHIFT)) | ||
467 | #define STA_CLR_PWR_SLEEP(sta) (sta->flags &= ~(STA_PWR_MGMT_MASK << STA_PWR_MGMT_SHIFT)) | ||
468 | #define STA_IS_PWR_SLEEP(sta) ((sta->flags >> STA_PWR_MGMT_SHIFT) & STA_PWR_MGMT_MASK) | ||
469 | |||
470 | #define STA_PS_POLLED_MASK 0x1 | ||
471 | #define STA_PS_POLLED_SHIFT 0x1 | ||
472 | #define STA_SET_PS_POLLED(sta) (sta->flags |= (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT)) | ||
473 | #define STA_CLR_PS_POLLED(sta) (sta->flags &= ~(STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT)) | ||
474 | #define STA_IS_PS_POLLED(sta) (sta->flags & (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT)) | ||
475 | |||
476 | typedef struct { | ||
477 | u16 flags; | ||
478 | u8 mac[ATH_MAC_LEN]; | ||
479 | u8 aid; | ||
480 | u8 keymgmt; | ||
481 | u8 ucipher; | ||
482 | u8 auth; | ||
483 | u8 wpa_ie[IEEE80211_MAX_IE]; | ||
484 | A_NETBUF_QUEUE_T psq; /* power save q */ | ||
485 | A_MUTEX_T psqLock; | ||
486 | } sta_t; | ||
487 | |||
488 | typedef struct ar6_raw_htc { | ||
489 | HTC_ENDPOINT_ID arRaw2EpMapping[HTC_RAW_STREAM_NUM_MAX]; | ||
490 | HTC_RAW_STREAM_ID arEp2RawMapping[ENDPOINT_MAX]; | ||
491 | struct semaphore raw_htc_read_sem[HTC_RAW_STREAM_NUM_MAX]; | ||
492 | struct semaphore raw_htc_write_sem[HTC_RAW_STREAM_NUM_MAX]; | ||
493 | wait_queue_head_t raw_htc_read_queue[HTC_RAW_STREAM_NUM_MAX]; | ||
494 | wait_queue_head_t raw_htc_write_queue[HTC_RAW_STREAM_NUM_MAX]; | ||
495 | raw_htc_buffer raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM]; | ||
496 | raw_htc_buffer raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM]; | ||
497 | bool write_buffer_available[HTC_RAW_STREAM_NUM_MAX]; | ||
498 | bool read_buffer_available[HTC_RAW_STREAM_NUM_MAX]; | ||
499 | } AR_RAW_HTC_T; | ||
500 | |||
501 | struct ar6_softc { | ||
502 | struct net_device *arNetDev; /* net_device pointer */ | ||
503 | void *arWmi; | ||
504 | int arTxPending[ENDPOINT_MAX]; | ||
505 | int arTotalTxDataPending; | ||
506 | u8 arNumDataEndPts; | ||
507 | bool arWmiEnabled; | ||
508 | bool arWmiReady; | ||
509 | bool arConnected; | ||
510 | HTC_HANDLE arHtcTarget; | ||
511 | void *arHifDevice; | ||
512 | spinlock_t arLock; | ||
513 | struct semaphore arSem; | ||
514 | int arSsidLen; | ||
515 | u_char arSsid[32]; | ||
516 | u8 arNextMode; | ||
517 | u8 arNetworkType; | ||
518 | u8 arDot11AuthMode; | ||
519 | u8 arAuthMode; | ||
520 | u8 arPairwiseCrypto; | ||
521 | u8 arPairwiseCryptoLen; | ||
522 | u8 arGroupCrypto; | ||
523 | u8 arGroupCryptoLen; | ||
524 | u8 arDefTxKeyIndex; | ||
525 | struct ar_wep_key arWepKeyList[WMI_MAX_KEY_INDEX + 1]; | ||
526 | u8 arBssid[6]; | ||
527 | u8 arReqBssid[6]; | ||
528 | u16 arChannelHint; | ||
529 | u16 arBssChannel; | ||
530 | u16 arListenIntervalB; | ||
531 | u16 arListenIntervalT; | ||
532 | struct ar6000_version arVersion; | ||
533 | u32 arTargetType; | ||
534 | s8 arRssi; | ||
535 | u8 arTxPwr; | ||
536 | bool arTxPwrSet; | ||
537 | s32 arBitRate; | ||
538 | struct net_device_stats arNetStats; | ||
539 | struct iw_statistics arIwStats; | ||
540 | s8 arNumChannels; | ||
541 | u16 arChannelList[32]; | ||
542 | u32 arRegCode; | ||
543 | bool statsUpdatePending; | ||
544 | TARGET_STATS arTargetStats; | ||
545 | s8 arMaxRetries; | ||
546 | u8 arPhyCapability; | ||
547 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
548 | u32 arTargetMode; | ||
549 | void *tcmd_rx_report; | ||
550 | int tcmd_rx_report_len; | ||
551 | #endif | ||
552 | AR6000_WLAN_STATE arWlanState; | ||
553 | struct ar_node_mapping arNodeMap[MAX_NODE_NUM]; | ||
554 | u8 arIbssPsEnable; | ||
555 | u8 arNodeNum; | ||
556 | u8 arNexEpId; | ||
557 | struct ar_cookie *arCookieList; | ||
558 | u32 arCookieCount; | ||
559 | u32 arRateMask; | ||
560 | u8 arSkipScan; | ||
561 | u16 arBeaconInterval; | ||
562 | bool arConnectPending; | ||
563 | bool arWmmEnabled; | ||
564 | struct ar_hb_chlng_resp arHBChallengeResp; | ||
565 | u8 arKeepaliveConfigured; | ||
566 | u32 arMgmtFilter; | ||
567 | HTC_ENDPOINT_ID arAc2EpMapping[WMM_NUM_AC]; | ||
568 | bool arAcStreamActive[WMM_NUM_AC]; | ||
569 | u8 arAcStreamPriMap[WMM_NUM_AC]; | ||
570 | u8 arHiAcStreamActivePri; | ||
571 | u8 arEp2AcMapping[ENDPOINT_MAX]; | ||
572 | HTC_ENDPOINT_ID arControlEp; | ||
573 | #ifdef HTC_RAW_INTERFACE | ||
574 | AR_RAW_HTC_T *arRawHtc; | ||
575 | #endif | ||
576 | bool arNetQueueStopped; | ||
577 | bool arRawIfInit; | ||
578 | int arDeviceIndex; | ||
579 | struct common_credit_state_info arCreditStateInfo; | ||
580 | bool arWMIControlEpFull; | ||
581 | bool dbgLogFetchInProgress; | ||
582 | u8 log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE]; | ||
583 | u32 log_cnt; | ||
584 | u32 dbglog_init_done; | ||
585 | u32 arConnectCtrlFlags; | ||
586 | s32 user_savedkeys_stat; | ||
587 | u32 user_key_ctrl; | ||
588 | struct USER_SAVEDKEYS user_saved_keys; | ||
589 | USER_RSSI_THOLD rssi_map[12]; | ||
590 | u8 arUserBssFilter; | ||
591 | u16 ap_profile_flag; /* AP mode */ | ||
592 | WMI_AP_ACL g_acl; /* AP mode */ | ||
593 | sta_t sta_list[AP_MAX_NUM_STA]; /* AP mode */ | ||
594 | u8 sta_list_index; /* AP mode */ | ||
595 | struct ieee80211req_key ap_mode_bkey; /* AP mode */ | ||
596 | A_NETBUF_QUEUE_T mcastpsq; /* power save q for Mcast frames */ | ||
597 | A_MUTEX_T mcastpsqLock; | ||
598 | bool DTIMExpired; /* flag to indicate DTIM expired */ | ||
599 | u8 intra_bss; /* enable/disable intra bss data forward */ | ||
600 | void *aggr_cntxt; | ||
601 | #ifndef EXPORT_HCI_BRIDGE_INTERFACE | ||
602 | void *hcidev_info; | ||
603 | #endif | ||
604 | WMI_AP_MODE_STAT arAPStats; | ||
605 | u8 ap_hidden_ssid; | ||
606 | u8 ap_country_code[3]; | ||
607 | u8 ap_wmode; | ||
608 | u8 ap_dtim_period; | ||
609 | u16 ap_beacon_interval; | ||
610 | u16 arRTS; | ||
611 | u16 arACS; /* AP mode - Auto Channel Selection */ | ||
612 | struct htc_packet_queue amsdu_rx_buffer_queue; | ||
613 | bool bIsDestroyProgress; /* flag to indicate ar6k destroy is in progress */ | ||
614 | A_TIMER disconnect_timer; | ||
615 | u8 rxMetaVersion; | ||
616 | #ifdef WAPI_ENABLE | ||
617 | u8 arWapiEnable; | ||
618 | #endif | ||
619 | WMI_BTCOEX_CONFIG_EVENT arBtcoexConfig; | ||
620 | WMI_BTCOEX_STATS_EVENT arBtcoexStats; | ||
621 | s32 (*exitCallback)(void *config); /* generic callback at AR6K exit */ | ||
622 | struct hif_device_os_device_info osDevInfo; | ||
623 | struct wireless_dev *wdev; | ||
624 | struct cfg80211_scan_request *scan_request; | ||
625 | struct ar_key keys[WMI_MAX_KEY_INDEX + 1]; | ||
626 | u32 smeState; | ||
627 | u16 arWlanPowerState; | ||
628 | bool arWlanOff; | ||
629 | #ifdef CONFIG_PM | ||
630 | u16 arWowState; | ||
631 | bool arBTOff; | ||
632 | bool arBTSharing; | ||
633 | u16 arSuspendConfig; | ||
634 | u16 arWlanOffConfig; | ||
635 | u16 arWow2Config; | ||
636 | #endif | ||
637 | u8 scan_triggered; | ||
638 | WMI_SCAN_PARAMS_CMD scParams; | ||
639 | #define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 | ||
640 | u8 mcast_filters[MAC_MAX_FILTERS_PER_LIST][AR_MCAST_FILTER_MAC_ADDR_SIZE]; | ||
641 | u8 bdaddr[6]; | ||
642 | bool scanSpecificSsid; | ||
643 | #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT | ||
644 | void *arApDev; | ||
645 | #endif | ||
646 | u8 arAutoAuthStage; | ||
647 | |||
648 | u8 *fw_otp; | ||
649 | size_t fw_otp_len; | ||
650 | u8 *fw; | ||
651 | size_t fw_len; | ||
652 | u8 *fw_patch; | ||
653 | size_t fw_patch_len; | ||
654 | u8 *fw_data; | ||
655 | size_t fw_data_len; | ||
656 | }; | ||
657 | |||
658 | #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT | ||
659 | struct ar_virtual_interface { | ||
660 | struct net_device *arNetDev; /* net_device pointer */ | ||
661 | struct ar6_softc *arDev; /* ar device pointer */ | ||
662 | struct net_device *arStaNetDev; /* net_device pointer */ | ||
663 | }; | ||
664 | #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ | ||
665 | |||
666 | static inline void *ar6k_priv(struct net_device *dev) | ||
667 | { | ||
668 | return (wdev_priv(dev->ieee80211_ptr)); | ||
669 | } | ||
670 | |||
671 | #define SET_HCI_BUS_TYPE(pHciDev, __bus, __type) do { \ | ||
672 | (pHciDev)->bus = (__bus); \ | ||
673 | (pHciDev)->dev_type = (__type); \ | ||
674 | } while(0) | ||
675 | |||
676 | #define GET_INODE_FROM_FILEP(filp) \ | ||
677 | (filp)->f_path.dentry->d_inode | ||
678 | |||
679 | #define arAc2EndpointID(ar,ac) (ar)->arAc2EpMapping[(ac)] | ||
680 | #define arSetAc2EndpointIDMap(ar,ac,ep) \ | ||
681 | { (ar)->arAc2EpMapping[(ac)] = (ep); \ | ||
682 | (ar)->arEp2AcMapping[(ep)] = (ac); } | ||
683 | #define arEndpoint2Ac(ar,ep) (ar)->arEp2AcMapping[(ep)] | ||
684 | |||
685 | #define arRawIfEnabled(ar) (ar)->arRawIfInit | ||
686 | #define arRawStream2EndpointID(ar,raw) (ar)->arRawHtc->arRaw2EpMapping[(raw)] | ||
687 | #define arSetRawStream2EndpointIDMap(ar,raw,ep) \ | ||
688 | { (ar)->arRawHtc->arRaw2EpMapping[(raw)] = (ep); \ | ||
689 | (ar)->arRawHtc->arEp2RawMapping[(ep)] = (raw); } | ||
690 | #define arEndpoint2RawStreamID(ar,ep) (ar)->arRawHtc->arEp2RawMapping[(ep)] | ||
691 | |||
692 | struct ar_giwscan_param { | ||
693 | char *current_ev; | ||
694 | char *end_buf; | ||
695 | u32 bytes_needed; | ||
696 | struct iw_request_info *info; | ||
697 | }; | ||
698 | |||
699 | #define AR6000_STAT_INC(ar, stat) (ar->arNetStats.stat++) | ||
700 | |||
701 | #define AR6000_SPIN_LOCK(lock, param) do { \ | ||
702 | if (irqs_disabled()) { \ | ||
703 | AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("IRQs disabled:AR6000_LOCK\n")); \ | ||
704 | } \ | ||
705 | spin_lock_bh(lock); \ | ||
706 | } while (0) | ||
707 | |||
708 | #define AR6000_SPIN_UNLOCK(lock, param) do { \ | ||
709 | if (irqs_disabled()) { \ | ||
710 | AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("IRQs disabled: AR6000_UNLOCK\n")); \ | ||
711 | } \ | ||
712 | spin_unlock_bh(lock); \ | ||
713 | } while (0) | ||
714 | |||
715 | void ar6000_init_profile_info(struct ar6_softc *ar); | ||
716 | void ar6000_install_static_wep_keys(struct ar6_softc *ar); | ||
717 | int ar6000_init(struct net_device *dev); | ||
718 | int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar); | ||
719 | void ar6000_TxDataCleanup(struct ar6_softc *ar); | ||
720 | int ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev); | ||
721 | void ar6000_restart_endpoint(struct net_device *dev); | ||
722 | void ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs); | ||
723 | |||
724 | #ifdef HTC_RAW_INTERFACE | ||
725 | |||
726 | #ifndef __user | ||
727 | #define __user | ||
728 | #endif | ||
729 | |||
730 | int ar6000_htc_raw_open(struct ar6_softc *ar); | ||
731 | int ar6000_htc_raw_close(struct ar6_softc *ar); | ||
732 | ssize_t ar6000_htc_raw_read(struct ar6_softc *ar, | ||
733 | HTC_RAW_STREAM_ID StreamID, | ||
734 | char __user *buffer, size_t count); | ||
735 | ssize_t ar6000_htc_raw_write(struct ar6_softc *ar, | ||
736 | HTC_RAW_STREAM_ID StreamID, | ||
737 | char __user *buffer, size_t count); | ||
738 | |||
739 | #endif /* HTC_RAW_INTERFACE */ | ||
740 | |||
741 | /* AP mode */ | ||
742 | /*TODO: These routines should be moved to a file that is common across OS */ | ||
743 | sta_t * | ||
744 | ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr); | ||
745 | |||
746 | sta_t * | ||
747 | ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid); | ||
748 | |||
749 | u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason); | ||
750 | |||
751 | /* HCI support */ | ||
752 | |||
753 | #ifndef EXPORT_HCI_BRIDGE_INTERFACE | ||
754 | int ar6000_setup_hci(struct ar6_softc *ar); | ||
755 | void ar6000_cleanup_hci(struct ar6_softc *ar); | ||
756 | void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig); | ||
757 | |||
758 | /* HCI bridge testing */ | ||
759 | int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb); | ||
760 | #endif | ||
761 | |||
762 | ATH_DEBUG_DECLARE_EXTERN(htc); | ||
763 | ATH_DEBUG_DECLARE_EXTERN(wmi); | ||
764 | ATH_DEBUG_DECLARE_EXTERN(bmi); | ||
765 | ATH_DEBUG_DECLARE_EXTERN(hif); | ||
766 | ATH_DEBUG_DECLARE_EXTERN(wlan); | ||
767 | ATH_DEBUG_DECLARE_EXTERN(misc); | ||
768 | |||
769 | extern u8 bcast_mac[]; | ||
770 | extern u8 null_mac[]; | ||
771 | |||
772 | #ifdef __cplusplus | ||
773 | } | ||
774 | #endif | ||
775 | |||
776 | #endif /* _AR6000_H_ */ | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h b/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h new file mode 100644 index 00000000000..39e0873aff2 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h | |||
@@ -0,0 +1,36 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. | ||
3 | // | ||
4 | // The software source and binaries included in this development package are | ||
5 | // licensed, not sold. You, or your company, received the package under one | ||
6 | // or more license agreements. The rights granted to you are specifically | ||
7 | // listed in these license agreement(s). All other rights remain with Atheros | ||
8 | // Communications, Inc., its subsidiaries, or the respective owner including | ||
9 | // those listed on the included copyright notices. Distribution of any | ||
10 | // portion of this package must be in strict compliance with the license | ||
11 | // agreement(s) terms. | ||
12 | // </copyright> | ||
13 | // | ||
14 | // <summary> | ||
15 | // PAL driver for AR6003 | ||
16 | // </summary> | ||
17 | // | ||
18 | //------------------------------------------------------------------------------ | ||
19 | //============================================================================== | ||
20 | // Author(s): ="Atheros" | ||
21 | //============================================================================== | ||
22 | #ifndef _AR6K_PAL_H_ | ||
23 | #define _AR6K_PAL_H_ | ||
24 | #define HCI_GET_OP_CODE(p) (((u16)((p)[1])) << 8) | ((u16)((p)[0])) | ||
25 | |||
26 | /* transmit packet reserve offset */ | ||
27 | #define TX_PACKET_RSV_OFFSET 32 | ||
28 | /* pal specific config structure */ | ||
29 | typedef bool (*ar6k_pal_recv_pkt_t)(void *pHciPalInfo, void *skb); | ||
30 | typedef struct ar6k_pal_config_s | ||
31 | { | ||
32 | ar6k_pal_recv_pkt_t fpar6k_pal_recv_pkt; | ||
33 | }ar6k_pal_config_t; | ||
34 | |||
35 | void register_pal_cb(ar6k_pal_config_t *palConfig_p); | ||
36 | #endif /* _AR6K_PAL_H_ */ | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h b/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h new file mode 100644 index 00000000000..184dbdb5049 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h | |||
@@ -0,0 +1,190 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #ifndef _AR6XAPI_LINUX_H | ||
25 | #define _AR6XAPI_LINUX_H | ||
26 | #ifdef __cplusplus | ||
27 | extern "C" { | ||
28 | #endif | ||
29 | |||
30 | struct ar6_softc; | ||
31 | |||
32 | void ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, | ||
33 | u32 sw_ver, u32 abi_ver); | ||
34 | int ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid); | ||
35 | void ar6000_connect_event(struct ar6_softc *ar, u16 channel, | ||
36 | u8 *bssid, u16 listenInterval, | ||
37 | u16 beaconInterval, NETWORK_TYPE networkType, | ||
38 | u8 beaconIeLen, u8 assocReqLen, | ||
39 | u8 assocRespLen,u8 *assocInfo); | ||
40 | void ar6000_disconnect_event(struct ar6_softc *ar, u8 reason, | ||
41 | u8 *bssid, u8 assocRespLen, | ||
42 | u8 *assocInfo, u16 protocolReasonStatus); | ||
43 | void ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, | ||
44 | bool ismcast); | ||
45 | void ar6000_bitrate_rx(void *devt, s32 rateKbps); | ||
46 | void ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList); | ||
47 | void ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode); | ||
48 | void ar6000_txPwr_rx(void *devt, u8 txPwr); | ||
49 | void ar6000_keepalive_rx(void *devt, u8 configured); | ||
50 | void ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, | ||
51 | WMI_NEIGHBOR_INFO *info); | ||
52 | void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num); | ||
53 | void ar6000_scanComplete_event(struct ar6_softc *ar, int status); | ||
54 | void ar6000_targetStats_event(struct ar6_softc *ar, u8 *ptr, u32 len); | ||
55 | void ar6000_rssiThreshold_event(struct ar6_softc *ar, | ||
56 | WMI_RSSI_THRESHOLD_VAL newThreshold, | ||
57 | s16 rssi); | ||
58 | void ar6000_reportError_event(struct ar6_softc *, WMI_TARGET_ERROR_VAL errorVal); | ||
59 | void ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cac_indication, | ||
60 | u8 statusCode, u8 *tspecSuggestion); | ||
61 | void ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel, u16 newChannel); | ||
62 | void ar6000_hbChallengeResp_event(struct ar6_softc *, u32 cookie, u32 source); | ||
63 | void | ||
64 | ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl); | ||
65 | |||
66 | void | ||
67 | ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p); | ||
68 | |||
69 | void | ||
70 | ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters, | ||
71 | WMI_GET_WOW_LIST_REPLY *wow_reply); | ||
72 | |||
73 | void ar6000_pmkid_list_event(void *devt, u8 numPMKID, | ||
74 | WMI_PMKID *pmkidList, u8 *bssidList); | ||
75 | |||
76 | void ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values); | ||
77 | void ar6000_gpio_data_rx(u32 reg_id, u32 value); | ||
78 | void ar6000_gpio_ack_rx(void); | ||
79 | |||
80 | s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt); | ||
81 | s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi); | ||
82 | s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above); | ||
83 | |||
84 | void ar6000_dbglog_init_done(struct ar6_softc *ar); | ||
85 | |||
86 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
87 | void ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len); | ||
88 | #endif | ||
89 | |||
90 | void ar6000_tx_retry_err_event(void *devt); | ||
91 | |||
92 | void ar6000_snrThresholdEvent_rx(void *devt, | ||
93 | WMI_SNR_THRESHOLD_VAL newThreshold, | ||
94 | u8 snr); | ||
95 | |||
96 | void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, u8 lqVal); | ||
97 | |||
98 | |||
99 | void ar6000_ratemask_rx(void *devt, u32 ratemask); | ||
100 | |||
101 | int ar6000_get_driver_cfg(struct net_device *dev, | ||
102 | u16 cfgParam, | ||
103 | void *result); | ||
104 | void ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *data, int len); | ||
105 | |||
106 | void ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped, | ||
107 | s8 *buffer, u32 length); | ||
108 | |||
109 | int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar); | ||
110 | |||
111 | void ar6000_peer_event(void *devt, u8 eventCode, u8 *bssid); | ||
112 | |||
113 | void ar6000_indicate_tx_activity(void *devt, u8 trafficClass, bool Active); | ||
114 | HTC_ENDPOINT_ID ar6000_ac2_endpoint_id ( void * devt, u8 ac); | ||
115 | u8 ar6000_endpoint_id2_ac (void * devt, HTC_ENDPOINT_ID ep ); | ||
116 | |||
117 | void ar6000_btcoex_config_event(struct ar6_softc *ar, u8 *ptr, u32 len); | ||
118 | |||
119 | void ar6000_btcoex_stats_event(struct ar6_softc *ar, u8 *ptr, u32 len) ; | ||
120 | |||
121 | void ar6000_dset_open_req(void *devt, | ||
122 | u32 id, | ||
123 | u32 targ_handle, | ||
124 | u32 targ_reply_fn, | ||
125 | u32 targ_reply_arg); | ||
126 | void ar6000_dset_close(void *devt, u32 access_cookie); | ||
127 | void ar6000_dset_data_req(void *devt, | ||
128 | u32 access_cookie, | ||
129 | u32 offset, | ||
130 | u32 length, | ||
131 | u32 targ_buf, | ||
132 | u32 targ_reply_fn, | ||
133 | u32 targ_reply_arg); | ||
134 | |||
135 | |||
136 | #if defined(CONFIG_TARGET_PROFILE_SUPPORT) | ||
137 | void prof_count_rx(unsigned int addr, unsigned int count); | ||
138 | #endif | ||
139 | |||
140 | u32 ar6000_getnodeAge (void); | ||
141 | |||
142 | u32 ar6000_getclkfreq (void); | ||
143 | |||
144 | int ar6000_ap_mode_profile_commit(struct ar6_softc *ar); | ||
145 | |||
146 | struct ieee80211req_wpaie; | ||
147 | int | ||
148 | ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie); | ||
149 | |||
150 | int is_iwioctl_allowed(u8 mode, u16 cmd); | ||
151 | |||
152 | int is_xioctl_allowed(u8 mode, int cmd); | ||
153 | |||
154 | void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid); | ||
155 | |||
156 | void ar6000_dtimexpiry_event(struct ar6_softc *ar); | ||
157 | |||
158 | void ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *cmd); | ||
159 | void ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *cmd); | ||
160 | void ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *cmd); | ||
161 | void ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd); | ||
162 | |||
163 | #ifdef WAPI_ENABLE | ||
164 | int ap_set_wapi_key(struct ar6_softc *ar, void *ik); | ||
165 | void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac); | ||
166 | #endif | ||
167 | |||
168 | int ar6000_connect_to_ap(struct ar6_softc *ar); | ||
169 | int ar6000_disconnect(struct ar6_softc *ar); | ||
170 | int ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool suspending); | ||
171 | int ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state); | ||
172 | int ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 state); | ||
173 | |||
174 | #ifdef CONFIG_PM | ||
175 | int ar6000_suspend_ev(void *context); | ||
176 | int ar6000_resume_ev(void *context); | ||
177 | int ar6000_power_change_ev(void *context, u32 config); | ||
178 | void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent); | ||
179 | #endif | ||
180 | |||
181 | #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT | ||
182 | int ar6000_add_ap_interface(struct ar6_softc *ar, char *ifname); | ||
183 | int ar6000_remove_ap_interface(struct ar6_softc *ar); | ||
184 | #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */ | ||
185 | |||
186 | #ifdef __cplusplus | ||
187 | } | ||
188 | #endif | ||
189 | |||
190 | #endif | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h b/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h new file mode 100644 index 00000000000..3d5f01da543 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h | |||
@@ -0,0 +1,1217 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #ifndef _ATHDRV_LINUX_H | ||
25 | #define _ATHDRV_LINUX_H | ||
26 | |||
27 | #ifdef __cplusplus | ||
28 | extern "C" { | ||
29 | #endif | ||
30 | |||
31 | |||
32 | /* | ||
33 | * There are two types of ioctl's here: Standard ioctls and | ||
34 | * eXtended ioctls. All extended ioctls (XIOCTL) are multiplexed | ||
35 | * off of the single ioctl command, AR6000_IOCTL_EXTENDED. The | ||
36 | * arguments for every XIOCTL starts with a 32-bit command word | ||
37 | * that is used to select which extended ioctl is in use. After | ||
38 | * the command word are command-specific arguments. | ||
39 | */ | ||
40 | |||
41 | /* Linux standard Wireless Extensions, private ioctl interfaces */ | ||
42 | #define IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) | ||
43 | #define IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+1) | ||
44 | #define IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+2) | ||
45 | #define IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+3) | ||
46 | #define IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+4) | ||
47 | #define IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+5) | ||
48 | //#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+6) | ||
49 | //#define IEEE80211_IOCTL_SETWMMPARAMS (SIOCIWFIRSTPRIV+7) | ||
50 | //#define IEEE80211_IOCTL_GETWMMPARAMS (SIOCIWFIRSTPRIV+8) | ||
51 | //#define IEEE80211_IOCTL_GETOPTIE (SIOCIWFIRSTPRIV+9) | ||
52 | //#define IEEE80211_IOCTL_SETAUTHALG (SIOCIWFIRSTPRIV+10) | ||
53 | #define IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+10) | ||
54 | |||
55 | |||
56 | |||
57 | /* ====WMI Ioctls==== */ | ||
58 | /* | ||
59 | * | ||
60 | * Many ioctls simply provide WMI services to application code: | ||
61 | * an application makes such an ioctl call with a set of arguments | ||
62 | * that are packaged into the corresponding WMI message, and sent | ||
63 | * to the Target. | ||
64 | */ | ||
65 | |||
66 | #define AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+11) | ||
67 | /* | ||
68 | * arguments: | ||
69 | * ar6000_version *revision | ||
70 | */ | ||
71 | |||
72 | #define AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+12) | ||
73 | /* | ||
74 | * arguments: | ||
75 | * WMI_POWER_MODE_CMD pwrModeCmd (see include/wmi.h) | ||
76 | * uses: WMI_SET_POWER_MODE_CMDID | ||
77 | */ | ||
78 | |||
79 | #define AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+13) | ||
80 | /* | ||
81 | * arguments: | ||
82 | * WMI_SCAN_PARAMS_CMD scanParams (see include/wmi.h) | ||
83 | * uses: WMI_SET_SCAN_PARAMS_CMDID | ||
84 | */ | ||
85 | |||
86 | #define AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+14) | ||
87 | /* | ||
88 | * arguments: | ||
89 | * UINT32 listenInterval | ||
90 | * uses: WMI_SET_LISTEN_INT_CMDID | ||
91 | */ | ||
92 | |||
93 | #define AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+15) | ||
94 | /* | ||
95 | * arguments: | ||
96 | * WMI_BSS_FILTER filter (see include/wmi.h) | ||
97 | * uses: WMI_SET_BSS_FILTER_CMDID | ||
98 | */ | ||
99 | |||
100 | #define AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16) | ||
101 | /* | ||
102 | * arguments: | ||
103 | * WMI_CHANNEL_PARAMS_CMD chParams | ||
104 | * uses: WMI_SET_CHANNEL_PARAMS_CMDID | ||
105 | */ | ||
106 | |||
107 | #define AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17) | ||
108 | /* | ||
109 | * arguments: | ||
110 | * WMI_PROBED_SSID_CMD probedSsids (see include/wmi.h) | ||
111 | * uses: WMI_SETPROBED_SSID_CMDID | ||
112 | */ | ||
113 | |||
114 | #define AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18) | ||
115 | /* | ||
116 | * arguments: | ||
117 | * WMI_POWER_PARAMS_CMD powerParams (see include/wmi.h) | ||
118 | * uses: WMI_SET_POWER_PARAMS_CMDID | ||
119 | */ | ||
120 | |||
121 | #define AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19) | ||
122 | /* | ||
123 | * arguments: | ||
124 | * WMI_ADD_BAD_AP_CMD badAPs (see include/wmi.h) | ||
125 | * uses: WMI_ADD_BAD_AP_CMDID | ||
126 | */ | ||
127 | |||
128 | #define AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20) | ||
129 | /* | ||
130 | * arguments: | ||
131 | * ar6000_queuereq queueRequest (see below) | ||
132 | */ | ||
133 | |||
134 | #define AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21) | ||
135 | /* | ||
136 | * arguments: | ||
137 | * WMI_CREATE_PSTREAM createPstreamCmd (see include/wmi.h) | ||
138 | * uses: WMI_CREATE_PSTREAM_CMDID | ||
139 | */ | ||
140 | |||
141 | #define AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22) | ||
142 | /* | ||
143 | * arguments: | ||
144 | * WMI_DELETE_PSTREAM_CMD deletePstreamCmd (see include/wmi.h) | ||
145 | * uses: WMI_DELETE_PSTREAM_CMDID | ||
146 | */ | ||
147 | |||
148 | #define AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23) | ||
149 | /* | ||
150 | * arguments: | ||
151 | * WMI_SNR_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) | ||
152 | * uses: WMI_SNR_THRESHOLD_PARAMS_CMDID | ||
153 | */ | ||
154 | |||
155 | #define AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24) | ||
156 | /* | ||
157 | * arguments: | ||
158 | * WMI_TARGET_ERROR_REPORT_BITMASK errorReportBitMask (see include/wmi.h) | ||
159 | * uses: WMI_TARGET_ERROR_REPORT_BITMASK_CMDID | ||
160 | */ | ||
161 | |||
162 | #define AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25) | ||
163 | /* | ||
164 | * arguments: | ||
165 | * TARGET_STATS *targetStats (see below) | ||
166 | * uses: WMI_GET_STATISTICS_CMDID | ||
167 | */ | ||
168 | |||
169 | #define AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26) | ||
170 | /* | ||
171 | * arguments: | ||
172 | * WMI_SET_ASSOC_INFO_CMD setAssocInfoCmd | ||
173 | * uses: WMI_SET_ASSOC_INFO_CMDID | ||
174 | */ | ||
175 | |||
176 | #define AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27) | ||
177 | /* | ||
178 | * arguments: | ||
179 | * WMI_SET_ACCESS_PARAMS_CMD setAccessParams (see include/wmi.h) | ||
180 | * uses: WMI_SET_ACCESS_PARAMS_CMDID | ||
181 | */ | ||
182 | |||
183 | #define AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28) | ||
184 | /* | ||
185 | * arguments: | ||
186 | * UINT32 beaconMissTime | ||
187 | * uses: WMI_SET_BMISS_TIME_CMDID | ||
188 | */ | ||
189 | |||
190 | #define AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29) | ||
191 | /* | ||
192 | * arguments: | ||
193 | * WMI_DISC_TIMEOUT_CMD disconnectTimeoutCmd (see include/wmi.h) | ||
194 | * uses: WMI_SET_DISC_TIMEOUT_CMDID | ||
195 | */ | ||
196 | |||
197 | #define AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30) | ||
198 | /* | ||
199 | * arguments: | ||
200 | * WMI_IBSS_PM_CAPS_CMD ibssPowerMgmtCapsCmd | ||
201 | * uses: WMI_SET_IBSS_PM_CAPS_CMDID | ||
202 | */ | ||
203 | |||
204 | /* | ||
205 | * There is a very small space available for driver-private | ||
206 | * wireless ioctls. In order to circumvent this limitation, | ||
207 | * we multiplex a bunch of ioctls (XIOCTLs) on top of a | ||
208 | * single AR6000_IOCTL_EXTENDED ioctl. | ||
209 | */ | ||
210 | #define AR6000_IOCTL_EXTENDED (SIOCIWFIRSTPRIV+31) | ||
211 | |||
212 | |||
213 | /* ====BMI Extended Ioctls==== */ | ||
214 | |||
215 | #define AR6000_XIOCTL_BMI_DONE 1 | ||
216 | /* | ||
217 | * arguments: | ||
218 | * UINT32 cmd (AR6000_XIOCTL_BMI_DONE) | ||
219 | * uses: BMI_DONE | ||
220 | */ | ||
221 | |||
222 | #define AR6000_XIOCTL_BMI_READ_MEMORY 2 | ||
223 | /* | ||
224 | * arguments: | ||
225 | * union { | ||
226 | * struct { | ||
227 | * UINT32 cmd (AR6000_XIOCTL_BMI_READ_MEMORY) | ||
228 | * UINT32 address | ||
229 | * UINT32 length | ||
230 | * } | ||
231 | * char results[length] | ||
232 | * } | ||
233 | * uses: BMI_READ_MEMORY | ||
234 | */ | ||
235 | |||
236 | #define AR6000_XIOCTL_BMI_WRITE_MEMORY 3 | ||
237 | /* | ||
238 | * arguments: | ||
239 | * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_MEMORY) | ||
240 | * UINT32 address | ||
241 | * UINT32 length | ||
242 | * char data[length] | ||
243 | * uses: BMI_WRITE_MEMORY | ||
244 | */ | ||
245 | |||
246 | #define AR6000_XIOCTL_BMI_EXECUTE 4 | ||
247 | /* | ||
248 | * arguments: | ||
249 | * UINT32 cmd (AR6000_XIOCTL_BMI_EXECUTE) | ||
250 | * UINT32 TargetAddress | ||
251 | * UINT32 parameter | ||
252 | * uses: BMI_EXECUTE | ||
253 | */ | ||
254 | |||
255 | #define AR6000_XIOCTL_BMI_SET_APP_START 5 | ||
256 | /* | ||
257 | * arguments: | ||
258 | * UINT32 cmd (AR6000_XIOCTL_BMI_SET_APP_START) | ||
259 | * UINT32 TargetAddress | ||
260 | * uses: BMI_SET_APP_START | ||
261 | */ | ||
262 | |||
263 | #define AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6 | ||
264 | /* | ||
265 | * arguments: | ||
266 | * union { | ||
267 | * struct { | ||
268 | * UINT32 cmd (AR6000_XIOCTL_BMI_READ_SOC_REGISTER) | ||
269 | * UINT32 TargetAddress, 32-bit aligned | ||
270 | * } | ||
271 | * UINT32 result | ||
272 | * } | ||
273 | * uses: BMI_READ_SOC_REGISTER | ||
274 | */ | ||
275 | |||
276 | #define AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7 | ||
277 | /* | ||
278 | * arguments: | ||
279 | * struct { | ||
280 | * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER) | ||
281 | * UINT32 TargetAddress, 32-bit aligned | ||
282 | * UINT32 newValue | ||
283 | * } | ||
284 | * uses: BMI_WRITE_SOC_REGISTER | ||
285 | */ | ||
286 | |||
287 | #define AR6000_XIOCTL_BMI_TEST 8 | ||
288 | /* | ||
289 | * arguments: | ||
290 | * UINT32 cmd (AR6000_XIOCTL_BMI_TEST) | ||
291 | * UINT32 address | ||
292 | * UINT32 length | ||
293 | * UINT32 count | ||
294 | */ | ||
295 | |||
296 | |||
297 | |||
298 | /* Historical Host-side DataSet support */ | ||
299 | #define AR6000_XIOCTL_UNUSED9 9 | ||
300 | #define AR6000_XIOCTL_UNUSED10 10 | ||
301 | #define AR6000_XIOCTL_UNUSED11 11 | ||
302 | |||
303 | /* ====Misc Extended Ioctls==== */ | ||
304 | |||
305 | #define AR6000_XIOCTL_FORCE_TARGET_RESET 12 | ||
306 | /* | ||
307 | * arguments: | ||
308 | * UINT32 cmd (AR6000_XIOCTL_FORCE_TARGET_RESET) | ||
309 | */ | ||
310 | |||
311 | |||
312 | #ifdef HTC_RAW_INTERFACE | ||
313 | /* HTC Raw Interface Ioctls */ | ||
314 | #define AR6000_XIOCTL_HTC_RAW_OPEN 13 | ||
315 | /* | ||
316 | * arguments: | ||
317 | * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_OPEN) | ||
318 | */ | ||
319 | |||
320 | #define AR6000_XIOCTL_HTC_RAW_CLOSE 14 | ||
321 | /* | ||
322 | * arguments: | ||
323 | * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_CLOSE) | ||
324 | */ | ||
325 | |||
326 | #define AR6000_XIOCTL_HTC_RAW_READ 15 | ||
327 | /* | ||
328 | * arguments: | ||
329 | * union { | ||
330 | * struct { | ||
331 | * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_READ) | ||
332 | * UINT32 mailboxID | ||
333 | * UINT32 length | ||
334 | * } | ||
335 | * results[length] | ||
336 | * } | ||
337 | */ | ||
338 | |||
339 | #define AR6000_XIOCTL_HTC_RAW_WRITE 16 | ||
340 | /* | ||
341 | * arguments: | ||
342 | * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_WRITE) | ||
343 | * UINT32 mailboxID | ||
344 | * UINT32 length | ||
345 | * char buffer[length] | ||
346 | */ | ||
347 | #endif /* HTC_RAW_INTERFACE */ | ||
348 | |||
349 | #define AR6000_XIOCTL_CHECK_TARGET_READY 17 | ||
350 | /* | ||
351 | * arguments: | ||
352 | * UINT32 cmd (AR6000_XIOCTL_CHECK_TARGET_READY) | ||
353 | */ | ||
354 | |||
355 | |||
356 | |||
357 | /* ====GPIO (General Purpose I/O) Extended Ioctls==== */ | ||
358 | |||
359 | #define AR6000_XIOCTL_GPIO_OUTPUT_SET 18 | ||
360 | /* | ||
361 | * arguments: | ||
362 | * UINT32 cmd (AR6000_XIOCTL_GPIO_OUTPUT_SET) | ||
363 | * ar6000_gpio_output_set_cmd_s (see below) | ||
364 | * uses: WMIX_GPIO_OUTPUT_SET_CMDID | ||
365 | */ | ||
366 | |||
367 | #define AR6000_XIOCTL_GPIO_INPUT_GET 19 | ||
368 | /* | ||
369 | * arguments: | ||
370 | * UINT32 cmd (AR6000_XIOCTL_GPIO_INPUT_GET) | ||
371 | * uses: WMIX_GPIO_INPUT_GET_CMDID | ||
372 | */ | ||
373 | |||
374 | #define AR6000_XIOCTL_GPIO_REGISTER_SET 20 | ||
375 | /* | ||
376 | * arguments: | ||
377 | * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_SET) | ||
378 | * ar6000_gpio_register_cmd_s (see below) | ||
379 | * uses: WMIX_GPIO_REGISTER_SET_CMDID | ||
380 | */ | ||
381 | |||
382 | #define AR6000_XIOCTL_GPIO_REGISTER_GET 21 | ||
383 | /* | ||
384 | * arguments: | ||
385 | * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_GET) | ||
386 | * ar6000_gpio_register_cmd_s (see below) | ||
387 | * uses: WMIX_GPIO_REGISTER_GET_CMDID | ||
388 | */ | ||
389 | |||
390 | #define AR6000_XIOCTL_GPIO_INTR_ACK 22 | ||
391 | /* | ||
392 | * arguments: | ||
393 | * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_ACK) | ||
394 | * ar6000_cpio_intr_ack_cmd_s (see below) | ||
395 | * uses: WMIX_GPIO_INTR_ACK_CMDID | ||
396 | */ | ||
397 | |||
398 | #define AR6000_XIOCTL_GPIO_INTR_WAIT 23 | ||
399 | /* | ||
400 | * arguments: | ||
401 | * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_WAIT) | ||
402 | */ | ||
403 | |||
404 | |||
405 | |||
406 | /* ====more wireless commands==== */ | ||
407 | |||
408 | #define AR6000_XIOCTL_SET_ADHOC_BSSID 24 | ||
409 | /* | ||
410 | * arguments: | ||
411 | * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BSSID) | ||
412 | * WMI_SET_ADHOC_BSSID_CMD setAdHocBssidCmd (see include/wmi.h) | ||
413 | */ | ||
414 | |||
415 | #define AR6000_XIOCTL_SET_OPT_MODE 25 | ||
416 | /* | ||
417 | * arguments: | ||
418 | * UINT32 cmd (AR6000_XIOCTL_SET_OPT_MODE) | ||
419 | * WMI_SET_OPT_MODE_CMD setOptModeCmd (see include/wmi.h) | ||
420 | * uses: WMI_SET_OPT_MODE_CMDID | ||
421 | */ | ||
422 | |||
423 | #define AR6000_XIOCTL_OPT_SEND_FRAME 26 | ||
424 | /* | ||
425 | * arguments: | ||
426 | * UINT32 cmd (AR6000_XIOCTL_OPT_SEND_FRAME) | ||
427 | * WMI_OPT_TX_FRAME_CMD optTxFrameCmd (see include/wmi.h) | ||
428 | * uses: WMI_OPT_TX_FRAME_CMDID | ||
429 | */ | ||
430 | |||
431 | #define AR6000_XIOCTL_SET_BEACON_INTVAL 27 | ||
432 | /* | ||
433 | * arguments: | ||
434 | * UINT32 cmd (AR6000_XIOCTL_SET_BEACON_INTVAL) | ||
435 | * WMI_BEACON_INT_CMD beaconIntCmd (see include/wmi.h) | ||
436 | * uses: WMI_SET_BEACON_INT_CMDID | ||
437 | */ | ||
438 | |||
439 | |||
440 | #define IEEE80211_IOCTL_SETAUTHALG 28 | ||
441 | |||
442 | |||
443 | #define AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29 | ||
444 | /* | ||
445 | * arguments: | ||
446 | * UINT32 cmd (AR6000_XIOCTL_SET_VOICE_PKT_SIZE) | ||
447 | * WMI_SET_VOICE_PKT_SIZE_CMD setVoicePktSizeCmd (see include/wmi.h) | ||
448 | * uses: WMI_SET_VOICE_PKT_SIZE_CMDID | ||
449 | */ | ||
450 | |||
451 | |||
452 | #define AR6000_XIOCTL_SET_MAX_SP 30 | ||
453 | /* | ||
454 | * arguments: | ||
455 | * UINT32 cmd (AR6000_XIOCTL_SET_MAX_SP) | ||
456 | * WMI_SET_MAX_SP_LEN_CMD maxSPLen(see include/wmi.h) | ||
457 | * uses: WMI_SET_MAX_SP_LEN_CMDID | ||
458 | */ | ||
459 | |||
460 | #define AR6000_XIOCTL_WMI_GET_ROAM_TBL 31 | ||
461 | |||
462 | #define AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32 | ||
463 | |||
464 | #define AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33 | ||
465 | |||
466 | |||
467 | /* | ||
468 | * arguments: | ||
469 | * UINT32 cmd (AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS) | ||
470 | * WMI_SET_POWERSAVE_TIMERS_CMD powerSaveTimers(see include/wmi.h) | ||
471 | * WMI_SET_POWERSAVE_TIMERS_CMDID | ||
472 | */ | ||
473 | |||
474 | #define AR6000_XIOCTRL_WMI_GET_POWER_MODE 34 | ||
475 | /* | ||
476 | * arguments: | ||
477 | * UINT32 cmd (AR6000_XIOCTRL_WMI_GET_POWER_MODE) | ||
478 | */ | ||
479 | |||
480 | #define AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35 | ||
481 | typedef enum { | ||
482 | WLAN_DISABLED, | ||
483 | WLAN_ENABLED | ||
484 | } AR6000_WLAN_STATE; | ||
485 | /* | ||
486 | * arguments: | ||
487 | * enable/disable | ||
488 | */ | ||
489 | |||
490 | #define AR6000_XIOCTL_WMI_GET_ROAM_DATA 36 | ||
491 | |||
492 | #define AR6000_XIOCTL_WMI_SETRETRYLIMITS 37 | ||
493 | /* | ||
494 | * arguments: | ||
495 | * WMI_SET_RETRY_LIMITS_CMD ibssSetRetryLimitsCmd | ||
496 | * uses: WMI_SET_RETRY_LIMITS_CMDID | ||
497 | */ | ||
498 | |||
499 | #ifdef CONFIG_HOST_TCMD_SUPPORT | ||
500 | /* ====extended commands for radio test ==== */ | ||
501 | |||
502 | #define AR6000_XIOCTL_TCMD_CONT_TX 38 | ||
503 | /* | ||
504 | * arguments: | ||
505 | * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_TX) | ||
506 | * WMI_TCMD_CONT_TX_CMD contTxCmd (see include/wmi.h) | ||
507 | * uses: WMI_TCMD_CONT_TX_CMDID | ||
508 | */ | ||
509 | |||
510 | #define AR6000_XIOCTL_TCMD_CONT_RX 39 | ||
511 | /* | ||
512 | * arguments: | ||
513 | * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_RX) | ||
514 | * WMI_TCMD_CONT_RX_CMD rxCmd (see include/wmi.h) | ||
515 | * uses: WMI_TCMD_CONT_RX_CMDID | ||
516 | */ | ||
517 | |||
518 | #define AR6000_XIOCTL_TCMD_PM 40 | ||
519 | /* | ||
520 | * arguments: | ||
521 | * UINT32 cmd (AR6000_XIOCTL_TCMD_PM) | ||
522 | * WMI_TCMD_PM_CMD pmCmd (see include/wmi.h) | ||
523 | * uses: WMI_TCMD_PM_CMDID | ||
524 | */ | ||
525 | |||
526 | #endif /* CONFIG_HOST_TCMD_SUPPORT */ | ||
527 | |||
528 | #define AR6000_XIOCTL_WMI_STARTSCAN 41 | ||
529 | /* | ||
530 | * arguments: | ||
531 | * UINT32 cmd (AR6000_XIOCTL_WMI_STARTSCAN) | ||
532 | * UINT8 scanType | ||
533 | * UINT8 scanConnected | ||
534 | * u32 forceFgScan | ||
535 | * uses: WMI_START_SCAN_CMDID | ||
536 | */ | ||
537 | |||
538 | #define AR6000_XIOCTL_WMI_SETFIXRATES 42 | ||
539 | |||
540 | #define AR6000_XIOCTL_WMI_GETFIXRATES 43 | ||
541 | |||
542 | |||
543 | #define AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44 | ||
544 | /* | ||
545 | * arguments: | ||
546 | * WMI_RSSI_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) | ||
547 | * uses: WMI_RSSI_THRESHOLD_PARAMS_CMDID | ||
548 | */ | ||
549 | |||
550 | #define AR6000_XIOCTL_WMI_CLR_RSSISNR 45 | ||
551 | /* | ||
552 | * arguments: | ||
553 | * WMI_CLR_RSSISNR_CMD thresholdParams (see include/wmi.h) | ||
554 | * uses: WMI_CLR_RSSISNR_CMDID | ||
555 | */ | ||
556 | |||
557 | #define AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46 | ||
558 | /* | ||
559 | * arguments: | ||
560 | * WMI_LQ_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) | ||
561 | * uses: WMI_LQ_THRESHOLD_PARAMS_CMDID | ||
562 | */ | ||
563 | |||
564 | #define AR6000_XIOCTL_WMI_SET_RTS 47 | ||
565 | /* | ||
566 | * arguments: | ||
567 | * WMI_SET_RTS_MODE_CMD (see include/wmi.h) | ||
568 | * uses: WMI_SET_RTS_MODE_CMDID | ||
569 | */ | ||
570 | |||
571 | #define AR6000_XIOCTL_WMI_SET_LPREAMBLE 48 | ||
572 | |||
573 | #define AR6000_XIOCTL_WMI_SET_AUTHMODE 49 | ||
574 | /* | ||
575 | * arguments: | ||
576 | * UINT32 cmd (AR6000_XIOCTL_WMI_SET_AUTHMODE) | ||
577 | * UINT8 mode | ||
578 | * uses: WMI_SET_RECONNECT_AUTH_MODE_CMDID | ||
579 | */ | ||
580 | |||
581 | #define AR6000_XIOCTL_WMI_SET_REASSOCMODE 50 | ||
582 | |||
583 | /* | ||
584 | * arguments: | ||
585 | * UINT32 cmd (AR6000_XIOCTL_WMI_SET_WMM) | ||
586 | * UINT8 mode | ||
587 | * uses: WMI_SET_WMM_CMDID | ||
588 | */ | ||
589 | #define AR6000_XIOCTL_WMI_SET_WMM 51 | ||
590 | |||
591 | /* | ||
592 | * arguments: | ||
593 | * UINT32 cmd (AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS) | ||
594 | * UINT32 frequency | ||
595 | * UINT8 threshold | ||
596 | */ | ||
597 | #define AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52 | ||
598 | |||
599 | /* | ||
600 | * arguments: | ||
601 | * UINT32 cmd (AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP) | ||
602 | * UINT32 cookie | ||
603 | */ | ||
604 | #define AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53 | ||
605 | |||
606 | /* | ||
607 | * arguments: | ||
608 | * UINT32 cmd (AR6000_XIOCTL_WMI_GET_RD) | ||
609 | * UINT32 regDomain | ||
610 | */ | ||
611 | #define AR6000_XIOCTL_WMI_GET_RD 54 | ||
612 | |||
613 | #define AR6000_XIOCTL_DIAG_READ 55 | ||
614 | |||
615 | #define AR6000_XIOCTL_DIAG_WRITE 56 | ||
616 | |||
617 | /* | ||
618 | * arguments cmd (AR6000_XIOCTL_SET_TXOP) | ||
619 | * WMI_TXOP_CFG txopEnable | ||
620 | */ | ||
621 | #define AR6000_XIOCTL_WMI_SET_TXOP 57 | ||
622 | |||
623 | /* | ||
624 | * arguments: | ||
625 | * UINT32 cmd (AR6000_XIOCTL_USER_SETKEYS) | ||
626 | * UINT32 keyOpCtrl | ||
627 | * uses struct ar6000_user_setkeys_info | ||
628 | */ | ||
629 | #define AR6000_XIOCTL_USER_SETKEYS 58 | ||
630 | |||
631 | #define AR6000_XIOCTL_WMI_SET_KEEPALIVE 59 | ||
632 | /* | ||
633 | * arguments: | ||
634 | * UINT8 cmd (AR6000_XIOCTL_WMI_SET_KEEPALIVE) | ||
635 | * UINT8 keepaliveInterval | ||
636 | * uses: WMI_SET_KEEPALIVE_CMDID | ||
637 | */ | ||
638 | |||
639 | #define AR6000_XIOCTL_WMI_GET_KEEPALIVE 60 | ||
640 | /* | ||
641 | * arguments: | ||
642 | * UINT8 cmd (AR6000_XIOCTL_WMI_GET_KEEPALIVE) | ||
643 | * UINT8 keepaliveInterval | ||
644 | * u32 configured | ||
645 | * uses: WMI_GET_KEEPALIVE_CMDID | ||
646 | */ | ||
647 | |||
648 | /* ====ROM Patching Extended Ioctls==== */ | ||
649 | |||
650 | #define AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61 | ||
651 | /* | ||
652 | * arguments: | ||
653 | * union { | ||
654 | * struct { | ||
655 | * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_INSTALL) | ||
656 | * UINT32 ROM Address | ||
657 | * UINT32 RAM Address | ||
658 | * UINT32 number of bytes | ||
659 | * UINT32 activate? (0 or 1) | ||
660 | * } | ||
661 | * u32 resulting rompatch ID | ||
662 | * } | ||
663 | * uses: BMI_ROMPATCH_INSTALL | ||
664 | */ | ||
665 | |||
666 | #define AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62 | ||
667 | /* | ||
668 | * arguments: | ||
669 | * struct { | ||
670 | * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL) | ||
671 | * UINT32 rompatch ID | ||
672 | * } | ||
673 | * uses: BMI_ROMPATCH_UNINSTALL | ||
674 | */ | ||
675 | |||
676 | #define AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63 | ||
677 | /* | ||
678 | * arguments: | ||
679 | * struct { | ||
680 | * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) | ||
681 | * UINT32 rompatch count | ||
682 | * UINT32 rompatch IDs[rompatch count] | ||
683 | * } | ||
684 | * uses: BMI_ROMPATCH_ACTIVATE | ||
685 | */ | ||
686 | |||
687 | #define AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64 | ||
688 | /* | ||
689 | * arguments: | ||
690 | * struct { | ||
691 | * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE) | ||
692 | * UINT32 rompatch count | ||
693 | * UINT32 rompatch IDs[rompatch count] | ||
694 | * } | ||
695 | * uses: BMI_ROMPATCH_DEACTIVATE | ||
696 | */ | ||
697 | |||
698 | #define AR6000_XIOCTL_WMI_SET_APPIE 65 | ||
699 | /* | ||
700 | * arguments: | ||
701 | * struct { | ||
702 | * UINT32 cmd (AR6000_XIOCTL_WMI_SET_APPIE) | ||
703 | * UINT32 app_frmtype; | ||
704 | * UINT32 app_buflen; | ||
705 | * UINT8 app_buf[]; | ||
706 | * } | ||
707 | */ | ||
708 | #define AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66 | ||
709 | /* | ||
710 | * arguments: | ||
711 | * u32 filter_type; | ||
712 | */ | ||
713 | |||
714 | #define AR6000_XIOCTL_DBGLOG_CFG_MODULE 67 | ||
715 | |||
716 | #define AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68 | ||
717 | |||
718 | #define AR6000_XIOCTL_WMI_SET_WSC_STATUS 70 | ||
719 | /* | ||
720 | * arguments: | ||
721 | * u32 wsc_status; | ||
722 | * (WSC_REG_INACTIVE or WSC_REG_ACTIVE) | ||
723 | */ | ||
724 | |||
725 | /* | ||
726 | * arguments: | ||
727 | * struct { | ||
728 | * u8 streamType; | ||
729 | * u8 status; | ||
730 | * } | ||
731 | * uses: WMI_SET_BT_STATUS_CMDID | ||
732 | */ | ||
733 | #define AR6000_XIOCTL_WMI_SET_BT_STATUS 71 | ||
734 | |||
735 | /* | ||
736 | * arguments: | ||
737 | * struct { | ||
738 | * u8 paramType; | ||
739 | * union { | ||
740 | * u8 noSCOPkts; | ||
741 | * BT_PARAMS_A2DP a2dpParams; | ||
742 | * BT_COEX_REGS regs; | ||
743 | * }; | ||
744 | * } | ||
745 | * uses: WMI_SET_BT_PARAM_CMDID | ||
746 | */ | ||
747 | #define AR6000_XIOCTL_WMI_SET_BT_PARAMS 72 | ||
748 | |||
749 | #define AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73 | ||
750 | #define AR6000_XIOCTL_WMI_SET_WOW_MODE 74 | ||
751 | #define AR6000_XIOCTL_WMI_GET_WOW_LIST 75 | ||
752 | #define AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76 | ||
753 | #define AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77 | ||
754 | |||
755 | |||
756 | |||
757 | #define AR6000_XIOCTL_TARGET_INFO 78 | ||
758 | /* | ||
759 | * arguments: | ||
760 | * UINT32 cmd (AR6000_XIOCTL_TARGET_INFO) | ||
761 | * u32 TargetVersion (returned) | ||
762 | * u32 TargetType (returned) | ||
763 | * (See also bmi_msg.h target_ver and target_type) | ||
764 | */ | ||
765 | |||
766 | #define AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79 | ||
767 | /* | ||
768 | * arguments: | ||
769 | * none | ||
770 | */ | ||
771 | |||
772 | #define AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80 | ||
773 | /* | ||
774 | * This ioctl is used to emulate traffic activity | ||
775 | * timeouts. Activity/inactivity will trigger the driver | ||
776 | * to re-balance credits. | ||
777 | * | ||
778 | * arguments: | ||
779 | * ar6000_traffic_activity_change | ||
780 | */ | ||
781 | |||
782 | #define AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81 | ||
783 | /* | ||
784 | * This ioctl is used to set the connect control flags | ||
785 | * | ||
786 | * arguments: | ||
787 | * u32 connectCtrlFlags | ||
788 | */ | ||
789 | |||
790 | #define AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82 | ||
791 | /* | ||
792 | * This IOCTL sets any Authentication,Key Management and Protection | ||
793 | * related parameters. This is used along with the information set in | ||
794 | * Connect Command. | ||
795 | * Currently this enables Multiple PMKIDs to an AP. | ||
796 | * | ||
797 | * arguments: | ||
798 | * struct { | ||
799 | * u32 akmpInfo; | ||
800 | * } | ||
801 | * uses: WMI_SET_AKMP_PARAMS_CMD | ||
802 | */ | ||
803 | |||
804 | #define AR6000_XIOCTL_WMI_GET_PMKID_LIST 83 | ||
805 | |||
806 | #define AR6000_XIOCTL_WMI_SET_PMKID_LIST 84 | ||
807 | /* | ||
808 | * This IOCTL is used to set a list of PMKIDs. This list of | ||
809 | * PMKIDs is used in the [Re]AssocReq Frame. This list is used | ||
810 | * only if the MultiPMKID option is enabled via the | ||
811 | * AR6000_XIOCTL_WMI_SET_AKMP_PARAMS IOCTL. | ||
812 | * | ||
813 | * arguments: | ||
814 | * struct { | ||
815 | * u32 numPMKID; | ||
816 | * WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE]; | ||
817 | * } | ||
818 | * uses: WMI_SET_PMKIDLIST_CMD | ||
819 | */ | ||
820 | |||
821 | #define AR6000_XIOCTL_WMI_SET_PARAMS 85 | ||
822 | #define AR6000_XIOCTL_WMI_SET_MCAST_FILTER 86 | ||
823 | #define AR6000_XIOCTL_WMI_DEL_MCAST_FILTER 87 | ||
824 | |||
825 | |||
826 | /* Historical DSETPATCH support for INI patches */ | ||
827 | #define AR6000_XIOCTL_UNUSED90 90 | ||
828 | |||
829 | |||
830 | /* Support LZ-compressed firmware download */ | ||
831 | #define AR6000_XIOCTL_BMI_LZ_STREAM_START 91 | ||
832 | /* | ||
833 | * arguments: | ||
834 | * UINT32 cmd (AR6000_XIOCTL_BMI_LZ_STREAM_START) | ||
835 | * UINT32 address | ||
836 | * uses: BMI_LZ_STREAM_START | ||
837 | */ | ||
838 | |||
839 | #define AR6000_XIOCTL_BMI_LZ_DATA 92 | ||
840 | /* | ||
841 | * arguments: | ||
842 | * UINT32 cmd (AR6000_XIOCTL_BMI_LZ_DATA) | ||
843 | * UINT32 length | ||
844 | * char data[length] | ||
845 | * uses: BMI_LZ_DATA | ||
846 | */ | ||
847 | |||
848 | #define AR6000_XIOCTL_PROF_CFG 93 | ||
849 | /* | ||
850 | * arguments: | ||
851 | * u32 period | ||
852 | * u32 nbins | ||
853 | */ | ||
854 | |||
855 | #define AR6000_XIOCTL_PROF_ADDR_SET 94 | ||
856 | /* | ||
857 | * arguments: | ||
858 | * u32 Target address | ||
859 | */ | ||
860 | |||
861 | #define AR6000_XIOCTL_PROF_START 95 | ||
862 | |||
863 | #define AR6000_XIOCTL_PROF_STOP 96 | ||
864 | |||
865 | #define AR6000_XIOCTL_PROF_COUNT_GET 97 | ||
866 | |||
867 | #define AR6000_XIOCTL_WMI_ABORT_SCAN 98 | ||
868 | |||
869 | /* | ||
870 | * AP mode | ||
871 | */ | ||
872 | #define AR6000_XIOCTL_AP_GET_STA_LIST 99 | ||
873 | |||
874 | #define AR6000_XIOCTL_AP_HIDDEN_SSID 100 | ||
875 | |||
876 | #define AR6000_XIOCTL_AP_SET_NUM_STA 101 | ||
877 | |||
878 | #define AR6000_XIOCTL_AP_SET_ACL_MAC 102 | ||
879 | |||
880 | #define AR6000_XIOCTL_AP_GET_ACL_LIST 103 | ||
881 | |||
882 | #define AR6000_XIOCTL_AP_COMMIT_CONFIG 104 | ||
883 | |||
884 | #define IEEE80211_IOCTL_GETWPAIE 105 | ||
885 | |||
886 | #define AR6000_XIOCTL_AP_CONN_INACT_TIME 106 | ||
887 | |||
888 | #define AR6000_XIOCTL_AP_PROT_SCAN_TIME 107 | ||
889 | |||
890 | #define AR6000_XIOCTL_AP_SET_COUNTRY 108 | ||
891 | |||
892 | #define AR6000_XIOCTL_AP_SET_DTIM 109 | ||
893 | |||
894 | |||
895 | |||
896 | |||
897 | #define AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT 110 | ||
898 | |||
899 | #define AR6000_XIOCTL_SET_IP 111 | ||
900 | |||
901 | #define AR6000_XIOCTL_AP_SET_ACL_POLICY 112 | ||
902 | |||
903 | #define AR6000_XIOCTL_AP_INTRA_BSS_COMM 113 | ||
904 | |||
905 | #define AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO 114 | ||
906 | |||
907 | #define AR6000_XIOCTL_MODULE_DEBUG_SET_MASK 115 | ||
908 | |||
909 | #define AR6000_XIOCTL_MODULE_DEBUG_GET_MASK 116 | ||
910 | |||
911 | #define AR6000_XIOCTL_DUMP_RCV_AGGR_STATS 117 | ||
912 | |||
913 | #define AR6000_XIOCTL_SET_HT_CAP 118 | ||
914 | |||
915 | #define AR6000_XIOCTL_SET_HT_OP 119 | ||
916 | |||
917 | #define AR6000_XIOCTL_AP_GET_STAT 120 | ||
918 | |||
919 | #define AR6000_XIOCTL_SET_TX_SELECT_RATES 121 | ||
920 | |||
921 | #define AR6000_XIOCTL_SETUP_AGGR 122 | ||
922 | |||
923 | #define AR6000_XIOCTL_ALLOW_AGGR 123 | ||
924 | |||
925 | #define AR6000_XIOCTL_AP_GET_HIDDEN_SSID 124 | ||
926 | |||
927 | #define AR6000_XIOCTL_AP_GET_COUNTRY 125 | ||
928 | |||
929 | #define AR6000_XIOCTL_AP_GET_WMODE 126 | ||
930 | |||
931 | #define AR6000_XIOCTL_AP_GET_DTIM 127 | ||
932 | |||
933 | #define AR6000_XIOCTL_AP_GET_BINTVL 128 | ||
934 | |||
935 | #define AR6000_XIOCTL_AP_GET_RTS 129 | ||
936 | |||
937 | #define AR6000_XIOCTL_DELE_AGGR 130 | ||
938 | |||
939 | #define AR6000_XIOCTL_FETCH_TARGET_REGS 131 | ||
940 | |||
941 | #define AR6000_XIOCTL_HCI_CMD 132 | ||
942 | |||
943 | #define AR6000_XIOCTL_ACL_DATA 133 /* used to be used for PAL */ | ||
944 | |||
945 | #define AR6000_XIOCTL_WLAN_CONN_PRECEDENCE 134 | ||
946 | |||
947 | #define AR6000_XIOCTL_AP_SET_11BG_RATESET 135 | ||
948 | |||
949 | /* | ||
950 | * arguments: | ||
951 | * WMI_AP_PS_CMD apPsCmd | ||
952 | * uses: WMI_AP_PS_CMDID | ||
953 | */ | ||
954 | |||
955 | #define AR6000_XIOCTL_WMI_SET_AP_PS 136 | ||
956 | |||
957 | #define AR6000_XIOCTL_WMI_MCAST_FILTER 137 | ||
958 | |||
959 | #define AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT 138 | ||
960 | |||
961 | #define AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV 139 | ||
962 | |||
963 | #define AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG 140 | ||
964 | |||
965 | #define AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG 141 | ||
966 | |||
967 | #define AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG 142 | ||
968 | |||
969 | #define AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG 143 | ||
970 | |||
971 | #define AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG 144 | ||
972 | |||
973 | #define AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS 145 | ||
974 | |||
975 | #define AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG 146 | ||
976 | |||
977 | #define AR6000_XIOCTL_WMI_GET_BTCOEX_STATS 147 | ||
978 | /* | ||
979 | * arguments: | ||
980 | * UINT32 cmd (AR6000_XIOCTL_WMI_SET_QOS_SUPP) | ||
981 | * UINT8 mode | ||
982 | * uses: WMI_SET_QOS_SUPP_CMDID | ||
983 | */ | ||
984 | #define AR6000_XIOCTL_WMI_SET_QOS_SUPP 148 | ||
985 | |||
986 | #define AR6000_XIOCTL_GET_WLAN_SLEEP_STATE 149 | ||
987 | |||
988 | #define AR6000_XIOCTL_SET_BT_HW_POWER_STATE 150 | ||
989 | |||
990 | #define AR6000_XIOCTL_GET_BT_HW_POWER_STATE 151 | ||
991 | |||
992 | #define AR6000_XIOCTL_ADD_AP_INTERFACE 152 | ||
993 | |||
994 | #define AR6000_XIOCTL_REMOVE_AP_INTERFACE 153 | ||
995 | |||
996 | #define AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM 154 | ||
997 | |||
998 | #define AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES 161 | ||
999 | |||
1000 | /* used by AR6000_IOCTL_WMI_GETREV */ | ||
1001 | struct ar6000_version { | ||
1002 | u32 host_ver; | ||
1003 | u32 target_ver; | ||
1004 | u32 wlan_ver; | ||
1005 | u32 abi_ver; | ||
1006 | }; | ||
1007 | |||
1008 | /* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */ | ||
1009 | struct ar6000_queuereq { | ||
1010 | u8 trafficClass; | ||
1011 | u16 activeTsids; | ||
1012 | }; | ||
1013 | |||
1014 | /* used by AR6000_IOCTL_WMI_GET_TARGET_STATS */ | ||
1015 | typedef struct targetStats_t { | ||
1016 | u64 tx_packets; | ||
1017 | u64 tx_bytes; | ||
1018 | u64 tx_unicast_pkts; | ||
1019 | u64 tx_unicast_bytes; | ||
1020 | u64 tx_multicast_pkts; | ||
1021 | u64 tx_multicast_bytes; | ||
1022 | u64 tx_broadcast_pkts; | ||
1023 | u64 tx_broadcast_bytes; | ||
1024 | u64 tx_rts_success_cnt; | ||
1025 | u64 tx_packet_per_ac[4]; | ||
1026 | |||
1027 | u64 tx_errors; | ||
1028 | u64 tx_failed_cnt; | ||
1029 | u64 tx_retry_cnt; | ||
1030 | u64 tx_mult_retry_cnt; | ||
1031 | u64 tx_rts_fail_cnt; | ||
1032 | |||
1033 | u64 rx_packets; | ||
1034 | u64 rx_bytes; | ||
1035 | u64 rx_unicast_pkts; | ||
1036 | u64 rx_unicast_bytes; | ||
1037 | u64 rx_multicast_pkts; | ||
1038 | u64 rx_multicast_bytes; | ||
1039 | u64 rx_broadcast_pkts; | ||
1040 | u64 rx_broadcast_bytes; | ||
1041 | u64 rx_fragment_pkt; | ||
1042 | |||
1043 | u64 rx_errors; | ||
1044 | u64 rx_crcerr; | ||
1045 | u64 rx_key_cache_miss; | ||
1046 | u64 rx_decrypt_err; | ||
1047 | u64 rx_duplicate_frames; | ||
1048 | |||
1049 | u64 tkip_local_mic_failure; | ||
1050 | u64 tkip_counter_measures_invoked; | ||
1051 | u64 tkip_replays; | ||
1052 | u64 tkip_format_errors; | ||
1053 | u64 ccmp_format_errors; | ||
1054 | u64 ccmp_replays; | ||
1055 | |||
1056 | u64 power_save_failure_cnt; | ||
1057 | |||
1058 | u64 cs_bmiss_cnt; | ||
1059 | u64 cs_lowRssi_cnt; | ||
1060 | u64 cs_connect_cnt; | ||
1061 | u64 cs_disconnect_cnt; | ||
1062 | |||
1063 | s32 tx_unicast_rate; | ||
1064 | s32 rx_unicast_rate; | ||
1065 | |||
1066 | u32 lq_val; | ||
1067 | |||
1068 | u32 wow_num_pkts_dropped; | ||
1069 | u16 wow_num_events_discarded; | ||
1070 | |||
1071 | s16 noise_floor_calibation; | ||
1072 | s16 cs_rssi; | ||
1073 | s16 cs_aveBeacon_rssi; | ||
1074 | u8 cs_aveBeacon_snr; | ||
1075 | u8 cs_lastRoam_msec; | ||
1076 | u8 cs_snr; | ||
1077 | |||
1078 | u8 wow_num_host_pkt_wakeups; | ||
1079 | u8 wow_num_host_event_wakeups; | ||
1080 | |||
1081 | u32 arp_received; | ||
1082 | u32 arp_matched; | ||
1083 | u32 arp_replied; | ||
1084 | }TARGET_STATS; | ||
1085 | |||
1086 | typedef struct targetStats_cmd_t { | ||
1087 | TARGET_STATS targetStats; | ||
1088 | int clearStats; | ||
1089 | } TARGET_STATS_CMD; | ||
1090 | |||
1091 | /* used by AR6000_XIOCTL_USER_SETKEYS */ | ||
1092 | |||
1093 | /* | ||
1094 | * Setting this bit to 1 doesnot initialize the RSC on the firmware | ||
1095 | */ | ||
1096 | #define AR6000_XIOCTL_USER_SETKEYS_RSC_CTRL 1 | ||
1097 | #define AR6000_USER_SETKEYS_RSC_UNCHANGED 0x00000002 | ||
1098 | |||
1099 | struct ar6000_user_setkeys_info { | ||
1100 | u32 keyOpCtrl; /* Bit Map of Key Mgmt Ctrl Flags */ | ||
1101 | }; /* XXX: unused !? */ | ||
1102 | |||
1103 | /* used by AR6000_XIOCTL_GPIO_OUTPUT_SET */ | ||
1104 | struct ar6000_gpio_output_set_cmd_s { | ||
1105 | u32 set_mask; | ||
1106 | u32 clear_mask; | ||
1107 | u32 enable_mask; | ||
1108 | u32 disable_mask; | ||
1109 | }; | ||
1110 | |||
1111 | /* | ||
1112 | * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET | ||
1113 | */ | ||
1114 | struct ar6000_gpio_register_cmd_s { | ||
1115 | u32 gpioreg_id; | ||
1116 | u32 value; | ||
1117 | }; | ||
1118 | |||
1119 | /* used by AR6000_XIOCTL_GPIO_INTR_ACK */ | ||
1120 | struct ar6000_gpio_intr_ack_cmd_s { | ||
1121 | u32 ack_mask; | ||
1122 | }; | ||
1123 | |||
1124 | /* used by AR6000_XIOCTL_GPIO_INTR_WAIT */ | ||
1125 | struct ar6000_gpio_intr_wait_cmd_s { | ||
1126 | u32 intr_mask; | ||
1127 | u32 input_values; | ||
1128 | }; | ||
1129 | |||
1130 | /* used by the AR6000_XIOCTL_DBGLOG_CFG_MODULE */ | ||
1131 | typedef struct ar6000_dbglog_module_config_s { | ||
1132 | u32 valid; | ||
1133 | u16 mmask; | ||
1134 | u16 tsr; | ||
1135 | u32 rep; | ||
1136 | u16 size; | ||
1137 | } DBGLOG_MODULE_CONFIG; | ||
1138 | |||
1139 | typedef struct user_rssi_thold_t { | ||
1140 | s16 tag; | ||
1141 | s16 rssi; | ||
1142 | } USER_RSSI_THOLD; | ||
1143 | |||
1144 | typedef struct user_rssi_params_t { | ||
1145 | u8 weight; | ||
1146 | u32 pollTime; | ||
1147 | USER_RSSI_THOLD tholds[12]; | ||
1148 | } USER_RSSI_PARAMS; | ||
1149 | |||
1150 | typedef struct ar6000_get_btcoex_config_cmd_t{ | ||
1151 | u32 btProfileType; | ||
1152 | u32 linkId; | ||
1153 | }AR6000_GET_BTCOEX_CONFIG_CMD; | ||
1154 | |||
1155 | typedef struct ar6000_btcoex_config_t { | ||
1156 | AR6000_GET_BTCOEX_CONFIG_CMD configCmd; | ||
1157 | u32 *configEvent; | ||
1158 | } AR6000_BTCOEX_CONFIG; | ||
1159 | |||
1160 | typedef struct ar6000_btcoex_stats_t { | ||
1161 | u32 *statsEvent; | ||
1162 | }AR6000_BTCOEX_STATS; | ||
1163 | /* | ||
1164 | * Host driver may have some config parameters. Typically, these | ||
1165 | * config params are one time config parameters. These could | ||
1166 | * correspond to any of the underlying modules. Host driver exposes | ||
1167 | * an api for the underlying modules to get this config. | ||
1168 | */ | ||
1169 | #define AR6000_DRIVER_CFG_BASE 0x8000 | ||
1170 | |||
1171 | /* Should driver perform wlan node caching? */ | ||
1172 | #define AR6000_DRIVER_CFG_GET_WLANNODECACHING 0x8001 | ||
1173 | /*Should we log raw WMI msgs */ | ||
1174 | #define AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS 0x8002 | ||
1175 | |||
1176 | /* used by AR6000_XIOCTL_DIAG_READ & AR6000_XIOCTL_DIAG_WRITE */ | ||
1177 | struct ar6000_diag_window_cmd_s { | ||
1178 | unsigned int addr; | ||
1179 | unsigned int value; | ||
1180 | }; | ||
1181 | |||
1182 | |||
1183 | struct ar6000_traffic_activity_change { | ||
1184 | u32 StreamID; /* stream ID to indicate activity change */ | ||
1185 | u32 Active; /* active (1) or inactive (0) */ | ||
1186 | }; | ||
1187 | |||
1188 | /* Used with AR6000_XIOCTL_PROF_COUNT_GET */ | ||
1189 | struct prof_count_s { | ||
1190 | u32 addr; /* bin start address */ | ||
1191 | u32 count; /* hit count */ | ||
1192 | }; | ||
1193 | |||
1194 | |||
1195 | /* used by AR6000_XIOCTL_MODULE_DEBUG_SET_MASK */ | ||
1196 | /* AR6000_XIOCTL_MODULE_DEBUG_GET_MASK */ | ||
1197 | /* AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO */ | ||
1198 | struct drv_debug_module_s { | ||
1199 | char modulename[128]; /* name of module */ | ||
1200 | u32 mask; /* new mask to set .. or .. current mask */ | ||
1201 | }; | ||
1202 | |||
1203 | |||
1204 | /* All HCI related rx events are sent up to the host app | ||
1205 | * via a wmi event id. It can contain ACL data or HCI event, | ||
1206 | * based on which it will be de-multiplexed. | ||
1207 | */ | ||
1208 | typedef enum { | ||
1209 | PAL_HCI_EVENT = 0, | ||
1210 | PAL_HCI_RX_DATA, | ||
1211 | } WMI_PAL_EVENT_INFO; | ||
1212 | |||
1213 | |||
1214 | #ifdef __cplusplus | ||
1215 | } | ||
1216 | #endif | ||
1217 | #endif | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/cfg80211.h b/drivers/staging/ath6kl/os/linux/include/cfg80211.h new file mode 100644 index 00000000000..d5253207b19 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/cfg80211.h | |||
@@ -0,0 +1,61 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #ifndef _AR6K_CFG80211_H_ | ||
25 | #define _AR6K_CFG80211_H_ | ||
26 | |||
27 | struct wireless_dev *ar6k_cfg80211_init(struct device *dev); | ||
28 | void ar6k_cfg80211_deinit(struct ar6_softc *ar); | ||
29 | |||
30 | void ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status); | ||
31 | |||
32 | void ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel, | ||
33 | u8 *bssid, u16 listenInterval, | ||
34 | u16 beaconInterval,NETWORK_TYPE networkType, | ||
35 | u8 beaconIeLen, u8 assocReqLen, | ||
36 | u8 assocRespLen, u8 *assocInfo); | ||
37 | |||
38 | void ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason, | ||
39 | u8 *bssid, u8 assocRespLen, | ||
40 | u8 *assocInfo, u16 protocolReasonStatus); | ||
41 | |||
42 | void ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast); | ||
43 | |||
44 | #ifdef CONFIG_NL80211_TESTMODE | ||
45 | void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf, | ||
46 | int buf_len); | ||
47 | #else | ||
48 | static inline void ar6000_testmode_rx_report_event(struct ar6_softc *ar, | ||
49 | void *buf, int buf_len) | ||
50 | { | ||
51 | } | ||
52 | #endif | ||
53 | |||
54 | |||
55 | #endif /* _AR6K_CFG80211_H_ */ | ||
56 | |||
57 | |||
58 | |||
59 | |||
60 | |||
61 | |||
diff --git a/drivers/staging/ath6kl/os/linux/include/config_linux.h b/drivers/staging/ath6kl/os/linux/include/config_linux.h new file mode 100644 index 00000000000..dbbe1a00b92 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/config_linux.h | |||
@@ -0,0 +1,51 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #ifndef _CONFIG_LINUX_H_ | ||
25 | #define _CONFIG_LINUX_H_ | ||
26 | |||
27 | #ifdef __cplusplus | ||
28 | extern "C" { | ||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * Host side Test Command support | ||
33 | */ | ||
34 | #define CONFIG_HOST_TCMD_SUPPORT | ||
35 | |||
36 | #define USE_4BYTE_REGISTER_ACCESS | ||
37 | |||
38 | /* Host-side support for Target-side profiling */ | ||
39 | #undef CONFIG_TARGET_PROFILE_SUPPORT | ||
40 | |||
41 | /* IP/TCP checksum offload */ | ||
42 | /* Checksum offload is currently not supported for 64 bit platforms */ | ||
43 | #ifndef __LP64__ | ||
44 | #define CONFIG_CHECKSUM_OFFLOAD | ||
45 | #endif /* __LP64__ */ | ||
46 | |||
47 | #ifdef __cplusplus | ||
48 | } | ||
49 | #endif | ||
50 | |||
51 | #endif | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/debug_linux.h b/drivers/staging/ath6kl/os/linux/include/debug_linux.h new file mode 100644 index 00000000000..b8dba52badc --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/debug_linux.h | |||
@@ -0,0 +1,50 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #ifndef _DEBUG_LINUX_H_ | ||
25 | #define _DEBUG_LINUX_H_ | ||
26 | |||
27 | /* macro to remove parens */ | ||
28 | #define ATH_PRINTX_ARG(arg...) arg | ||
29 | |||
30 | #ifdef DEBUG | ||
31 | /* NOTE: the AR_DEBUG_PRINTF macro is defined here to handle special handling of variable arg macros | ||
32 | * which may be compiler dependent. */ | ||
33 | #define AR_DEBUG_PRINTF(mask, args) do { \ | ||
34 | if (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (mask)) { \ | ||
35 | A_LOGGER(mask, ATH_MODULE_NAME, ATH_PRINTX_ARG args); \ | ||
36 | } \ | ||
37 | } while (0) | ||
38 | #else | ||
39 | /* on non-debug builds, keep in error and warning messages in the driver, all other | ||
40 | * message tracing will get compiled out */ | ||
41 | #define AR_DEBUG_PRINTF(mask, args) \ | ||
42 | if ((mask) & (ATH_DEBUG_ERR | ATH_DEBUG_WARN)) { A_PRINTF(ATH_PRINTX_ARG args); } | ||
43 | |||
44 | #endif | ||
45 | |||
46 | /* compile specific macro to get the function name string */ | ||
47 | #define _A_FUNCNAME_ __func__ | ||
48 | |||
49 | |||
50 | #endif /* _DEBUG_LINUX_H_ */ | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h b/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h new file mode 100644 index 00000000000..74f98618334 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h | |||
@@ -0,0 +1,76 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. | ||
3 | // | ||
4 | // | ||
5 | // Permission to use, copy, modify, and/or distribute this software for any | ||
6 | // purpose with or without fee is hereby granted, provided that the above | ||
7 | // copyright notice and this permission notice appear in all copies. | ||
8 | // | ||
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | // | ||
17 | // | ||
18 | //------------------------------------------------------------------------------ | ||
19 | //============================================================================== | ||
20 | // HCI bridge implementation | ||
21 | // | ||
22 | // Author(s): ="Atheros" | ||
23 | //============================================================================== | ||
24 | |||
25 | #include "hci_transport_api.h" | ||
26 | #include "common_drv.h" | ||
27 | |||
28 | extern HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo); | ||
29 | extern void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans); | ||
30 | extern int (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue); | ||
31 | extern int (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous); | ||
32 | extern void (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans); | ||
33 | extern int (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans); | ||
34 | extern int (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); | ||
35 | extern int (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, | ||
36 | struct htc_packet *pPacket, | ||
37 | int MaxPollMS); | ||
38 | extern int (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud); | ||
39 | extern int (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable); | ||
40 | |||
41 | |||
42 | #define HCI_TransportAttach(HTCHandle, pInfo) \ | ||
43 | _HCI_TransportAttach((HTCHandle), (pInfo)) | ||
44 | #define HCI_TransportDetach(HciTrans) \ | ||
45 | _HCI_TransportDetach(HciTrans) | ||
46 | #define HCI_TransportAddReceivePkts(HciTrans, pQueue) \ | ||
47 | _HCI_TransportAddReceivePkts((HciTrans), (pQueue)) | ||
48 | #define HCI_TransportSendPkt(HciTrans, pPacket, Synchronous) \ | ||
49 | _HCI_TransportSendPkt((HciTrans), (pPacket), (Synchronous)) | ||
50 | #define HCI_TransportStop(HciTrans) \ | ||
51 | _HCI_TransportStop((HciTrans)) | ||
52 | #define HCI_TransportStart(HciTrans) \ | ||
53 | _HCI_TransportStart((HciTrans)) | ||
54 | #define HCI_TransportEnableDisableAsyncRecv(HciTrans, Enable) \ | ||
55 | _HCI_TransportEnableDisableAsyncRecv((HciTrans), (Enable)) | ||
56 | #define HCI_TransportRecvHCIEventSync(HciTrans, pPacket, MaxPollMS) \ | ||
57 | _HCI_TransportRecvHCIEventSync((HciTrans), (pPacket), (MaxPollMS)) | ||
58 | #define HCI_TransportSetBaudRate(HciTrans, Baud) \ | ||
59 | _HCI_TransportSetBaudRate((HciTrans), (Baud)) | ||
60 | #define HCI_TransportEnablePowerMgmt(HciTrans, Enable) \ | ||
61 | _HCI_TransportEnablePowerMgmt((HciTrans), (Enable)) | ||
62 | |||
63 | |||
64 | extern int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks); | ||
65 | |||
66 | extern int ar6000_get_hif_dev(struct hif_device *device, void *config); | ||
67 | |||
68 | extern int ar6000_set_uart_config(struct hif_device *hifDevice, u32 scale, u32 step); | ||
69 | |||
70 | /* get core clock register settings | ||
71 | * data: 0 - 40/44MHz | ||
72 | * 1 - 80/88MHz | ||
73 | * where (5G band/2.4G band) | ||
74 | * assume 2.4G band for now | ||
75 | */ | ||
76 | extern int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data); | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h b/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h new file mode 100644 index 00000000000..e6e96de3fc6 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h | |||
@@ -0,0 +1,177 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #ifndef _IEEE80211_IOCTL_H_ | ||
25 | #define _IEEE80211_IOCTL_H_ | ||
26 | |||
27 | #ifdef __cplusplus | ||
28 | extern "C" { | ||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * Extracted from the MADWIFI net80211/ieee80211_ioctl.h | ||
33 | */ | ||
34 | |||
35 | /* | ||
36 | * WPA/RSN get/set key request. Specify the key/cipher | ||
37 | * type and whether the key is to be used for sending and/or | ||
38 | * receiving. The key index should be set only when working | ||
39 | * with global keys (use IEEE80211_KEYIX_NONE for ``no index''). | ||
40 | * Otherwise a unicast/pairwise key is specified by the bssid | ||
41 | * (on a station) or mac address (on an ap). They key length | ||
42 | * must include any MIC key data; otherwise it should be no | ||
43 | more than IEEE80211_KEYBUF_SIZE. | ||
44 | */ | ||
45 | struct ieee80211req_key { | ||
46 | u_int8_t ik_type; /* key/cipher type */ | ||
47 | u_int8_t ik_pad; | ||
48 | u_int16_t ik_keyix; /* key index */ | ||
49 | u_int8_t ik_keylen; /* key length in bytes */ | ||
50 | u_int8_t ik_flags; | ||
51 | #define IEEE80211_KEY_XMIT 0x01 | ||
52 | #define IEEE80211_KEY_RECV 0x02 | ||
53 | #define IEEE80211_KEY_DEFAULT 0x80 /* default xmit key */ | ||
54 | u_int8_t ik_macaddr[IEEE80211_ADDR_LEN]; | ||
55 | u_int64_t ik_keyrsc; /* key receive sequence counter */ | ||
56 | u_int64_t ik_keytsc; /* key transmit sequence counter */ | ||
57 | u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE]; | ||
58 | }; | ||
59 | /* | ||
60 | * Delete a key either by index or address. Set the index | ||
61 | * to IEEE80211_KEYIX_NONE when deleting a unicast key. | ||
62 | */ | ||
63 | struct ieee80211req_del_key { | ||
64 | u_int8_t idk_keyix; /* key index */ | ||
65 | u_int8_t idk_macaddr[IEEE80211_ADDR_LEN]; | ||
66 | }; | ||
67 | /* | ||
68 | * MLME state manipulation request. IEEE80211_MLME_ASSOC | ||
69 | * only makes sense when operating as a station. The other | ||
70 | * requests can be used when operating as a station or an | ||
71 | * ap (to effect a station). | ||
72 | */ | ||
73 | struct ieee80211req_mlme { | ||
74 | u_int8_t im_op; /* operation to perform */ | ||
75 | #define IEEE80211_MLME_ASSOC 1 /* associate station */ | ||
76 | #define IEEE80211_MLME_DISASSOC 2 /* disassociate station */ | ||
77 | #define IEEE80211_MLME_DEAUTH 3 /* deauthenticate station */ | ||
78 | #define IEEE80211_MLME_AUTHORIZE 4 /* authorize station */ | ||
79 | #define IEEE80211_MLME_UNAUTHORIZE 5 /* unauthorize station */ | ||
80 | u_int16_t im_reason; /* 802.11 reason code */ | ||
81 | u_int8_t im_macaddr[IEEE80211_ADDR_LEN]; | ||
82 | }; | ||
83 | |||
84 | struct ieee80211req_addpmkid { | ||
85 | u_int8_t pi_bssid[IEEE80211_ADDR_LEN]; | ||
86 | u_int8_t pi_enable; | ||
87 | u_int8_t pi_pmkid[16]; | ||
88 | }; | ||
89 | |||
90 | #define AUTH_ALG_OPEN_SYSTEM 0x01 | ||
91 | #define AUTH_ALG_SHARED_KEY 0x02 | ||
92 | #define AUTH_ALG_LEAP 0x04 | ||
93 | |||
94 | struct ieee80211req_authalg { | ||
95 | u_int8_t auth_alg; | ||
96 | }; | ||
97 | |||
98 | /* | ||
99 | * Request to add an IE to a Management Frame | ||
100 | */ | ||
101 | enum{ | ||
102 | IEEE80211_APPIE_FRAME_BEACON = 0, | ||
103 | IEEE80211_APPIE_FRAME_PROBE_REQ = 1, | ||
104 | IEEE80211_APPIE_FRAME_PROBE_RESP = 2, | ||
105 | IEEE80211_APPIE_FRAME_ASSOC_REQ = 3, | ||
106 | IEEE80211_APPIE_FRAME_ASSOC_RESP = 4, | ||
107 | IEEE80211_APPIE_NUM_OF_FRAME = 5 | ||
108 | }; | ||
109 | |||
110 | /* | ||
111 | * The Maximum length of the IE that can be added to a Management frame | ||
112 | */ | ||
113 | #define IEEE80211_APPIE_FRAME_MAX_LEN 200 | ||
114 | |||
115 | struct ieee80211req_getset_appiebuf { | ||
116 | u_int32_t app_frmtype; /* management frame type for which buffer is added */ | ||
117 | u_int32_t app_buflen; /*application supplied buffer length */ | ||
118 | u_int8_t app_buf[]; | ||
119 | }; | ||
120 | |||
121 | /* | ||
122 | * The following definitions are used by an application to set filter | ||
123 | * for receiving management frames | ||
124 | */ | ||
125 | enum { | ||
126 | IEEE80211_FILTER_TYPE_BEACON = 0x1, | ||
127 | IEEE80211_FILTER_TYPE_PROBE_REQ = 0x2, | ||
128 | IEEE80211_FILTER_TYPE_PROBE_RESP = 0x4, | ||
129 | IEEE80211_FILTER_TYPE_ASSOC_REQ = 0x8, | ||
130 | IEEE80211_FILTER_TYPE_ASSOC_RESP = 0x10, | ||
131 | IEEE80211_FILTER_TYPE_AUTH = 0x20, | ||
132 | IEEE80211_FILTER_TYPE_DEAUTH = 0x40, | ||
133 | IEEE80211_FILTER_TYPE_DISASSOC = 0x80, | ||
134 | IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */ | ||
135 | }; | ||
136 | |||
137 | struct ieee80211req_set_filter { | ||
138 | u_int32_t app_filterype; /* management frame filter type */ | ||
139 | }; | ||
140 | |||
141 | enum { | ||
142 | IEEE80211_PARAM_AUTHMODE = 3, /* Authentication Mode */ | ||
143 | IEEE80211_PARAM_MCASTCIPHER = 5, | ||
144 | IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */ | ||
145 | IEEE80211_PARAM_UCASTCIPHER = 8, | ||
146 | IEEE80211_PARAM_UCASTKEYLEN = 9, /* unicast key length */ | ||
147 | IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */ | ||
148 | IEEE80211_PARAM_ROAMING = 12, /* roaming mode */ | ||
149 | IEEE80211_PARAM_PRIVACY = 13, /* privacy invoked */ | ||
150 | IEEE80211_PARAM_COUNTERMEASURES = 14, /* WPA/TKIP countermeasures */ | ||
151 | IEEE80211_PARAM_DROPUNENCRYPTED = 15, /* discard unencrypted frames */ | ||
152 | IEEE80211_PARAM_WAPI = 16, /* WAPI policy from wapid */ | ||
153 | }; | ||
154 | |||
155 | /* | ||
156 | * Values for IEEE80211_PARAM_WPA | ||
157 | */ | ||
158 | #define WPA_MODE_WPA1 1 | ||
159 | #define WPA_MODE_WPA2 2 | ||
160 | #define WPA_MODE_AUTO 3 | ||
161 | #define WPA_MODE_NONE 4 | ||
162 | |||
163 | struct ieee80211req_wpaie { | ||
164 | u_int8_t wpa_macaddr[IEEE80211_ADDR_LEN]; | ||
165 | u_int8_t wpa_ie[IEEE80211_MAX_IE]; | ||
166 | u_int8_t rsn_ie[IEEE80211_MAX_IE]; | ||
167 | }; | ||
168 | |||
169 | #ifndef IW_ENCODE_ALG_PMK | ||
170 | #define IW_ENCODE_ALG_PMK 4 | ||
171 | #endif | ||
172 | |||
173 | #ifdef __cplusplus | ||
174 | } | ||
175 | #endif | ||
176 | |||
177 | #endif /* _IEEE80211_IOCTL_H_ */ | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h new file mode 100644 index 00000000000..41f43730772 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h | |||
@@ -0,0 +1,339 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // This file contains the definitions of the basic atheros data types. | ||
3 | // It is used to map the data types in atheros files to a platform specific | ||
4 | // type. | ||
5 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
6 | // All rights reserved. | ||
7 | // | ||
8 | // | ||
9 | // | ||
10 | // Permission to use, copy, modify, and/or distribute this software for any | ||
11 | // purpose with or without fee is hereby granted, provided that the above | ||
12 | // copyright notice and this permission notice appear in all copies. | ||
13 | // | ||
14 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
15 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
16 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
17 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
18 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
19 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
20 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
21 | // | ||
22 | // | ||
23 | // | ||
24 | // Author(s): ="Atheros" | ||
25 | //------------------------------------------------------------------------------ | ||
26 | |||
27 | #ifndef _OSAPI_LINUX_H_ | ||
28 | #define _OSAPI_LINUX_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #include <linux/types.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/string.h> | ||
35 | #include <linux/skbuff.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/jiffies.h> | ||
38 | #include <linux/timer.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <linux/wait.h> | ||
41 | #include <linux/semaphore.h> | ||
42 | #include <linux/cache.h> | ||
43 | |||
44 | #ifdef __GNUC__ | ||
45 | #define __ATTRIB_PACK __attribute__ ((packed)) | ||
46 | #define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) | ||
47 | #define __ATTRIB_NORETURN __attribute__ ((noreturn)) | ||
48 | #ifndef INLINE | ||
49 | #define INLINE __inline__ | ||
50 | #endif | ||
51 | #else /* Not GCC */ | ||
52 | #define __ATTRIB_PACK | ||
53 | #define __ATTRIB_PRINTF | ||
54 | #define __ATTRIB_NORETURN | ||
55 | #ifndef INLINE | ||
56 | #define INLINE __inline | ||
57 | #endif | ||
58 | #endif /* End __GNUC__ */ | ||
59 | |||
60 | #define PREPACK | ||
61 | #define POSTPACK __ATTRIB_PACK | ||
62 | |||
63 | /* | ||
64 | * Endianes macros | ||
65 | */ | ||
66 | #define A_BE2CPU8(x) ntohb(x) | ||
67 | #define A_BE2CPU16(x) ntohs(x) | ||
68 | #define A_BE2CPU32(x) ntohl(x) | ||
69 | |||
70 | #define A_LE2CPU8(x) (x) | ||
71 | #define A_LE2CPU16(x) (x) | ||
72 | #define A_LE2CPU32(x) (x) | ||
73 | |||
74 | #define A_CPU2BE8(x) htonb(x) | ||
75 | #define A_CPU2BE16(x) htons(x) | ||
76 | #define A_CPU2BE32(x) htonl(x) | ||
77 | |||
78 | #define A_MEMZERO(addr, len) memset(addr, 0, len) | ||
79 | #define A_MALLOC(size) kmalloc((size), GFP_KERNEL) | ||
80 | #define A_MALLOC_NOWAIT(size) kmalloc((size), GFP_ATOMIC) | ||
81 | |||
82 | #define A_LOGGER(mask, mod, args...) printk(KERN_ALERT args) | ||
83 | #define A_PRINTF(args...) printk(KERN_ALERT args) | ||
84 | |||
85 | #define A_PRINTF_LOG(args...) printk(args) | ||
86 | #define A_SPRINTF(buf, args...) sprintf (buf, args) | ||
87 | |||
88 | /* Mutual Exclusion */ | ||
89 | typedef spinlock_t A_MUTEX_T; | ||
90 | #define A_MUTEX_INIT(mutex) spin_lock_init(mutex) | ||
91 | #define A_MUTEX_LOCK(mutex) spin_lock_bh(mutex) | ||
92 | #define A_MUTEX_UNLOCK(mutex) spin_unlock_bh(mutex) | ||
93 | #define A_IS_MUTEX_VALID(mutex) true /* okay to return true, since A_MUTEX_DELETE does nothing */ | ||
94 | #define A_MUTEX_DELETE(mutex) /* spin locks are not kernel resources so nothing to free.. */ | ||
95 | |||
96 | /* Get current time in ms adding a constant offset (in ms) */ | ||
97 | #define A_GET_MS(offset) \ | ||
98 | (((jiffies / HZ) * 1000) + (offset)) | ||
99 | |||
100 | /* | ||
101 | * Timer Functions | ||
102 | */ | ||
103 | #define A_MDELAY(msecs) mdelay(msecs) | ||
104 | typedef struct timer_list A_TIMER; | ||
105 | |||
106 | #define A_INIT_TIMER(pTimer, pFunction, pArg) do { \ | ||
107 | init_timer(pTimer); \ | ||
108 | (pTimer)->function = (pFunction); \ | ||
109 | (pTimer)->data = (unsigned long)(pArg); \ | ||
110 | } while (0) | ||
111 | |||
112 | /* | ||
113 | * Start a Timer that elapses after 'periodMSec' milli-seconds | ||
114 | * Support is provided for a one-shot timer. The 'repeatFlag' is | ||
115 | * ignored. | ||
116 | */ | ||
117 | #define A_TIMEOUT_MS(pTimer, periodMSec, repeatFlag) do { \ | ||
118 | if (repeatFlag) { \ | ||
119 | printk("\n" __FILE__ ":%d: Timer Repeat requested\n",__LINE__); \ | ||
120 | panic("Timer Repeat"); \ | ||
121 | } \ | ||
122 | mod_timer((pTimer), jiffies + HZ * (periodMSec) / 1000); \ | ||
123 | } while (0) | ||
124 | |||
125 | /* | ||
126 | * Cancel the Timer. | ||
127 | */ | ||
128 | #define A_UNTIMEOUT(pTimer) do { \ | ||
129 | del_timer((pTimer)); \ | ||
130 | } while (0) | ||
131 | |||
132 | #define A_DELETE_TIMER(pTimer) do { \ | ||
133 | } while (0) | ||
134 | |||
135 | /* | ||
136 | * Wait Queue related functions | ||
137 | */ | ||
138 | typedef wait_queue_head_t A_WAITQUEUE_HEAD; | ||
139 | #define A_INIT_WAITQUEUE_HEAD(head) init_waitqueue_head(head) | ||
140 | #ifndef wait_event_interruptible_timeout | ||
141 | #define __wait_event_interruptible_timeout(wq, condition, ret) \ | ||
142 | do { \ | ||
143 | wait_queue_t __wait; \ | ||
144 | init_waitqueue_entry(&__wait, current); \ | ||
145 | \ | ||
146 | add_wait_queue(&wq, &__wait); \ | ||
147 | for (;;) { \ | ||
148 | set_current_state(TASK_INTERRUPTIBLE); \ | ||
149 | if (condition) \ | ||
150 | break; \ | ||
151 | if (!signal_pending(current)) { \ | ||
152 | ret = schedule_timeout(ret); \ | ||
153 | if (!ret) \ | ||
154 | break; \ | ||
155 | continue; \ | ||
156 | } \ | ||
157 | ret = -ERESTARTSYS; \ | ||
158 | break; \ | ||
159 | } \ | ||
160 | current->state = TASK_RUNNING; \ | ||
161 | remove_wait_queue(&wq, &__wait); \ | ||
162 | } while (0) | ||
163 | |||
164 | #define wait_event_interruptible_timeout(wq, condition, timeout) \ | ||
165 | ({ \ | ||
166 | long __ret = timeout; \ | ||
167 | if (!(condition)) \ | ||
168 | __wait_event_interruptible_timeout(wq, condition, __ret); \ | ||
169 | __ret; \ | ||
170 | }) | ||
171 | #endif /* wait_event_interruptible_timeout */ | ||
172 | |||
173 | #define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \ | ||
174 | wait_event_interruptible_timeout(head, condition, timeout); \ | ||
175 | } while (0) | ||
176 | |||
177 | #define A_WAKE_UP(head) wake_up(head) | ||
178 | |||
179 | #ifdef DEBUG | ||
180 | extern unsigned int panic_on_assert; | ||
181 | #define A_ASSERT(expr) \ | ||
182 | if (!(expr)) { \ | ||
183 | printk(KERN_ALERT"Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#expr); \ | ||
184 | if (panic_on_assert) panic(#expr); \ | ||
185 | } | ||
186 | #else | ||
187 | #define A_ASSERT(expr) | ||
188 | #endif /* DEBUG */ | ||
189 | |||
190 | #define A_REQUEST_FIRMWARE(_ppf, _pfile, _dev) request_firmware(_ppf, _pfile, _dev) | ||
191 | #define A_RELEASE_FIRMWARE(_pf) release_firmware(_pf) | ||
192 | |||
193 | /* | ||
194 | * Initialization of the network buffer subsystem | ||
195 | */ | ||
196 | #define A_NETBUF_INIT() | ||
197 | |||
198 | /* | ||
199 | * Network buffer queue support | ||
200 | */ | ||
201 | typedef struct sk_buff_head A_NETBUF_QUEUE_T; | ||
202 | |||
203 | #define A_NETBUF_QUEUE_INIT(q) \ | ||
204 | a_netbuf_queue_init(q) | ||
205 | |||
206 | #define A_NETBUF_ENQUEUE(q, pkt) \ | ||
207 | a_netbuf_enqueue((q), (pkt)) | ||
208 | #define A_NETBUF_PREQUEUE(q, pkt) \ | ||
209 | a_netbuf_prequeue((q), (pkt)) | ||
210 | #define A_NETBUF_DEQUEUE(q) \ | ||
211 | (a_netbuf_dequeue(q)) | ||
212 | #define A_NETBUF_QUEUE_SIZE(q) \ | ||
213 | a_netbuf_queue_size(q) | ||
214 | #define A_NETBUF_QUEUE_EMPTY(q) \ | ||
215 | (a_netbuf_queue_empty(q) ? true : false) | ||
216 | |||
217 | /* | ||
218 | * Network buffer support | ||
219 | */ | ||
220 | #define A_NETBUF_ALLOC(size) \ | ||
221 | a_netbuf_alloc(size) | ||
222 | #define A_NETBUF_ALLOC_RAW(size) \ | ||
223 | a_netbuf_alloc_raw(size) | ||
224 | #define A_NETBUF_FREE(bufPtr) \ | ||
225 | a_netbuf_free(bufPtr) | ||
226 | #define A_NETBUF_DATA(bufPtr) \ | ||
227 | a_netbuf_to_data(bufPtr) | ||
228 | #define A_NETBUF_LEN(bufPtr) \ | ||
229 | a_netbuf_to_len(bufPtr) | ||
230 | #define A_NETBUF_PUSH(bufPtr, len) \ | ||
231 | a_netbuf_push(bufPtr, len) | ||
232 | #define A_NETBUF_PUT(bufPtr, len) \ | ||
233 | a_netbuf_put(bufPtr, len) | ||
234 | #define A_NETBUF_TRIM(bufPtr,len) \ | ||
235 | a_netbuf_trim(bufPtr, len) | ||
236 | #define A_NETBUF_PULL(bufPtr, len) \ | ||
237 | a_netbuf_pull(bufPtr, len) | ||
238 | #define A_NETBUF_HEADROOM(bufPtr)\ | ||
239 | a_netbuf_headroom(bufPtr) | ||
240 | #define A_NETBUF_SETLEN(bufPtr,len) \ | ||
241 | a_netbuf_setlen(bufPtr, len) | ||
242 | |||
243 | /* Add data to end of a buffer */ | ||
244 | #define A_NETBUF_PUT_DATA(bufPtr, srcPtr, len) \ | ||
245 | a_netbuf_put_data(bufPtr, srcPtr, len) | ||
246 | |||
247 | /* Add data to start of the buffer */ | ||
248 | #define A_NETBUF_PUSH_DATA(bufPtr, srcPtr, len) \ | ||
249 | a_netbuf_push_data(bufPtr, srcPtr, len) | ||
250 | |||
251 | /* Remove data at start of the buffer */ | ||
252 | #define A_NETBUF_PULL_DATA(bufPtr, dstPtr, len) \ | ||
253 | a_netbuf_pull_data(bufPtr, dstPtr, len) | ||
254 | |||
255 | /* Remove data from the end of the buffer */ | ||
256 | #define A_NETBUF_TRIM_DATA(bufPtr, dstPtr, len) \ | ||
257 | a_netbuf_trim_data(bufPtr, dstPtr, len) | ||
258 | |||
259 | /* View data as "size" contiguous bytes of type "t" */ | ||
260 | #define A_NETBUF_VIEW_DATA(bufPtr, t, size) \ | ||
261 | (t )( ((struct skbuf *)(bufPtr))->data) | ||
262 | |||
263 | /* return the beginning of the headroom for the buffer */ | ||
264 | #define A_NETBUF_HEAD(bufPtr) \ | ||
265 | ((((struct sk_buff *)(bufPtr))->head)) | ||
266 | |||
267 | /* | ||
268 | * OS specific network buffer access routines | ||
269 | */ | ||
270 | void *a_netbuf_alloc(int size); | ||
271 | void *a_netbuf_alloc_raw(int size); | ||
272 | void a_netbuf_free(void *bufPtr); | ||
273 | void *a_netbuf_to_data(void *bufPtr); | ||
274 | u32 a_netbuf_to_len(void *bufPtr); | ||
275 | int a_netbuf_push(void *bufPtr, s32 len); | ||
276 | int a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len); | ||
277 | int a_netbuf_put(void *bufPtr, s32 len); | ||
278 | int a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len); | ||
279 | int a_netbuf_pull(void *bufPtr, s32 len); | ||
280 | int a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len); | ||
281 | int a_netbuf_trim(void *bufPtr, s32 len); | ||
282 | int a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len); | ||
283 | int a_netbuf_setlen(void *bufPtr, s32 len); | ||
284 | s32 a_netbuf_headroom(void *bufPtr); | ||
285 | void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt); | ||
286 | void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt); | ||
287 | void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q); | ||
288 | int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q); | ||
289 | int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); | ||
290 | int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); | ||
291 | void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q); | ||
292 | |||
293 | /* | ||
294 | * Kernel v.s User space functions | ||
295 | */ | ||
296 | u32 a_copy_to_user(void *to, const void *from, u32 n); | ||
297 | u32 a_copy_from_user(void *to, const void *from, u32 n); | ||
298 | |||
299 | /* In linux, WLAN Rx and Tx run in different contexts, so no need to check | ||
300 | * for any commands/data queued for WLAN */ | ||
301 | #define A_CHECK_DRV_TX() | ||
302 | |||
303 | #define A_GET_CACHE_LINE_BYTES() L1_CACHE_BYTES | ||
304 | |||
305 | #define A_CACHE_LINE_PAD 128 | ||
306 | |||
307 | static inline void *A_ALIGN_TO_CACHE_LINE(void *ptr) { | ||
308 | return (void *)L1_CACHE_ALIGN((unsigned long)ptr); | ||
309 | } | ||
310 | |||
311 | #else /* __KERNEL__ */ | ||
312 | |||
313 | #ifdef __GNUC__ | ||
314 | #define __ATTRIB_PACK __attribute__ ((packed)) | ||
315 | #define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) | ||
316 | #define __ATTRIB_NORETURN __attribute__ ((noreturn)) | ||
317 | #ifndef INLINE | ||
318 | #define INLINE __inline__ | ||
319 | #endif | ||
320 | #else /* Not GCC */ | ||
321 | #define __ATTRIB_PACK | ||
322 | #define __ATTRIB_PRINTF | ||
323 | #define __ATTRIB_NORETURN | ||
324 | #ifndef INLINE | ||
325 | #define INLINE __inline | ||
326 | #endif | ||
327 | #endif /* End __GNUC__ */ | ||
328 | |||
329 | #define PREPACK | ||
330 | #define POSTPACK __ATTRIB_PACK | ||
331 | |||
332 | #define A_MEMZERO(addr, len) memset((addr), 0, (len)) | ||
333 | #define A_MALLOC(size) malloc(size) | ||
334 | |||
335 | #include <err.h> | ||
336 | |||
337 | #endif /* __KERNEL__ */ | ||
338 | |||
339 | #endif /* _OSAPI_LINUX_H_ */ | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/wlan_config.h b/drivers/staging/ath6kl/os/linux/include/wlan_config.h new file mode 100644 index 00000000000..c1fe0c6e4fa --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/wlan_config.h | |||
@@ -0,0 +1,108 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. | ||
3 | // | ||
4 | // | ||
5 | // Permission to use, copy, modify, and/or distribute this software for any | ||
6 | // purpose with or without fee is hereby granted, provided that the above | ||
7 | // copyright notice and this permission notice appear in all copies. | ||
8 | // | ||
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | // | ||
17 | // | ||
18 | //------------------------------------------------------------------------------ | ||
19 | //============================================================================== | ||
20 | // This file contains the tunable configuration items for the WLAN module | ||
21 | // | ||
22 | // Author(s): ="Atheros" | ||
23 | //============================================================================== | ||
24 | #ifndef _HOST_WLAN_CONFIG_H_ | ||
25 | #define _HOST_WLAN_CONFIG_H_ | ||
26 | |||
27 | /* Include definitions here that can be used to tune the WLAN module behavior. | ||
28 | * Different customers can tune the behavior as per their needs, here. | ||
29 | */ | ||
30 | |||
31 | /* This configuration item when defined will consider the barker preamble | ||
32 | * mentioned in the ERP IE of the beacons from the AP to determine the short | ||
33 | * preamble support sent in the (Re)Assoc request frames. | ||
34 | */ | ||
35 | #define WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP 0 | ||
36 | |||
37 | /* This config item when defined will not send the power module state transition | ||
38 | * failure events that happen during scan, to the host. | ||
39 | */ | ||
40 | #define WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN 0 | ||
41 | |||
42 | /* | ||
43 | * This configuration item enable/disable keepalive support. | ||
44 | * Keepalive support: In the absence of any data traffic to AP, null | ||
45 | * frames will be sent to the AP at periodic interval, to keep the association | ||
46 | * active. This configuration item defines the periodic interval. | ||
47 | * Use value of zero to disable keepalive support | ||
48 | * Default: 60 seconds | ||
49 | */ | ||
50 | #define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60 | ||
51 | |||
52 | /* | ||
53 | * This configuration item sets the value of disconnect timeout | ||
54 | * Firmware delays sending the disconnec event to the host for this | ||
55 | * timeout after is gets disconnected from the current AP. | ||
56 | * If the firmware successly roams within the disconnect timeout | ||
57 | * it sends a new connect event | ||
58 | */ | ||
59 | #define WLAN_CONFIG_DISCONNECT_TIMEOUT 10 | ||
60 | |||
61 | /* | ||
62 | * This configuration item disables 11n support. | ||
63 | * 0 - Enable | ||
64 | * 1 - Disable | ||
65 | */ | ||
66 | #define WLAN_CONFIG_DISABLE_11N 0 | ||
67 | |||
68 | /* | ||
69 | * This configuration item enable BT clock sharing support | ||
70 | * 1 - Enable | ||
71 | * 0 - Disable (Default) | ||
72 | */ | ||
73 | #define WLAN_CONFIG_BT_SHARING 0 | ||
74 | |||
75 | /* | ||
76 | * This configuration item sets WIFI OFF policy | ||
77 | * 0 - CUT_POWER | ||
78 | * 1 - DEEP_SLEEP (Default) | ||
79 | */ | ||
80 | #define WLAN_CONFIG_WLAN_OFF 1 | ||
81 | |||
82 | /* | ||
83 | * This configuration item sets suspend policy | ||
84 | * 0 - CUT_POWER (Default) | ||
85 | * 1 - DEEP_SLEEP | ||
86 | * 2 - WoW | ||
87 | * 3 - CUT_POWER if BT OFF (clock sharing designs only) | ||
88 | */ | ||
89 | #define WLAN_CONFIG_PM_SUSPEND 0 | ||
90 | |||
91 | /* | ||
92 | * This configuration item sets suspend policy to use if PM_SUSPEND is | ||
93 | * set to WoW and device is not connected at the time of suspend | ||
94 | * 0 - CUT_POWER (Default) | ||
95 | * 1 - DEEP_SLEEP | ||
96 | * 2 - WoW | ||
97 | * 3 - CUT_POWER if BT OFF (clock sharing designs only) | ||
98 | */ | ||
99 | #define WLAN_CONFIG_PM_WOW2 0 | ||
100 | |||
101 | /* | ||
102 | * This configuration item enables/disables transmit bursting | ||
103 | * 0 - Enable tx Bursting (default) | ||
104 | * 1 - Disable tx bursting | ||
105 | */ | ||
106 | #define WLAN_CONFIG_DISABLE_TX_BURSTING 0 | ||
107 | |||
108 | #endif /* _HOST_WLAN_CONFIG_H_ */ | ||
diff --git a/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h b/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h new file mode 100644 index 00000000000..1eb6f822d64 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h | |||
@@ -0,0 +1,300 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | |||
24 | #ifndef _WMI_FILTER_LINUX_H_ | ||
25 | #define _WMI_FILTER_LINUX_H_ | ||
26 | |||
27 | /* | ||
28 | * sioctl_filter - Standard ioctl | ||
29 | * pioctl_filter - Priv ioctl | ||
30 | * xioctl_filter - eXtended ioctl | ||
31 | * | ||
32 | * ---- Possible values for the WMI filter --------------- | ||
33 | * (0) - Block this cmd always (or) not implemented | ||
34 | * (INFRA_NETWORK) - Allow this cmd only in STA mode | ||
35 | * (ADHOC_NETWORK) - Allow this cmd only in IBSS mode | ||
36 | * (AP_NETWORK) - Allow this cmd only in AP mode | ||
37 | * (INFRA_NETWORK | ADHOC_NETWORK) - Block this cmd in AP mode | ||
38 | * (ADHOC_NETWORK | AP_NETWORK) - Block this cmd in STA mode | ||
39 | * (INFRA_NETWORK | AP_NETWORK) - Block this cmd in IBSS mode | ||
40 | * (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK)- allow only when mode is set | ||
41 | * (0xFF) - Allow this cmd always irrespective of mode | ||
42 | */ | ||
43 | |||
44 | u8 sioctl_filter[] = { | ||
45 | (AP_NETWORK), /* SIOCSIWCOMMIT 0x8B00 */ | ||
46 | (0xFF), /* SIOCGIWNAME 0x8B01 */ | ||
47 | (0), /* SIOCSIWNWID 0x8B02 */ | ||
48 | (0), /* SIOCGIWNWID 0x8B03 */ | ||
49 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWFREQ 0x8B04 */ | ||
50 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWFREQ 0x8B05 */ | ||
51 | (0xFF), /* SIOCSIWMODE 0x8B06 */ | ||
52 | (0xFF), /* SIOCGIWMODE 0x8B07 */ | ||
53 | (0), /* SIOCSIWSENS 0x8B08 */ | ||
54 | (0), /* SIOCGIWSENS 0x8B09 */ | ||
55 | (0), /* SIOCSIWRANGE 0x8B0A */ | ||
56 | (0xFF), /* SIOCGIWRANGE 0x8B0B */ | ||
57 | (0), /* SIOCSIWPRIV 0x8B0C */ | ||
58 | (0), /* SIOCGIWPRIV 0x8B0D */ | ||
59 | (0), /* SIOCSIWSTATS 0x8B0E */ | ||
60 | (0), /* SIOCGIWSTATS 0x8B0F */ | ||
61 | (0), /* SIOCSIWSPY 0x8B10 */ | ||
62 | (0), /* SIOCGIWSPY 0x8B11 */ | ||
63 | (0), /* SIOCSIWTHRSPY 0x8B12 */ | ||
64 | (0), /* SIOCGIWTHRSPY 0x8B13 */ | ||
65 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWAP 0x8B14 */ | ||
66 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWAP 0x8B15 */ | ||
67 | #if (WIRELESS_EXT >= 18) | ||
68 | (INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWMLME 0X8B16 */ | ||
69 | #else | ||
70 | (0), /* Dummy 0 */ | ||
71 | #endif /* WIRELESS_EXT */ | ||
72 | (0), /* SIOCGIWAPLIST 0x8B17 */ | ||
73 | (INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWSCAN 0x8B18 */ | ||
74 | (INFRA_NETWORK | ADHOC_NETWORK), /* SIOCGIWSCAN 0x8B19 */ | ||
75 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWESSID 0x8B1A */ | ||
76 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWESSID 0x8B1B */ | ||
77 | (0), /* SIOCSIWNICKN 0x8B1C */ | ||
78 | (0), /* SIOCGIWNICKN 0x8B1D */ | ||
79 | (0), /* Dummy 0 */ | ||
80 | (0), /* Dummy 0 */ | ||
81 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWRATE 0x8B20 */ | ||
82 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWRATE 0x8B21 */ | ||
83 | (0), /* SIOCSIWRTS 0x8B22 */ | ||
84 | (0), /* SIOCGIWRTS 0x8B23 */ | ||
85 | (0), /* SIOCSIWFRAG 0x8B24 */ | ||
86 | (0), /* SIOCGIWFRAG 0x8B25 */ | ||
87 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWTXPOW 0x8B26 */ | ||
88 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWTXPOW 0x8B27 */ | ||
89 | (INFRA_NETWORK | ADHOC_NETWORK), /* SIOCSIWRETRY 0x8B28 */ | ||
90 | (INFRA_NETWORK | ADHOC_NETWORK), /* SIOCGIWRETRY 0x8B29 */ | ||
91 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWENCODE 0x8B2A */ | ||
92 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWENCODE 0x8B2B */ | ||
93 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCSIWPOWER 0x8B2C */ | ||
94 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* SIOCGIWPOWER 0x8B2D */ | ||
95 | }; | ||
96 | |||
97 | |||
98 | |||
99 | u8 pioctl_filter[] = { | ||
100 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) */ | ||
101 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+1) */ | ||
102 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+2) */ | ||
103 | (AP_NETWORK), /* IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+3) */ | ||
104 | (INFRA_NETWORK), /* IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+4) */ | ||
105 | (0), /* IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+5) */ | ||
106 | (0), /* (SIOCIWFIRSTPRIV+6) */ | ||
107 | (0), /* (SIOCIWFIRSTPRIV+7) */ | ||
108 | (0), /* (SIOCIWFIRSTPRIV+8) */ | ||
109 | (0), /* (SIOCIWFIRSTPRIV+9) */ | ||
110 | (0), /* IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+10) */ | ||
111 | (0xFF), /* AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+11) */ | ||
112 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+12) */ | ||
113 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+13) */ | ||
114 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+14) */ | ||
115 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+15) */ | ||
116 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16) */ | ||
117 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17) */ | ||
118 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18) */ | ||
119 | (INFRA_NETWORK), /* AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19) */ | ||
120 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20) */ | ||
121 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21) */ | ||
122 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22) */ | ||
123 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23) */ | ||
124 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24)*/ | ||
125 | (0xFF), /* AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25) */ | ||
126 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26) */ | ||
127 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27) */ | ||
128 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28) */ | ||
129 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29) */ | ||
130 | (ADHOC_NETWORK), /* AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30) */ | ||
131 | }; | ||
132 | |||
133 | |||
134 | |||
135 | u8 xioctl_filter[] = { | ||
136 | (0xFF), /* Dummy 0 */ | ||
137 | (0xFF), /* AR6000_XIOCTL_BMI_DONE 1 */ | ||
138 | (0xFF), /* AR6000_XIOCTL_BMI_READ_MEMORY 2 */ | ||
139 | (0xFF), /* AR6000_XIOCTL_BMI_WRITE_MEMORY 3 */ | ||
140 | (0xFF), /* AR6000_XIOCTL_BMI_EXECUTE 4 */ | ||
141 | (0xFF), /* AR6000_XIOCTL_BMI_SET_APP_START 5 */ | ||
142 | (0xFF), /* AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6 */ | ||
143 | (0xFF), /* AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7 */ | ||
144 | (0xFF), /* AR6000_XIOCTL_BMI_TEST 8 */ | ||
145 | (0xFF), /* AR6000_XIOCTL_UNUSED9 9 */ | ||
146 | (0xFF), /* AR6000_XIOCTL_UNUSED10 10 */ | ||
147 | (0xFF), /* AR6000_XIOCTL_UNUSED11 11 */ | ||
148 | (0xFF), /* AR6000_XIOCTL_FORCE_TARGET_RESET 12 */ | ||
149 | (0xFF), /* AR6000_XIOCTL_HTC_RAW_OPEN 13 */ | ||
150 | (0xFF), /* AR6000_XIOCTL_HTC_RAW_CLOSE 14 */ | ||
151 | (0xFF), /* AR6000_XIOCTL_HTC_RAW_READ 15 */ | ||
152 | (0xFF), /* AR6000_XIOCTL_HTC_RAW_WRITE 16 */ | ||
153 | (0xFF), /* AR6000_XIOCTL_CHECK_TARGET_READY 17 */ | ||
154 | (0xFF), /* AR6000_XIOCTL_GPIO_OUTPUT_SET 18 */ | ||
155 | (0xFF), /* AR6000_XIOCTL_GPIO_INPUT_GET 19 */ | ||
156 | (0xFF), /* AR6000_XIOCTL_GPIO_REGISTER_SET 20 */ | ||
157 | (0xFF), /* AR6000_XIOCTL_GPIO_REGISTER_GET 21 */ | ||
158 | (0xFF), /* AR6000_XIOCTL_GPIO_INTR_ACK 22 */ | ||
159 | (0xFF), /* AR6000_XIOCTL_GPIO_INTR_WAIT 23 */ | ||
160 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_ADHOC_BSSID 24 */ | ||
161 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_OPT_MODE 25 */ | ||
162 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_OPT_SEND_FRAME 26 */ | ||
163 | (ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_SET_BEACON_INTVAL 27 */ | ||
164 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* IEEE80211_IOCTL_SETAUTHALG 28 */ | ||
165 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29 */ | ||
166 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_MAX_SP 30 */ | ||
167 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_ROAM_TBL 31 */ | ||
168 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32 */ | ||
169 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33 */ | ||
170 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTRL_WMI_GET_POWER_MODE 34 */ | ||
171 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35 */ | ||
172 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_ROAM_DATA 36 */ | ||
173 | (0xFF), /* AR6000_XIOCTL_WMI_SETRETRYLIMITS 37 */ | ||
174 | (0xFF), /* AR6000_XIOCTL_TCMD_CONT_TX 38 */ | ||
175 | (0xFF), /* AR6000_XIOCTL_TCMD_CONT_RX 39 */ | ||
176 | (0xFF), /* AR6000_XIOCTL_TCMD_PM 40 */ | ||
177 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_STARTSCAN 41 */ | ||
178 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SETFIXRATES 42 */ | ||
179 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_GETFIXRATES 43 */ | ||
180 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44 */ | ||
181 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_CLR_RSSISNR 45 */ | ||
182 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46 */ | ||
183 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_RTS 47 */ | ||
184 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_LPREAMBLE 48 */ | ||
185 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_AUTHMODE 49 */ | ||
186 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_REASSOCMODE 50 */ | ||
187 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WMM 51 */ | ||
188 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52 */ | ||
189 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53 */ | ||
190 | (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK), /* AR6000_XIOCTL_WMI_GET_RD 54 */ | ||
191 | (0xFF), /* AR6000_XIOCTL_DIAG_READ 55 */ | ||
192 | (0xFF), /* AR6000_XIOCTL_DIAG_WRITE 56 */ | ||
193 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_TXOP 57 */ | ||
194 | (INFRA_NETWORK), /* AR6000_XIOCTL_USER_SETKEYS 58 */ | ||
195 | (INFRA_NETWORK), /* AR6000_XIOCTL_WMI_SET_KEEPALIVE 59 */ | ||
196 | (INFRA_NETWORK), /* AR6000_XIOCTL_WMI_GET_KEEPALIVE 60 */ | ||
197 | (0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61 */ | ||
198 | (0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62 */ | ||
199 | (0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63 */ | ||
200 | (0xFF), /* AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64 */ | ||
201 | (0xFF), /* AR6000_XIOCTL_WMI_SET_APPIE 65 */ | ||
202 | (0xFF), /* AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66 */ | ||
203 | (0xFF), /* AR6000_XIOCTL_DBGLOG_CFG_MODULE 67 */ | ||
204 | (0xFF), /* AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68 */ | ||
205 | (0xFF), /* Dummy 69 */ | ||
206 | (0xFF), /* AR6000_XIOCTL_WMI_SET_WSC_STATUS 70 */ | ||
207 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_STATUS 71 */ | ||
208 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_PARAMS 72 */ | ||
209 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73 */ | ||
210 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WOW_MODE 74 */ | ||
211 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_WOW_LIST 75 */ | ||
212 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76 */ | ||
213 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77 */ | ||
214 | (0xFF), /* AR6000_XIOCTL_TARGET_INFO 78 */ | ||
215 | (0xFF), /* AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79 */ | ||
216 | (0xFF), /* AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80 */ | ||
217 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81 */ | ||
218 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82 */ | ||
219 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_PMKID_LIST 83 */ | ||
220 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_PMKID_LIST 84 */ | ||
221 | (0xFF), /* Dummy 85 */ | ||
222 | (0xFF), /* Dummy 86 */ | ||
223 | (0xFF), /* Dummy 87 */ | ||
224 | (0xFF), /* Dummy 88 */ | ||
225 | (0xFF), /* Dummy 89 */ | ||
226 | (0xFF), /* AR6000_XIOCTL_UNUSED90 90 */ | ||
227 | (0xFF), /* AR6000_XIOCTL_BMI_LZ_STREAM_START 91 */ | ||
228 | (0xFF), /* AR6000_XIOCTL_BMI_LZ_DATA 92 */ | ||
229 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_CFG 93 */ | ||
230 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_ADDR_SET 94 */ | ||
231 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_START 95 */ | ||
232 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_STOP 96 */ | ||
233 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_PROF_COUNT_GET 97 */ | ||
234 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_ABORT_SCAN 98 */ | ||
235 | (AP_NETWORK), /* AR6000_XIOCTL_AP_GET_STA_LIST 99 */ | ||
236 | (AP_NETWORK), /* AR6000_XIOCTL_AP_HIDDEN_SSID 100 */ | ||
237 | (AP_NETWORK), /* AR6000_XIOCTL_AP_SET_NUM_STA 101 */ | ||
238 | (AP_NETWORK), /* AR6000_XIOCTL_AP_SET_ACL_MAC 102 */ | ||
239 | (AP_NETWORK), /* AR6000_XIOCTL_AP_GET_ACL_LIST 103 */ | ||
240 | (AP_NETWORK), /* AR6000_XIOCTL_AP_COMMIT_CONFIG 104 */ | ||
241 | (AP_NETWORK), /* IEEE80211_IOCTL_GETWPAIE 105 */ | ||
242 | (AP_NETWORK), /* AR6000_XIOCTL_AP_CONN_INACT_TIME 106 */ | ||
243 | (AP_NETWORK), /* AR6000_XIOCTL_AP_PROT_SCAN_TIME 107 */ | ||
244 | (AP_NETWORK), /* AR6000_XIOCTL_WMI_SET_COUNTRY 108 */ | ||
245 | (AP_NETWORK), /* AR6000_XIOCTL_AP_SET_DTIM 109 */ | ||
246 | (0xFF), /* AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT 110 */ | ||
247 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_SET_IP 111 */ | ||
248 | (AP_NETWORK), /* AR6000_XIOCTL_AP_SET_ACL_POLICY 112 */ | ||
249 | (AP_NETWORK), /* AR6000_XIOCTL_AP_INTRA_BSS_COMM 113 */ | ||
250 | (0xFF), /* AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO 114 */ | ||
251 | (0xFF), /* AR6000_XIOCTL_MODULE_DEBUG_SET_MASK 115 */ | ||
252 | (0xFF), /* AR6000_XIOCTL_MODULE_DEBUG_GET_MASK 116 */ | ||
253 | (0xFF), /* AR6000_XIOCTL_DUMP_RCV_AGGR_STATS 117 */ | ||
254 | (0xFF), /* AR6000_XIOCTL_SET_HT_CAP 118 */ | ||
255 | (0xFF), /* AR6000_XIOCTL_SET_HT_OP 119 */ | ||
256 | (AP_NETWORK), /* AR6000_XIOCTL_AP_GET_STAT 120 */ | ||
257 | (0xFF), /* AR6000_XIOCTL_SET_TX_SELECT_RATES 121 */ | ||
258 | (0xFF), /* AR6000_XIOCTL_SETUP_AGGR 122 */ | ||
259 | (0xFF), /* AR6000_XIOCTL_ALLOW_AGGR 123 */ | ||
260 | (AP_NETWORK), /* AR6000_XIOCTL_AP_GET_HIDDEN_SSID 124 */ | ||
261 | (AP_NETWORK), /* AR6000_XIOCTL_AP_GET_COUNTRY 125 */ | ||
262 | (AP_NETWORK), /* AR6000_XIOCTL_AP_GET_WMODE 126 */ | ||
263 | (AP_NETWORK), /* AR6000_XIOCTL_AP_GET_DTIM 127 */ | ||
264 | (AP_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_AP_GET_BINTVL 128 */ | ||
265 | (0xFF), /* AR6000_XIOCTL_AP_GET_RTS 129 */ | ||
266 | (0xFF), /* AR6000_XIOCTL_DELE_AGGR 130 */ | ||
267 | (0xFF), /* AR6000_XIOCTL_FETCH_TARGET_REGS 131 */ | ||
268 | (0xFF), /* AR6000_XIOCTL_HCI_CMD 132 */ | ||
269 | (0xFF), /* AR6000_XIOCTL_ACL_DATA(used to be used for PAL) 133 */ | ||
270 | (0xFF), /* AR6000_XIOCTL_WLAN_CONN_PRECEDENCE 134 */ | ||
271 | (AP_NETWORK), /* AR6000_XIOCTL_AP_SET_11BG_RATESET 135 */ | ||
272 | (0xFF), | ||
273 | (0xFF), | ||
274 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT 138 */ | ||
275 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV 139 */ | ||
276 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG 140 */ | ||
277 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG 141 */ | ||
278 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG 142 */ | ||
279 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG 143 */ | ||
280 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG 144 */ | ||
281 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS 145 */ | ||
282 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG 146 */ | ||
283 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_GET_BTCOEX_GET_STATS 147 */ | ||
284 | (0xFF), /* AR6000_XIOCTL_WMI_SET_QOS_SUPP 148 */ | ||
285 | (0xFF), /* AR6000_XIOCTL_GET_WLAN_SLEEP_STATE 149 */ | ||
286 | (0xFF), /* AR6000_XIOCTL_SET_BT_HW_POWER_STATE 150 */ | ||
287 | (0xFF), /* AR6000_XIOCTL_GET_BT_HW_POWER_STATE 151 */ | ||
288 | (0xFF), /* AR6000_XIOCTL_ADD_AP_INTERFACE 152 */ | ||
289 | (0xFF), /* AR6000_XIOCTL_REMOVE_AP_INTERFACE 153 */ | ||
290 | (0xFF), /* AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM 154 */ | ||
291 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_WPA_OFFLOAD_STATE 155 */ | ||
292 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_PASSPHRASE 156 */ | ||
293 | (0xFF), | ||
294 | (0xFF), | ||
295 | (0xFF), | ||
296 | (0xFF), | ||
297 | (INFRA_NETWORK | ADHOC_NETWORK), /* AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES 161 */ | ||
298 | }; | ||
299 | |||
300 | #endif /*_WMI_FILTER_LINUX_H_*/ | ||
diff --git a/drivers/staging/ath6kl/os/linux/netbuf.c b/drivers/staging/ath6kl/os/linux/netbuf.c new file mode 100644 index 00000000000..963a2fb76a9 --- /dev/null +++ b/drivers/staging/ath6kl/os/linux/netbuf.c | |||
@@ -0,0 +1,231 @@ | |||
1 | //------------------------------------------------------------------------------ | ||
2 | // Copyright (c) 2004-2010 Atheros Communications Inc. | ||
3 | // All rights reserved. | ||
4 | // | ||
5 | // | ||
6 | // | ||
7 | // Permission to use, copy, modify, and/or distribute this software for any | ||
8 | // purpose with or without fee is hereby granted, provided that the above | ||
9 | // copyright notice and this permission notice appear in all copies. | ||
10 | // | ||
11 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
13 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
14 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
15 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | // | ||
19 | // | ||
20 | // | ||
21 | // Author(s): ="Atheros" | ||
22 | //------------------------------------------------------------------------------ | ||
23 | #include <a_config.h> | ||
24 | #include "athdefs.h" | ||
25 | #include "a_osapi.h" | ||
26 | #include "htc_packet.h" | ||
27 | |||
28 | #define AR6000_DATA_OFFSET 64 | ||
29 | |||
30 | void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt) | ||
31 | { | ||
32 | skb_queue_tail((struct sk_buff_head *) q, (struct sk_buff *) pkt); | ||
33 | } | ||
34 | |||
35 | void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt) | ||
36 | { | ||
37 | skb_queue_head((struct sk_buff_head *) q, (struct sk_buff *) pkt); | ||
38 | } | ||
39 | |||
40 | void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q) | ||
41 | { | ||
42 | return((void *) skb_dequeue((struct sk_buff_head *) q)); | ||
43 | } | ||
44 | |||
45 | int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q) | ||
46 | { | ||
47 | return(skb_queue_len((struct sk_buff_head *) q)); | ||
48 | } | ||
49 | |||
50 | int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q) | ||
51 | { | ||
52 | return(skb_queue_empty((struct sk_buff_head *) q)); | ||
53 | } | ||
54 | |||
55 | void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q) | ||
56 | { | ||
57 | skb_queue_head_init((struct sk_buff_head *) q); | ||
58 | } | ||
59 | |||
60 | void * | ||
61 | a_netbuf_alloc(int size) | ||
62 | { | ||
63 | struct sk_buff *skb; | ||
64 | size += 2 * (A_GET_CACHE_LINE_BYTES()); /* add some cacheline space at front and back of buffer */ | ||
65 | skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(struct htc_packet) + size); | ||
66 | skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(struct htc_packet) + A_GET_CACHE_LINE_BYTES()); | ||
67 | return ((void *)skb); | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Allocate an SKB w.o. any encapsulation requirement. | ||
72 | */ | ||
73 | void * | ||
74 | a_netbuf_alloc_raw(int size) | ||
75 | { | ||
76 | struct sk_buff *skb; | ||
77 | |||
78 | skb = dev_alloc_skb(size); | ||
79 | |||
80 | return ((void *)skb); | ||
81 | } | ||
82 | |||
83 | void | ||
84 | a_netbuf_free(void *bufPtr) | ||
85 | { | ||
86 | struct sk_buff *skb = (struct sk_buff *)bufPtr; | ||
87 | |||
88 | dev_kfree_skb(skb); | ||
89 | } | ||
90 | |||
91 | u32 a_netbuf_to_len(void *bufPtr) | ||
92 | { | ||
93 | return (((struct sk_buff *)bufPtr)->len); | ||
94 | } | ||
95 | |||
96 | void * | ||
97 | a_netbuf_to_data(void *bufPtr) | ||
98 | { | ||
99 | return (((struct sk_buff *)bufPtr)->data); | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * Add len # of bytes to the beginning of the network buffer | ||
104 | * pointed to by bufPtr | ||
105 | */ | ||
106 | int | ||
107 | a_netbuf_push(void *bufPtr, s32 len) | ||
108 | { | ||
109 | skb_push((struct sk_buff *)bufPtr, len); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Add len # of bytes to the beginning of the network buffer | ||
116 | * pointed to by bufPtr and also fill with data | ||
117 | */ | ||
118 | int | ||
119 | a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len) | ||
120 | { | ||
121 | skb_push((struct sk_buff *) bufPtr, len); | ||
122 | memcpy(((struct sk_buff *)bufPtr)->data, srcPtr, len); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Add len # of bytes to the end of the network buffer | ||
129 | * pointed to by bufPtr | ||
130 | */ | ||
131 | int | ||
132 | a_netbuf_put(void *bufPtr, s32 len) | ||
133 | { | ||
134 | skb_put((struct sk_buff *)bufPtr, len); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * Add len # of bytes to the end of the network buffer | ||
141 | * pointed to by bufPtr and also fill with data | ||
142 | */ | ||
143 | int | ||
144 | a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len) | ||
145 | { | ||
146 | char *start = (char*)(((struct sk_buff *)bufPtr)->data + | ||
147 | ((struct sk_buff *)bufPtr)->len); | ||
148 | skb_put((struct sk_buff *)bufPtr, len); | ||
149 | memcpy(start, srcPtr, len); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | |||
155 | /* | ||
156 | * Trim the network buffer pointed to by bufPtr to len # of bytes | ||
157 | */ | ||
158 | int | ||
159 | a_netbuf_setlen(void *bufPtr, s32 len) | ||
160 | { | ||
161 | skb_trim((struct sk_buff *)bufPtr, len); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * Chop of len # of bytes from the end of the buffer. | ||
168 | */ | ||
169 | int | ||
170 | a_netbuf_trim(void *bufPtr, s32 len) | ||
171 | { | ||
172 | skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * Chop of len # of bytes from the end of the buffer and return the data. | ||
179 | */ | ||
180 | int | ||
181 | a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len) | ||
182 | { | ||
183 | char *start = (char*)(((struct sk_buff *)bufPtr)->data + | ||
184 | (((struct sk_buff *)bufPtr)->len - len)); | ||
185 | |||
186 | memcpy(dstPtr, start, len); | ||
187 | skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | |||
193 | /* | ||
194 | * Returns the number of bytes available to a a_netbuf_push() | ||
195 | */ | ||
196 | s32 a_netbuf_headroom(void *bufPtr) | ||
197 | { | ||
198 | return (skb_headroom((struct sk_buff *)bufPtr)); | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Removes specified number of bytes from the beginning of the buffer | ||
203 | */ | ||
204 | int | ||
205 | a_netbuf_pull(void *bufPtr, s32 len) | ||
206 | { | ||
207 | skb_pull((struct sk_buff *)bufPtr, len); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * Removes specified number of bytes from the beginning of the buffer | ||
214 | * and return the data | ||
215 | */ | ||
216 | int | ||
217 | a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len) | ||
218 | { | ||
219 | memcpy(dstPtr, ((struct sk_buff *)bufPtr)->data, len); | ||
220 | skb_pull((struct sk_buff *)bufPtr, len); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | ||
226 | EXPORT_SYMBOL(a_netbuf_to_data); | ||
227 | EXPORT_SYMBOL(a_netbuf_put); | ||
228 | EXPORT_SYMBOL(a_netbuf_pull); | ||
229 | EXPORT_SYMBOL(a_netbuf_alloc); | ||
230 | EXPORT_SYMBOL(a_netbuf_free); | ||
231 | #endif | ||