clean interface before shutting it down
[openwrt/openwrt.git] / target / linux / s3c24xx / files-2.6.30 / drivers / ar6000 / ar6000 / ar6000_drv.c
1 /*
2 *
3 * Copyright (c) 2004-2007 Atheros Communications Inc.
4 * All rights reserved.
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation;
10 *
11 * Software distributed under the License is distributed on an "AS
12 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13 * implied. See the License for the specific language governing
14 * rights and limitations under the License.
15 *
16 *
17 *
18 */
19
20 /*
21 * This driver is a pseudo ethernet driver to access the Atheros AR6000
22 * WLAN Device
23 */
24 static const char athId[] __attribute__ ((unused)) = "$Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/ar6000_drv.c#2 $";
25
26 #include "ar6000_drv.h"
27 #include "htc.h"
28
29 MODULE_LICENSE("GPL and additional rights");
30
31 #ifndef REORG_APTC_HEURISTICS
32 #undef ADAPTIVE_POWER_THROUGHPUT_CONTROL
33 #endif /* REORG_APTC_HEURISTICS */
34
35 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
36 #define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */
37 #define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */
38 #define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */
39
40 typedef struct aptc_traffic_record {
41 A_BOOL timerScheduled;
42 struct timeval samplingTS;
43 unsigned long bytesReceived;
44 unsigned long bytesTransmitted;
45 } APTC_TRAFFIC_RECORD;
46
47 A_TIMER aptcTimer;
48 APTC_TRAFFIC_RECORD aptcTR;
49 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
50
51 int bmienable = 0;
52 unsigned int bypasswmi = 0;
53 unsigned int debuglevel = 0;
54 int tspecCompliance = 1;
55 unsigned int busspeedlow = 0;
56 unsigned int onebitmode = 0;
57 unsigned int skipflash = 0;
58 unsigned int wmitimeout = 2;
59 unsigned int wlanNodeCaching = 1;
60 unsigned int enableuartprint = 0;
61 unsigned int logWmiRawMsgs = 0;
62 unsigned int enabletimerwar = 0;
63 unsigned int mbox_yield_limit = 99;
64 int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF;
65 int allow_trace_signal = 0;
66 #ifdef CONFIG_HOST_TCMD_SUPPORT
67 unsigned int testmode =0;
68 #endif
69
70 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
71 module_param(bmienable, int, 0644);
72 module_param(bypasswmi, int, 0644);
73 module_param(debuglevel, int, 0644);
74 module_param(tspecCompliance, int, 0644);
75 module_param(onebitmode, int, 0644);
76 module_param(busspeedlow, int, 0644);
77 module_param(skipflash, int, 0644);
78 module_param(wmitimeout, int, 0644);
79 module_param(wlanNodeCaching, int, 0644);
80 module_param(logWmiRawMsgs, int, 0644);
81 module_param(enableuartprint, int, 0644);
82 module_param(enabletimerwar, int, 0644);
83 module_param(mbox_yield_limit, int, 0644);
84 module_param(reduce_credit_dribble, int, 0644);
85 module_param(allow_trace_signal, int, 0644);
86 #ifdef CONFIG_HOST_TCMD_SUPPORT
87 module_param(testmode, int, 0644);
88 #endif
89 #else
90
91 #define __user
92 /* for linux 2.4 and lower */
93 MODULE_PARM(bmienable,"i");
94 MODULE_PARM(bypasswmi,"i");
95 MODULE_PARM(debuglevel, "i");
96 MODULE_PARM(onebitmode,"i");
97 MODULE_PARM(busspeedlow, "i");
98 MODULE_PARM(skipflash, "i");
99 MODULE_PARM(wmitimeout, "i");
100 MODULE_PARM(wlanNodeCaching, "i");
101 MODULE_PARM(enableuartprint,"i");
102 MODULE_PARM(logWmiRawMsgs, "i");
103 MODULE_PARM(enabletimerwar,"i");
104 MODULE_PARM(mbox_yield_limit,"i");
105 MODULE_PARM(reduce_credit_dribble,"i");
106 MODULE_PARM(allow_trace_signal,"i");
107 #ifdef CONFIG_HOST_TCMD_SUPPORT
108 MODULE_PARM(testmode, "i");
109 #endif
110 #endif
111
112 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
113 /* in 2.6.10 and later this is now a pointer to a uint */
114 unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX;
115 #define mboxnum &_mboxnum
116 #else
117 unsigned int mboxnum = HTC_MAILBOX_NUM_MAX;
118 #endif
119
120 #ifdef CONFIG_AR6000_WLAN_RESET
121 unsigned int resetok = 1;
122 #else
123 unsigned int resetok = 0;
124 #endif
125
126 #ifdef DEBUG
127 A_UINT32 g_dbg_flags = DBG_DEFAULTS;
128 unsigned int debugflags = 0;
129 int debugdriver = 1;
130 unsigned int debughtc = 128;
131 unsigned int debugbmi = 1;
132 unsigned int debughif = 2;
133 unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0};
134 unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0};
135 unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0};
136 unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0};
137
138 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
139 module_param(debugflags, int, 0644);
140 module_param(debugdriver, int, 0644);
141 module_param(debughtc, int, 0644);
142 module_param(debugbmi, int, 0644);
143 module_param(debughif, int, 0644);
144 module_param(resetok, int, 0644);
145 module_param_array(txcreditsavailable, int, mboxnum, 0644);
146 module_param_array(txcreditsconsumed, int, mboxnum, 0644);
147 module_param_array(txcreditintrenable, int, mboxnum, 0644);
148 module_param_array(txcreditintrenableaggregate, int, mboxnum, 0644);
149 #else
150 /* linux 2.4 and lower */
151 MODULE_PARM(debugflags,"i");
152 MODULE_PARM(debugdriver, "i");
153 MODULE_PARM(debughtc, "i");
154 MODULE_PARM(debugbmi, "i");
155 MODULE_PARM(debughif, "i");
156 MODULE_PARM(resetok, "i");
157 MODULE_PARM(txcreditsavailable, "0-3i");
158 MODULE_PARM(txcreditsconsumed, "0-3i");
159 MODULE_PARM(txcreditintrenable, "0-3i");
160 MODULE_PARM(txcreditintrenableaggregate, "0-3i");
161 #endif
162
163 #endif /* DEBUG */
164
165 unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0};
166 unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0};
167 unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0};
168 unsigned int hifBusRequestNumMax = 40;
169 unsigned int war23838_disabled = 0;
170 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
171 unsigned int enableAPTCHeuristics = 1;
172 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
173 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
174 module_param_array(tx_attempt, int, mboxnum, 0644);
175 module_param_array(tx_post, int, mboxnum, 0644);
176 module_param_array(tx_complete, int, mboxnum, 0644);
177 module_param(hifBusRequestNumMax, int, 0644);
178 module_param(war23838_disabled, int, 0644);
179 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
180 module_param(enableAPTCHeuristics, int, 0644);
181 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
182 #else
183 MODULE_PARM(tx_attempt, "0-3i");
184 MODULE_PARM(tx_post, "0-3i");
185 MODULE_PARM(tx_complete, "0-3i");
186 MODULE_PARM(hifBusRequestNumMax, "i");
187 MODULE_PARM(war23838_disabled, "i");
188 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
189 MODULE_PARM(enableAPTCHeuristics, "i");
190 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
191 #endif
192
193 #ifdef BLOCK_TX_PATH_FLAG
194 int blocktx = 0;
195 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
196 module_param(blocktx, int, 0644);
197 #else
198 MODULE_PARM(blocktx, "i");
199 #endif
200 #endif /* BLOCK_TX_PATH_FLAG */
201
202 // TODO move to arsoft_c
203 USER_RSSI_THOLD rssi_map[12];
204
205 int reconnect_flag = 0;
206
207 DECLARE_WAIT_QUEUE_HEAD(ar6000_scan_queue);
208
209 /* Function declarations */
210 static int ar6000_init_module(void);
211 static void ar6000_cleanup_module(void);
212
213 int ar6000_init(struct net_device *dev);
214 static int ar6000_open(struct net_device *dev);
215 static int ar6000_close(struct net_device *dev);
216 static int ar6000_cleanup(struct net_device *dev);
217 static void ar6000_init_control_info(AR_SOFTC_T *ar);
218 static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev);
219
220 static void ar6000_destroy(struct net_device *dev, unsigned int unregister);
221 static void ar6000_detect_error(unsigned long ptr);
222 static struct net_device_stats *ar6000_get_stats(struct net_device *dev);
223 static struct iw_statistics *ar6000_get_iwstats(struct net_device * dev);
224
225 /*
226 * HTC service connection handlers
227 */
228 static void ar6000_avail_ev(HTC_HANDLE HTCHandle);
229
230 static void ar6000_unavail_ev(void *Instance);
231
232 static void ar6000_target_failure(void *Instance, A_STATUS Status);
233
234 static void ar6000_rx(void *Context, HTC_PACKET *pPacket);
235
236 static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint);
237
238 static void ar6000_tx_complete(void *Context, HTC_PACKET *pPacket);
239
240 static void ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint);
241
242 static void ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint);
243
244 /*
245 * Static variables
246 */
247
248 static struct net_device *ar6000_devices[MAX_AR6000];
249 extern struct iw_handler_def ath_iw_handler_def;
250 DECLARE_WAIT_QUEUE_HEAD(arEvent);
251 static void ar6000_cookie_init(AR_SOFTC_T *ar);
252 static void ar6000_cookie_cleanup(AR_SOFTC_T *ar);
253 static void ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie);
254 static struct ar_cookie *ar6000_alloc_cookie(AR_SOFTC_T *ar);
255 static void ar6000_TxDataCleanup(AR_SOFTC_T *ar);
256
257 #ifdef USER_KEYS
258 static A_STATUS ar6000_reinstall_keys(AR_SOFTC_T *ar,A_UINT8 key_op_ctrl);
259 #endif
260
261
262 static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM];
263
264 #define HOST_INTEREST_ITEM_ADDRESS(ar, item) \
265 ((ar->arTargetType == TARGET_TYPE_AR6001) ? \
266 AR6001_HOST_INTEREST_ITEM_ADDRESS(item) : \
267 AR6002_HOST_INTEREST_ITEM_ADDRESS(item))
268
269
270 /* Debug log support */
271
272 /*
273 * Flag to govern whether the debug logs should be parsed in the kernel
274 * or reported to the application.
275 */
276 #ifdef DEBUG
277 #define REPORT_DEBUG_LOGS_TO_APP
278 #endif
279
280 A_STATUS
281 ar6000_set_host_app_area(AR_SOFTC_T *ar)
282 {
283 A_UINT32 address, data;
284 struct host_app_area_s host_app_area;
285
286 /* Fetch the address of the host_app_area_s instance in the host interest area */
287 address = HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest);
288 if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != A_OK) {
289 return A_ERROR;
290 }
291 address = data;
292 host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
293 if (ar6000_WriteDataDiag(ar->arHifDevice, address,
294 (A_UCHAR *)&host_app_area,
295 sizeof(struct host_app_area_s)) != A_OK)
296 {
297 return A_ERROR;
298 }
299
300 return A_OK;
301 }
302
303 A_UINT32
304 dbglog_get_debug_hdr_ptr(AR_SOFTC_T *ar)
305 {
306 A_UINT32 param;
307 A_UINT32 address;
308 A_STATUS status;
309
310 address = HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr);
311 if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address,
312 (A_UCHAR *)&param, 4)) != A_OK)
313 {
314 param = 0;
315 }
316
317 return param;
318 }
319
320 /*
321 * The dbglog module has been initialized. Its ok to access the relevant
322 * data stuctures over the diagnostic window.
323 */
324 void
325 ar6000_dbglog_init_done(AR_SOFTC_T *ar)
326 {
327 ar->dbglog_init_done = TRUE;
328 }
329
330 A_UINT32
331 dbglog_get_debug_fragment(A_INT8 *datap, A_UINT32 len, A_UINT32 limit)
332 {
333 A_INT32 *buffer;
334 A_UINT32 count;
335 A_UINT32 numargs;
336 A_UINT32 length;
337 A_UINT32 fraglen;
338
339 count = fraglen = 0;
340 buffer = (A_INT32 *)datap;
341 length = (limit >> 2);
342
343 if (len <= limit) {
344 fraglen = len;
345 } else {
346 while (count < length) {
347 numargs = DBGLOG_GET_NUMARGS(buffer[count]);
348 fraglen = (count << 2);
349 count += numargs + 1;
350 }
351 }
352
353 return fraglen;
354 }
355
356 void
357 dbglog_parse_debug_logs(A_INT8 *datap, A_UINT32 len)
358 {
359 A_INT32 *buffer;
360 A_UINT32 count;
361 A_UINT32 timestamp;
362 A_UINT32 debugid;
363 A_UINT32 moduleid;
364 A_UINT32 numargs;
365 A_UINT32 length;
366
367 count = 0;
368 buffer = (A_INT32 *)datap;
369 length = (len >> 2);
370 while (count < length) {
371 debugid = DBGLOG_GET_DBGID(buffer[count]);
372 moduleid = DBGLOG_GET_MODULEID(buffer[count]);
373 numargs = DBGLOG_GET_NUMARGS(buffer[count]);
374 timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]);
375 switch (numargs) {
376 case 0:
377 AR_DEBUG_PRINTF("%d %d (%d)\n", moduleid, debugid, timestamp);
378 break;
379
380 case 1:
381 AR_DEBUG_PRINTF("%d %d (%d): 0x%x\n", moduleid, debugid,
382 timestamp, buffer[count+1]);
383 break;
384
385 case 2:
386 AR_DEBUG_PRINTF("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid,
387 timestamp, buffer[count+1], buffer[count+2]);
388 break;
389
390 default:
391 AR_DEBUG_PRINTF("Invalid args: %d\n", numargs);
392 }
393 count += numargs + 1;
394 }
395 }
396
397 int
398 ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
399 {
400 struct dbglog_hdr_s debug_hdr;
401 struct dbglog_buf_s debug_buf;
402 A_UINT32 address;
403 A_UINT32 length;
404 A_UINT32 dropped;
405 A_UINT32 firstbuf;
406 A_UINT32 debug_hdr_ptr;
407
408 if (!ar->dbglog_init_done) return A_ERROR;
409
410 #ifndef CONFIG_AR6000_WLAN_DEBUG
411 return 0;
412 #endif
413
414 AR6000_SPIN_LOCK(&ar->arLock, 0);
415
416 if (ar->dbgLogFetchInProgress) {
417 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
418 return A_EBUSY;
419 }
420
421 /* block out others */
422 ar->dbgLogFetchInProgress = TRUE;
423
424 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
425
426 debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar);
427 printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr);
428
429 /* Get the contents of the ring buffer */
430 if (debug_hdr_ptr) {
431 address = debug_hdr_ptr;
432 length = sizeof(struct dbglog_hdr_s);
433 ar6000_ReadDataDiag(ar->arHifDevice, address,
434 (A_UCHAR *)&debug_hdr, length);
435 address = (A_UINT32)debug_hdr.dbuf;
436 firstbuf = address;
437 dropped = debug_hdr.dropped;
438 length = sizeof(struct dbglog_buf_s);
439 ar6000_ReadDataDiag(ar->arHifDevice, address,
440 (A_UCHAR *)&debug_buf, length);
441
442 do {
443 address = (A_UINT32)debug_buf.buffer;
444 length = debug_buf.length;
445 if ((length) && (debug_buf.length <= debug_buf.bufsize)) {
446 /* Rewind the index if it is about to overrun the buffer */
447 if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) {
448 ar->log_cnt = 0;
449 }
450 if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
451 (A_UCHAR *)&ar->log_buffer[ar->log_cnt], length))
452 {
453 break;
454 }
455 ar6000_dbglog_event(ar, dropped, &ar->log_buffer[ar->log_cnt], length);
456 ar->log_cnt += length;
457 } else {
458 AR_DEBUG_PRINTF("Length: %d (Total size: %d)\n",
459 debug_buf.length, debug_buf.bufsize);
460 }
461
462 address = (A_UINT32)debug_buf.next;
463 length = sizeof(struct dbglog_buf_s);
464 if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
465 (A_UCHAR *)&debug_buf, length))
466 {
467 break;
468 }
469
470 } while (address != firstbuf);
471 }
472
473 ar->dbgLogFetchInProgress = FALSE;
474
475 return A_OK;
476 }
477
478 void
479 ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped,
480 A_INT8 *buffer, A_UINT32 length)
481 {
482 #ifdef REPORT_DEBUG_LOGS_TO_APP
483 #define MAX_WIRELESS_EVENT_SIZE 252
484 /*
485 * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages.
486 * There seems to be a limitation on the length of message that could be
487 * transmitted to the user app via this mechanism.
488 */
489 A_UINT32 send, sent;
490
491 sent = 0;
492 send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
493 MAX_WIRELESS_EVENT_SIZE);
494 while (send) {
495 ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, &buffer[sent], send);
496 sent += send;
497 send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
498 MAX_WIRELESS_EVENT_SIZE);
499 }
500 #else
501 AR_DEBUG_PRINTF("Dropped logs: 0x%x\nDebug info length: %d\n",
502 dropped, length);
503
504 /* Interpret the debug logs */
505 dbglog_parse_debug_logs(buffer, length);
506 #endif /* REPORT_DEBUG_LOGS_TO_APP */
507 }
508
509
510
511 static int __init
512 ar6000_init_module(void)
513 {
514 static int probed = 0;
515 A_STATUS status;
516 HTC_INIT_INFO initInfo;
517
518 A_MEMZERO(&initInfo,sizeof(initInfo));
519 initInfo.AddInstance = ar6000_avail_ev;
520 initInfo.DeleteInstance = ar6000_unavail_ev;
521 initInfo.TargetFailure = ar6000_target_failure;
522
523
524 #ifdef DEBUG
525 /* Set the debug flags if specified at load time */
526 if(debugflags != 0)
527 {
528 g_dbg_flags = debugflags;
529 }
530 #endif
531
532 if (probed) {
533 return -ENODEV;
534 }
535 probed++;
536
537 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
538 memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD));
539 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
540
541 #ifdef CONFIG_HOST_GPIO_SUPPORT
542 ar6000_gpio_init();
543 #endif /* CONFIG_HOST_GPIO_SUPPORT */
544
545 status = HTCInit(&initInfo);
546 if(status != A_OK)
547 return -ENODEV;
548
549 return 0;
550 }
551
552 static void __exit
553 ar6000_cleanup_module(void)
554 {
555 int i = 0;
556 struct net_device *ar6000_netdev;
557
558 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
559 /* Delete the Adaptive Power Control timer */
560 if (timer_pending(&aptcTimer)) {
561 del_timer_sync(&aptcTimer);
562 }
563 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
564
565 for (i=0; i < MAX_AR6000; i++) {
566 if (ar6000_devices[i] != NULL) {
567 ar6000_netdev = ar6000_devices[i];
568 ar6000_devices[i] = NULL;
569 ar6000_destroy(ar6000_netdev, 1);
570 }
571 }
572
573 /* shutting down HTC will cause the HIF layer to detach from the
574 * underlying bus driver which will cause the subsequent deletion of
575 * all HIF and HTC instances */
576 HTCShutDown();
577
578 AR_DEBUG_PRINTF("ar6000_cleanup: success\n");
579 }
580
581 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
582 void
583 aptcTimerHandler(unsigned long arg)
584 {
585 A_UINT32 numbytes;
586 A_UINT32 throughput;
587 AR_SOFTC_T *ar;
588 A_STATUS status;
589
590 ar = (AR_SOFTC_T *)arg;
591 A_ASSERT(ar != NULL);
592 A_ASSERT(!timer_pending(&aptcTimer));
593
594 AR6000_SPIN_LOCK(&ar->arLock, 0);
595
596 /* Get the number of bytes transferred */
597 numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
598 aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
599
600 /* Calculate and decide based on throughput thresholds */
601 throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */
602 if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) {
603 /* Enable Sleep and delete the timer */
604 A_ASSERT(ar->arWmiReady == TRUE);
605 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
606 status = wmi_powermode_cmd(ar->arWmi, REC_POWER);
607 AR6000_SPIN_LOCK(&ar->arLock, 0);
608 A_ASSERT(status == A_OK);
609 aptcTR.timerScheduled = FALSE;
610 } else {
611 A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
612 }
613
614 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
615 }
616 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
617
618
619
620 /* set HTC block size, assume BMI is already initialized */
621 A_STATUS ar6000_SetHTCBlockSize(AR_SOFTC_T *ar)
622 {
623 A_STATUS status;
624 A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX];
625
626 do {
627 /* get the block sizes */
628 status = HIFConfigureDevice(ar->arHifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
629 blocksizes, sizeof(blocksizes));
630
631 if (A_FAILED(status)) {
632 AR_DEBUG_PRINTF("Failed to get block size info from HIF layer...\n");
633 break;
634 }
635 /* note: we actually get the block size for mailbox 1, for SDIO the block
636 * size on mailbox 0 is artificially set to 1 */
637 /* must be a power of 2 */
638 A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0);
639
640 /* set the host interest area for the block size */
641 status = BMIWriteMemory(ar->arHifDevice,
642 HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_io_block_sz),
643 (A_UCHAR *)&blocksizes[1],
644 4);
645
646 if (A_FAILED(status)) {
647 AR_DEBUG_PRINTF("BMIWriteMemory for IO block size failed \n");
648 break;
649 }
650
651 AR_DEBUG_PRINTF("Block Size Set: %d (target address:0x%X)\n",
652 blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_io_block_sz));
653
654 /* set the host interest area for the mbox ISR yield limit */
655 status = BMIWriteMemory(ar->arHifDevice,
656 HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_isr_yield_limit),
657 (A_UCHAR *)&mbox_yield_limit,
658 4);
659
660 if (A_FAILED(status)) {
661 AR_DEBUG_PRINTF("BMIWriteMemory for yield limit failed \n");
662 break;
663 }
664
665 } while (FALSE);
666
667 return status;
668 }
669
670 static void free_raw_buffers(AR_SOFTC_T *ar)
671 {
672 int i, j;
673
674 for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) {
675 for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++)
676 kfree(ar->raw_htc_read_buffer[i][j]);
677 for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++)
678 kfree(ar->raw_htc_write_buffer[i][j]);
679 }
680 }
681
682 static int alloc_raw_buffers(AR_SOFTC_T *ar)
683 {
684 int i, j;
685 raw_htc_buffer *b;
686
687 for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) {
688 for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++) {
689 b = kzalloc(sizeof(*b), GFP_KERNEL);
690 if (!b)
691 return -ENOMEM;
692 ar->raw_htc_read_buffer[i][j] = b;
693 }
694 for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++) {
695 b = kzalloc(sizeof(*b), GFP_KERNEL);
696 if (!b)
697 return -ENOMEM;
698 ar->raw_htc_write_buffer[i][j] = b;
699 }
700 }
701 return 0;
702 }
703
704 /*
705 * HTC Event handlers
706 */
707 static void
708 ar6000_avail_ev(HTC_HANDLE HTCHandle)
709 {
710 int i;
711 struct net_device *dev;
712 AR_SOFTC_T *ar;
713 int device_index = 0;
714
715 AR_DEBUG_PRINTF("ar6000_available\n");
716
717 for (i=0; i < MAX_AR6000; i++) {
718 if (ar6000_devices[i] == NULL) {
719 break;
720 }
721 }
722
723 if (i == MAX_AR6000) {
724 AR_DEBUG_PRINTF("ar6000_available: max devices reached\n");
725 return;
726 }
727
728 /* Save this. It gives a bit better readability especially since */
729 /* we use another local "i" variable below. */
730 device_index = i;
731
732 A_ASSERT(HTCHandle != NULL);
733
734 dev = alloc_etherdev(sizeof(AR_SOFTC_T));
735 if (dev == NULL) {
736 AR_DEBUG_PRINTF("ar6000_available: can't alloc etherdev\n");
737 return;
738 }
739
740 ether_setup(dev);
741
742 if (netdev_priv(dev) == NULL) {
743 printk(KERN_CRIT "ar6000_available: Could not allocate memory\n");
744 return;
745 }
746
747 A_MEMZERO(netdev_priv(dev), sizeof(AR_SOFTC_T));
748
749 ar = (AR_SOFTC_T *)netdev_priv(dev);
750 ar->arNetDev = dev;
751 ar->arHtcTarget = HTCHandle;
752 ar->arHifDevice = HTCGetHifDevice(HTCHandle);
753 ar->arWlanState = WLAN_ENABLED;
754 ar->arRadioSwitch = WLAN_ENABLED;
755 ar->arDeviceIndex = device_index;
756
757 A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev);
758 ar->arHBChallengeResp.seqNum = 0;
759 ar->arHBChallengeResp.outstanding = FALSE;
760 ar->arHBChallengeResp.missCnt = 0;
761 ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT;
762 ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT;
763
764 ar6000_init_control_info(ar);
765 init_waitqueue_head(&arEvent);
766 sema_init(&ar->arSem, 1);
767
768 if (alloc_raw_buffers(ar)) {
769 free_raw_buffers(ar);
770 /*
771 * @@@ Clean up our own mess, but for anything else, cheerfully mimick
772 * the beautiful error non-handling of the rest of this function.
773 */
774 return;
775 }
776
777 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
778 A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar);
779 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
780
781 /*
782 * If requested, perform some magic which requires no cooperation from
783 * the Target. It causes the Target to ignore flash and execute to the
784 * OS from ROM.
785 *
786 * This is intended to support recovery from a corrupted flash on Targets
787 * that support flash.
788 */
789 if (skipflash)
790 {
791 ar6000_reset_device_skipflash(ar->arHifDevice);
792 }
793
794 BMIInit();
795 {
796 struct bmi_target_info targ_info;
797
798 if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != A_OK) {
799 return;
800 }
801
802 ar->arVersion.target_ver = targ_info.target_ver;
803 ar->arTargetType = targ_info.target_type;
804 }
805
806 if (enableuartprint) {
807 A_UINT32 param;
808 param = 1;
809 if (BMIWriteMemory(ar->arHifDevice,
810 HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable),
811 (A_UCHAR *)&param,
812 4)!= A_OK)
813 {
814 AR_DEBUG_PRINTF("BMIWriteMemory for enableuartprint failed \n");
815 return ;
816 }
817 AR_DEBUG_PRINTF("Serial console prints enabled\n");
818 }
819 #ifdef CONFIG_HOST_TCMD_SUPPORT
820 if(testmode) {
821 ar->arTargetMode = AR6000_TCMD_MODE;
822 }else {
823 ar->arTargetMode = AR6000_WLAN_MODE;
824 }
825 #endif
826 if (enabletimerwar) {
827 A_UINT32 param;
828
829 if (BMIReadMemory(ar->arHifDevice,
830 HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
831 (A_UCHAR *)&param,
832 4)!= A_OK)
833 {
834 AR_DEBUG_PRINTF("BMIReadMemory for enabletimerwar failed \n");
835 return;
836 }
837
838 param |= HI_OPTION_TIMER_WAR;
839
840 if (BMIWriteMemory(ar->arHifDevice,
841 HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
842 (A_UCHAR *)&param,
843 4) != A_OK)
844 {
845 AR_DEBUG_PRINTF("BMIWriteMemory for enabletimerwar failed \n");
846 return;
847 }
848 AR_DEBUG_PRINTF("Timer WAR enabled\n");
849 }
850
851
852 /* since BMIInit is called in the driver layer, we have to set the block
853 * size here for the target */
854
855 if (A_FAILED(ar6000_SetHTCBlockSize(ar))) {
856 return;
857 }
858
859 spin_lock_init(&ar->arLock);
860
861 /* Don't install the init function if BMI is requested */
862 if(!bmienable)
863 {
864 dev->init = ar6000_init;
865 } else {
866 AR_DEBUG_PRINTF(" BMI enabled \n");
867 }
868
869 dev->open = &ar6000_open;
870 dev->stop = &ar6000_close;
871 dev->hard_start_xmit = &ar6000_data_tx;
872 dev->get_stats = &ar6000_get_stats;
873
874 /* dev->tx_timeout = ar6000_tx_timeout; */
875 dev->do_ioctl = &ar6000_ioctl;
876 dev->watchdog_timeo = AR6000_TX_TIMEOUT;
877 ar6000_ioctl_iwsetup(&ath_iw_handler_def);
878 dev->wireless_handlers = &ath_iw_handler_def;
879 ath_iw_handler_def.get_wireless_stats = ar6000_get_iwstats; /*Displayed via proc fs */
880
881 /*
882 * We need the OS to provide us with more headroom in order to
883 * perform dix to 802.3, WMI header encap, and the HTC header
884 */
885 dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) +
886 sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN;
887
888 /* This runs the init function */
889 SET_NETDEV_DEV(dev, HIFGetOSDevice(ar->arHifDevice));
890 if (register_netdev(dev)) {
891 AR_DEBUG_PRINTF("ar6000_avail: register_netdev failed\n");
892 ar6000_destroy(dev, 0);
893 return;
894 }
895
896 HTCSetInstance(ar->arHtcTarget, ar);
897
898 /* We only register the device in the global list if we succeed. */
899 /* If the device is in the global list, it will be destroyed */
900 /* when the module is unloaded. */
901 ar6000_devices[device_index] = dev;
902
903 AR_DEBUG_PRINTF("ar6000_avail: name=%s htcTarget=0x%x, dev=0x%x (%d), ar=0x%x\n",
904 dev->name, (A_UINT32)HTCHandle, (A_UINT32)dev, device_index,
905 (A_UINT32)ar);
906 }
907
908 static void ar6000_target_failure(void *Instance, A_STATUS Status)
909 {
910 AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
911 WMI_TARGET_ERROR_REPORT_EVENT errEvent;
912 static A_BOOL sip = FALSE;
913
914 if (Status != A_OK) {
915 if (timer_pending(&ar->arHBChallengeResp.timer)) {
916 A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
917 }
918
919 /* try dumping target assertion information (if any) */
920 ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType);
921
922 /*
923 * Fetch the logs from the target via the diagnostic
924 * window.
925 */
926 ar6000_dbglog_get_debug_logs(ar);
927
928 /* Report the error only once */
929 if (!sip) {
930 sip = TRUE;
931 errEvent.errorVal = WMI_TARGET_COM_ERR |
932 WMI_TARGET_FATAL_ERR;
933 #ifdef SEND_EVENT_TO_APP
934 ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
935 (A_UINT8 *)&errEvent,
936 sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
937 #endif
938 }
939 }
940 }
941
942 static void
943 ar6000_unavail_ev(void *Instance)
944 {
945 AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
946 /* NULL out it's entry in the global list */
947 ar6000_devices[ar->arDeviceIndex] = NULL;
948 ar6000_destroy(ar->arNetDev, 1);
949 }
950
951 /*
952 * We need to differentiate between the surprise and planned removal of the
953 * device because of the following consideration:
954 * - In case of surprise removal, the hcd already frees up the pending
955 * for the device and hence there is no need to unregister the function
956 * driver inorder to get these requests. For planned removal, the function
957 * driver has to explictly unregister itself to have the hcd return all the
958 * pending requests before the data structures for the devices are freed up.
959 * Note that as per the current implementation, the function driver will
960 * end up releasing all the devices since there is no API to selectively
961 * release a particular device.
962 * - Certain commands issued to the target can be skipped for surprise
963 * removal since they will anyway not go through.
964 */
965 static void
966 ar6000_destroy(struct net_device *dev, unsigned int unregister)
967 {
968 AR_SOFTC_T *ar;
969
970 AR_DEBUG_PRINTF("+ar6000_destroy \n");
971
972 if((dev == NULL) || ((ar = netdev_priv(dev)) == NULL))
973 {
974 AR_DEBUG_PRINTF("%s(): Failed to get device structure.\n", __func__);
975 return;
976 }
977
978 /* Clear the tx counters */
979 memset(tx_attempt, 0, sizeof(tx_attempt));
980 memset(tx_post, 0, sizeof(tx_post));
981 memset(tx_complete, 0, sizeof(tx_complete));
982
983 /* Free up the device data structure */
984 if (unregister) {
985 unregister_netdev(dev);
986 } else {
987 ar6000_close(dev);
988 ar6000_cleanup(dev);
989 }
990
991 free_raw_buffers(ar);
992
993 #ifndef free_netdev
994 kfree(dev);
995 #else
996 free_netdev(dev);
997 #endif
998
999 AR_DEBUG_PRINTF("-ar6000_destroy \n");
1000 }
1001
1002 static void ar6000_detect_error(unsigned long ptr)
1003 {
1004 struct net_device *dev = (struct net_device *)ptr;
1005 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1006 WMI_TARGET_ERROR_REPORT_EVENT errEvent;
1007
1008 AR6000_SPIN_LOCK(&ar->arLock, 0);
1009
1010 if (ar->arHBChallengeResp.outstanding) {
1011 ar->arHBChallengeResp.missCnt++;
1012 } else {
1013 ar->arHBChallengeResp.missCnt = 0;
1014 }
1015
1016 if (ar->arHBChallengeResp.missCnt > ar->arHBChallengeResp.missThres) {
1017 /* Send Error Detect event to the application layer and do not reschedule the error detection module timer */
1018 ar->arHBChallengeResp.missCnt = 0;
1019 ar->arHBChallengeResp.seqNum = 0;
1020 errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR;
1021 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1022 #ifdef SEND_EVENT_TO_APP
1023 ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
1024 (A_UINT8 *)&errEvent,
1025 sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
1026 #endif
1027 return;
1028 }
1029
1030 /* Generate the sequence number for the next challenge */
1031 ar->arHBChallengeResp.seqNum++;
1032 ar->arHBChallengeResp.outstanding = TRUE;
1033
1034 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1035
1036 /* Send the challenge on the control channel */
1037 if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != A_OK) {
1038 AR_DEBUG_PRINTF("Unable to send heart beat challenge\n");
1039 }
1040
1041
1042 /* Reschedule the timer for the next challenge */
1043 A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
1044 }
1045
1046 void ar6000_init_profile_info(AR_SOFTC_T *ar)
1047 {
1048 ar->arSsidLen = 0;
1049 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1050 ar->arNetworkType = INFRA_NETWORK;
1051 ar->arDot11AuthMode = OPEN_AUTH;
1052 ar->arAuthMode = NONE_AUTH;
1053 ar->arPairwiseCrypto = NONE_CRYPT;
1054 ar->arPairwiseCryptoLen = 0;
1055 ar->arGroupCrypto = NONE_CRYPT;
1056 ar->arGroupCryptoLen = 0;
1057 A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
1058 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
1059 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
1060 ar->arBssChannel = 0;
1061 }
1062
1063 static void
1064 ar6000_init_control_info(AR_SOFTC_T *ar)
1065 {
1066 ar->arWmiEnabled = FALSE;
1067 ar6000_init_profile_info(ar);
1068 ar->arDefTxKeyIndex = 0;
1069 A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
1070 ar->arChannelHint = 0;
1071 ar->arListenInterval = MAX_LISTEN_INTERVAL;
1072 ar->arVersion.host_ver = AR6K_SW_VERSION;
1073 ar->arRssi = 0;
1074 ar->arTxPwr = 0;
1075 ar->arTxPwrSet = FALSE;
1076 ar->arSkipScan = 0;
1077 ar->arBeaconInterval = 0;
1078 ar->arBitRate = 0;
1079 ar->arMaxRetries = 0;
1080 ar->arWmmEnabled = TRUE;
1081 }
1082
1083 static int
1084 ar6000_open(struct net_device *dev)
1085 {
1086 /* Wake up the queues */
1087 netif_start_queue(dev);
1088
1089 return 0;
1090 }
1091
1092 static int
1093 ar6000_close(struct net_device *dev)
1094 {
1095 /* Stop the transmit queues */
1096 netif_stop_queue(dev);
1097 return 0;
1098 }
1099
1100 static int
1101 ar6000_cleanup(struct net_device *dev)
1102 {
1103 AR_SOFTC_T *ar = netdev_priv(dev);
1104
1105 /* Stop the transmit queues */
1106 netif_stop_queue(dev);
1107
1108 /* Disable the target and the interrupts associated with it */
1109 if (ar->arWmiReady == TRUE)
1110 {
1111 if (!bypasswmi)
1112 {
1113 if (ar->arConnected == TRUE || ar->arConnectPending == TRUE)
1114 {
1115 AR_DEBUG_PRINTF("%s(): Disconnect\n", __func__);
1116 AR6000_SPIN_LOCK(&ar->arLock, 0);
1117 ar6000_init_profile_info(ar);
1118 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1119 wmi_disconnect_cmd(ar->arWmi);
1120 }
1121
1122 ar6000_dbglog_get_debug_logs(ar);
1123 ar->arWmiReady = FALSE;
1124 ar->arConnected = FALSE;
1125 ar->arConnectPending = FALSE;
1126 wmi_shutdown(ar->arWmi);
1127 ar->arWmiEnabled = FALSE;
1128 ar->arWmi = NULL;
1129 ar->arWlanState = WLAN_ENABLED;
1130 #ifdef USER_KEYS
1131 ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
1132 ar->user_key_ctrl = 0;
1133 #endif
1134 }
1135
1136 AR_DEBUG_PRINTF("%s(): WMI stopped\n", __func__);
1137 }
1138 else
1139 {
1140 AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n",
1141 __func__, (unsigned int) ar, (unsigned int) ar->arWmi);
1142
1143 /* Shut down WMI if we have started it */
1144 if(ar->arWmiEnabled == TRUE)
1145 {
1146 AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__);
1147 wmi_shutdown(ar->arWmi);
1148 ar->arWmiEnabled = FALSE;
1149 ar->arWmi = NULL;
1150 }
1151 }
1152
1153 /* stop HTC */
1154 HTCStop(ar->arHtcTarget);
1155
1156 /* set the instance to NULL so we do not get called back on remove incase we
1157 * we're explicity destroyed by module unload */
1158 HTCSetInstance(ar->arHtcTarget, NULL);
1159
1160 if (resetok) {
1161 /* try to reset the device if we can
1162 * The driver may have been configure NOT to reset the target during
1163 * a debug session */
1164 AR_DEBUG_PRINTF(" Attempting to reset target on instance destroy.... \n");
1165 ar6000_reset_device(ar->arHifDevice, ar->arTargetType);
1166 } else {
1167 AR_DEBUG_PRINTF(" Host does not want target reset. \n");
1168 }
1169
1170 /* Done with cookies */
1171 ar6000_cookie_cleanup(ar);
1172
1173 /* Cleanup BMI */
1174 BMIInit();
1175
1176 return 0;
1177 }
1178
1179 /* connect to a service */
1180 static A_STATUS ar6000_connectservice(AR_SOFTC_T *ar,
1181 HTC_SERVICE_CONNECT_REQ *pConnect,
1182 WMI_PRI_STREAM_ID WmiStreamID,
1183 char *pDesc)
1184 {
1185 A_STATUS status;
1186 HTC_SERVICE_CONNECT_RESP response;
1187
1188 do {
1189
1190 A_MEMZERO(&response,sizeof(response));
1191
1192 status = HTCConnectService(ar->arHtcTarget,
1193 pConnect,
1194 &response);
1195
1196 if (A_FAILED(status)) {
1197 AR_DEBUG_PRINTF(" Failed to connect to %s service status:%d \n", pDesc, status);
1198 break;
1199 }
1200
1201 if (WmiStreamID == WMI_NOT_MAPPED) {
1202 /* done */
1203 break;
1204 }
1205
1206 /* set endpoint mapping for the WMI stream in the driver layer */
1207 arSetWMIStream2EndpointIDMap(ar,WmiStreamID,response.Endpoint);
1208
1209 } while (FALSE);
1210
1211 return status;
1212 }
1213
1214 static void ar6000_TxDataCleanup(AR_SOFTC_T *ar)
1215 {
1216 /* flush all the data (non-control) streams
1217 * we only flush packets that are tagged as data, we leave any control packets that
1218 * were in the TX queues alone */
1219 HTCFlushEndpoint(ar->arHtcTarget,
1220 arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI),
1221 AR6K_DATA_PKT_TAG);
1222 HTCFlushEndpoint(ar->arHtcTarget,
1223 arWMIStream2EndpointID(ar,WMI_LOW_PRI),
1224 AR6K_DATA_PKT_TAG);
1225 HTCFlushEndpoint(ar->arHtcTarget,
1226 arWMIStream2EndpointID(ar,WMI_HIGH_PRI),
1227 AR6K_DATA_PKT_TAG);
1228 HTCFlushEndpoint(ar->arHtcTarget,
1229 arWMIStream2EndpointID(ar,WMI_HIGHEST_PRI),
1230 AR6K_DATA_PKT_TAG);
1231 }
1232
1233 /* This function does one time initialization for the lifetime of the device */
1234 int ar6000_init(struct net_device *dev)
1235 {
1236 AR_SOFTC_T *ar;
1237 A_STATUS status;
1238 A_INT32 timeleft;
1239
1240 if((ar = netdev_priv(dev)) == NULL)
1241 {
1242 return(-EIO);
1243 }
1244
1245 /* Do we need to finish the BMI phase */
1246 if(BMIDone(ar->arHifDevice) != A_OK)
1247 {
1248 return -EIO;
1249 }
1250
1251 if (!bypasswmi)
1252 {
1253 #if 0 /* TBDXXX */
1254 if (ar->arVersion.host_ver != ar->arVersion.target_ver) {
1255 A_PRINTF("WARNING: Host version 0x%x does not match Target "
1256 " version 0x%x!\n",
1257 ar->arVersion.host_ver, ar->arVersion.target_ver);
1258 }
1259 #endif
1260
1261 /* Indicate that WMI is enabled (although not ready yet) */
1262 ar->arWmiEnabled = TRUE;
1263 if ((ar->arWmi = wmi_init((void *) ar)) == NULL)
1264 {
1265 AR_DEBUG_PRINTF("%s() Failed to initialize WMI.\n", __func__);
1266 return(-EIO);
1267 }
1268
1269 AR_DEBUG_PRINTF("%s() Got WMI @ 0x%08x.\n", __func__,
1270 (unsigned int) ar->arWmi);
1271 }
1272
1273 do {
1274 HTC_SERVICE_CONNECT_REQ connect;
1275
1276 /* the reason we have to wait for the target here is that the driver layer
1277 * has to init BMI in order to set the host block size,
1278 */
1279 status = HTCWaitTarget(ar->arHtcTarget);
1280
1281 if (A_FAILED(status)) {
1282 break;
1283 }
1284
1285 A_MEMZERO(&connect,sizeof(connect));
1286 /* meta data is unused for now */
1287 connect.pMetaData = NULL;
1288 connect.MetaDataLength = 0;
1289 /* these fields are the same for all service endpoints */
1290 connect.EpCallbacks.pContext = ar;
1291 connect.EpCallbacks.EpTxComplete = ar6000_tx_complete;
1292 connect.EpCallbacks.EpRecv = ar6000_rx;
1293 connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill;
1294 connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full;
1295 connect.EpCallbacks.EpSendAvail = ar6000_tx_queue_avail;
1296 /* set the max queue depth so that our ar6000_tx_queue_full handler gets called.
1297 * Linux has the peculiarity of not providing flow control between the
1298 * NIC and the network stack. There is no API to indicate that a TX packet
1299 * was sent which could provide some back pressure to the network stack.
1300 * Under linux you would have to wait till the network stack consumed all sk_buffs
1301 * before any back-flow kicked in. Which isn't very friendly.
1302 * So we have to manage this ourselves */
1303 connect.MaxSendQueueDepth = 32;
1304
1305 /* connect to control service */
1306 connect.ServiceID = WMI_CONTROL_SVC;
1307 status = ar6000_connectservice(ar,
1308 &connect,
1309 WMI_CONTROL_PRI,
1310 "WMI CONTROL");
1311 if (A_FAILED(status)) {
1312 break;
1313 }
1314
1315 /* for the remaining data services set the connection flag to reduce dribbling,
1316 * if configured to do so */
1317 if (reduce_credit_dribble) {
1318 connect.ConnectionFlags |= HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE;
1319 /* the credit dribble trigger threshold is (reduce_credit_dribble - 1) for a value
1320 * of 0-3 */
1321 connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
1322 connect.ConnectionFlags |=
1323 ((A_UINT16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
1324 }
1325 /* connect to best-effort service */
1326 connect.ServiceID = WMI_DATA_BE_SVC;
1327
1328 status = ar6000_connectservice(ar,
1329 &connect,
1330 WMI_BEST_EFFORT_PRI,
1331 "WMI DATA BE");
1332 if (A_FAILED(status)) {
1333 break;
1334 }
1335
1336 /* connect to back-ground
1337 * map this to WMI LOW_PRI */
1338 connect.ServiceID = WMI_DATA_BK_SVC;
1339 status = ar6000_connectservice(ar,
1340 &connect,
1341 WMI_LOW_PRI,
1342 "WMI DATA BK");
1343 if (A_FAILED(status)) {
1344 break;
1345 }
1346
1347 /* connect to Video service, map this to
1348 * to HI PRI */
1349 connect.ServiceID = WMI_DATA_VI_SVC;
1350 status = ar6000_connectservice(ar,
1351 &connect,
1352 WMI_HIGH_PRI,
1353 "WMI DATA VI");
1354 if (A_FAILED(status)) {
1355 break;
1356 }
1357
1358 /* connect to VO service, this is currently not
1359 * mapped to a WMI priority stream due to historical reasons.
1360 * WMI originally defined 3 priorities over 3 mailboxes
1361 * We can change this when WMI is reworked so that priorities are not
1362 * dependent on mailboxes */
1363 connect.ServiceID = WMI_DATA_VO_SVC;
1364 status = ar6000_connectservice(ar,
1365 &connect,
1366 WMI_HIGHEST_PRI,
1367 "WMI DATA VO");
1368 if (A_FAILED(status)) {
1369 break;
1370 }
1371
1372 A_ASSERT(arWMIStream2EndpointID(ar,WMI_CONTROL_PRI) != 0);
1373 A_ASSERT(arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI) != 0);
1374 A_ASSERT(arWMIStream2EndpointID(ar,WMI_LOW_PRI) != 0);
1375 A_ASSERT(arWMIStream2EndpointID(ar,WMI_HIGH_PRI) != 0);
1376 A_ASSERT(arWMIStream2EndpointID(ar,WMI_HIGHEST_PRI) != 0);
1377 } while (FALSE);
1378
1379 if (A_FAILED(status)) {
1380 return (-EIO);
1381 }
1382
1383 /*
1384 * give our connected endpoints some buffers
1385 */
1386 ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_CONTROL_PRI));
1387
1388 ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI));
1389
1390 /*
1391 * We will post the receive buffers only for SPE testing and so we are
1392 * making it conditional on the 'bypasswmi' flag.
1393 */
1394 if (bypasswmi) {
1395 ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_LOW_PRI));
1396 ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_HIGH_PRI));
1397 }
1398
1399 /* setup credit distribution */
1400 ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo);
1401
1402 /* Since cookies are used for HTC transports, they should be */
1403 /* initialized prior to enabling HTC. */
1404 ar6000_cookie_init(ar);
1405
1406 /* start HTC */
1407 status = HTCStart(ar->arHtcTarget);
1408
1409 if (status != A_OK) {
1410 if (ar->arWmiEnabled == TRUE) {
1411 wmi_shutdown(ar->arWmi);
1412 ar->arWmiEnabled = FALSE;
1413 ar->arWmi = NULL;
1414 }
1415 ar6000_cookie_cleanup(ar);
1416 return -EIO;
1417 }
1418
1419 if (!bypasswmi) {
1420 /* Wait for Wmi event to be ready */
1421 timeleft = wait_event_interruptible_timeout(arEvent,
1422 (ar->arWmiReady == TRUE), wmitimeout * HZ);
1423
1424 if(!timeleft || signal_pending(current))
1425 {
1426 AR_DEBUG_PRINTF("WMI is not ready or wait was interrupted\n");
1427 #if defined(DWSIM) /* TBDXXX */
1428 AR_DEBUG_PRINTF(".....but proceed anyway.\n");
1429 #else
1430 return -EIO;
1431 #endif
1432 }
1433
1434 AR_DEBUG_PRINTF("%s() WMI is ready\n", __func__);
1435
1436 /* Communicate the wmi protocol verision to the target */
1437 if ((ar6000_set_host_app_area(ar)) != A_OK) {
1438 AR_DEBUG_PRINTF("Unable to set the host app area\n");
1439 }
1440 }
1441
1442 ar->arNumDataEndPts = 1;
1443
1444 return(0);
1445 }
1446
1447
1448 void
1449 ar6000_bitrate_rx(void *devt, A_INT32 rateKbps)
1450 {
1451 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
1452
1453 ar->arBitRate = rateKbps;
1454 wake_up(&arEvent);
1455 }
1456
1457 void
1458 ar6000_ratemask_rx(void *devt, A_UINT16 ratemask)
1459 {
1460 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
1461
1462 ar->arRateMask = ratemask;
1463 wake_up(&arEvent);
1464 }
1465
1466 void
1467 ar6000_txPwr_rx(void *devt, A_UINT8 txPwr)
1468 {
1469 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
1470
1471 ar->arTxPwr = txPwr;
1472 wake_up(&arEvent);
1473 }
1474
1475
1476 void
1477 ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList)
1478 {
1479 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
1480
1481 A_MEMCPY(ar->arChannelList, chanList, numChan * sizeof (A_UINT16));
1482 ar->arNumChannels = numChan;
1483
1484 wake_up(&arEvent);
1485 }
1486
1487 A_UINT8
1488 ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, A_UINT32 * mapNo)
1489 {
1490 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1491 A_UINT8 *datap;
1492 ATH_MAC_HDR *macHdr;
1493 A_UINT32 i, eptMap;
1494
1495 (*mapNo) = 0;
1496 datap = A_NETBUF_DATA(skb);
1497 macHdr = (ATH_MAC_HDR *)(datap + sizeof(WMI_DATA_HDR));
1498 if (IEEE80211_IS_MULTICAST(macHdr->dstMac)) {
1499 return ENDPOINT_2;
1500 }
1501
1502 eptMap = -1;
1503 for (i = 0; i < ar->arNodeNum; i ++) {
1504 if (IEEE80211_ADDR_EQ(macHdr->dstMac, ar->arNodeMap[i].macAddress)) {
1505 (*mapNo) = i + 1;
1506 ar->arNodeMap[i].txPending ++;
1507 return ar->arNodeMap[i].epId;
1508 }
1509
1510 if ((eptMap == -1) && !ar->arNodeMap[i].txPending) {
1511 eptMap = i;
1512 }
1513 }
1514
1515 if (eptMap == -1) {
1516 eptMap = ar->arNodeNum;
1517 ar->arNodeNum ++;
1518 A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM);
1519 }
1520
1521 A_MEMCPY(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN);
1522
1523 for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) {
1524 if (!ar->arTxPending[i]) {
1525 ar->arNodeMap[eptMap].epId = i;
1526 break;
1527 }
1528 // No free endpoint is available, start redistribution on the inuse endpoints.
1529 if (i == ENDPOINT_5) {
1530 ar->arNodeMap[eptMap].epId = ar->arNexEpId;
1531 ar->arNexEpId ++;
1532 if (ar->arNexEpId > ENDPOINT_5) {
1533 ar->arNexEpId = ENDPOINT_2;
1534 }
1535 }
1536 }
1537
1538 (*mapNo) = eptMap + 1;
1539 ar->arNodeMap[eptMap].txPending ++;
1540
1541 return ar->arNodeMap[eptMap].epId;
1542 }
1543
1544 #ifdef DEBUG
1545 static void ar6000_dump_skb(struct sk_buff *skb)
1546 {
1547 u_char *ch;
1548 for (ch = A_NETBUF_DATA(skb);
1549 (A_UINT32)ch < ((A_UINT32)A_NETBUF_DATA(skb) +
1550 A_NETBUF_LEN(skb)); ch++)
1551 {
1552 AR_DEBUG_PRINTF("%2.2x ", *ch);
1553 }
1554 AR_DEBUG_PRINTF("\n");
1555 }
1556 #endif
1557
1558 static int
1559 ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
1560 {
1561 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
1562 WMI_PRI_STREAM_ID streamID = WMI_NOT_MAPPED;
1563 A_UINT32 mapNo = 0;
1564 int len;
1565 struct ar_cookie *cookie;
1566 A_BOOL checkAdHocPsMapping = FALSE;
1567
1568 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
1569 skb->list = NULL;
1570 #endif
1571
1572 AR_DEBUG2_PRINTF("ar6000_data_tx start - skb=0x%x, data=0x%x, len=0x%x\n",
1573 (A_UINT32)skb, (A_UINT32)A_NETBUF_DATA(skb),
1574 A_NETBUF_LEN(skb));
1575 #ifdef CONFIG_HOST_TCMD_SUPPORT
1576 /* TCMD doesnt support any data, free the buf and return */
1577 if(ar->arTargetMode == AR6000_TCMD_MODE) {
1578 A_NETBUF_FREE(skb);
1579 return 0;
1580 }
1581 #endif
1582 do {
1583
1584 if (ar->arWmiReady == FALSE && bypasswmi == 0) {
1585 break;
1586 }
1587
1588 #ifdef BLOCK_TX_PATH_FLAG
1589 if (blocktx) {
1590 break;
1591 }
1592 #endif /* BLOCK_TX_PATH_FLAG */
1593
1594 if (ar->arWmiEnabled) {
1595 if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len) {
1596 struct sk_buff *newbuf;
1597 /*
1598 * We really should have gotten enough headroom but sometimes
1599 * we still get packets with not enough headroom. Copy the packet.
1600 */
1601 len = A_NETBUF_LEN(skb);
1602 newbuf = A_NETBUF_ALLOC(len);
1603 if (newbuf == NULL) {
1604 break;
1605 }
1606 A_NETBUF_PUT(newbuf, len);
1607 A_MEMCPY(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len);
1608 A_NETBUF_FREE(skb);
1609 skb = newbuf;
1610 /* fall through and assemble header */
1611 }
1612
1613 if (wmi_dix_2_dot3(ar->arWmi, skb) != A_OK) {
1614 AR_DEBUG_PRINTF("ar6000_data_tx - wmi_dix_2_dot3 failed\n");
1615 break;
1616 }
1617
1618 if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE) != A_OK) {
1619 AR_DEBUG_PRINTF("ar6000_data_tx - wmi_data_hdr_add failed\n");
1620 break;
1621 }
1622
1623 if ((ar->arNetworkType == ADHOC_NETWORK) &&
1624 ar->arIbssPsEnable && ar->arConnected) {
1625 /* flag to check adhoc mapping once we take the lock below: */
1626 checkAdHocPsMapping = TRUE;
1627
1628 } else {
1629 /* get the stream mapping */
1630 if (ar->arWmmEnabled) {
1631 streamID = wmi_get_stream_id(ar->arWmi,
1632 wmi_implicit_create_pstream(ar->arWmi, skb, UPLINK_TRAFFIC, UNDEFINED_PRI));
1633 } else {
1634 streamID = WMI_BEST_EFFORT_PRI;
1635 }
1636 }
1637
1638 } else {
1639 struct iphdr *ipHdr;
1640 /*
1641 * the endpoint is directly based on the TOS field in the IP
1642 * header **** only for testing ******
1643 */
1644 ipHdr = A_NETBUF_DATA(skb) + sizeof(ATH_MAC_HDR);
1645 /* here we map the TOS field to an endpoint number, this is for
1646 * the endpointping test application */
1647 streamID = IP_TOS_TO_WMI_PRI(ipHdr->tos);
1648 }
1649
1650 } while (FALSE);
1651
1652 /* did we succeed ? */
1653 if ((streamID == WMI_NOT_MAPPED) && !checkAdHocPsMapping) {
1654 /* cleanup and exit */
1655 A_NETBUF_FREE(skb);
1656 AR6000_STAT_INC(ar, tx_dropped);
1657 AR6000_STAT_INC(ar, tx_aborted_errors);
1658 return 0;
1659 }
1660
1661 cookie = NULL;
1662
1663 /* take the lock to protect driver data */
1664 AR6000_SPIN_LOCK(&ar->arLock, 0);
1665
1666 do {
1667
1668 if (checkAdHocPsMapping) {
1669 streamID = ar6000_ibss_map_epid(skb, dev, &mapNo);
1670 }
1671
1672 A_ASSERT(streamID != WMI_NOT_MAPPED);
1673
1674 /* validate that the endpoint is connected */
1675 if (arWMIStream2EndpointID(ar,streamID) == 0) {
1676 AR_DEBUG_PRINTF("Stream %d is NOT mapped!\n",streamID);
1677 break;
1678 }
1679 /* allocate resource for this packet */
1680 cookie = ar6000_alloc_cookie(ar);
1681
1682 if (cookie != NULL) {
1683 /* update counts while the lock is held */
1684 ar->arTxPending[streamID]++;
1685 ar->arTotalTxDataPending++;
1686 }
1687
1688 } while (FALSE);
1689
1690 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1691
1692 if (cookie != NULL) {
1693 cookie->arc_bp[0] = (A_UINT32)skb;
1694 cookie->arc_bp[1] = mapNo;
1695 SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
1696 cookie,
1697 A_NETBUF_DATA(skb),
1698 A_NETBUF_LEN(skb),
1699 arWMIStream2EndpointID(ar,streamID),
1700 AR6K_DATA_PKT_TAG);
1701
1702 #ifdef DEBUG
1703 if (debugdriver >= 3) {
1704 ar6000_dump_skb(skb);
1705 }
1706 #endif
1707 /* HTC interface is asynchronous, if this fails, cleanup will happen in
1708 * the ar6000_tx_complete callback */
1709 HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
1710 } else {
1711 /* no packet to send, cleanup */
1712 A_NETBUF_FREE(skb);
1713 AR6000_STAT_INC(ar, tx_dropped);
1714 AR6000_STAT_INC(ar, tx_aborted_errors);
1715 }
1716
1717 return 0;
1718 }
1719
1720 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
1721 static void
1722 tvsub(register struct timeval *out, register struct timeval *in)
1723 {
1724 if((out->tv_usec -= in->tv_usec) < 0) {
1725 out->tv_sec--;
1726 out->tv_usec += 1000000;
1727 }
1728 out->tv_sec -= in->tv_sec;
1729 }
1730
1731 void
1732 applyAPTCHeuristics(AR_SOFTC_T *ar)
1733 {
1734 A_UINT32 duration;
1735 A_UINT32 numbytes;
1736 A_UINT32 throughput;
1737 struct timeval ts;
1738 A_STATUS status;
1739
1740 AR6000_SPIN_LOCK(&ar->arLock, 0);
1741
1742 if ((enableAPTCHeuristics) && (!aptcTR.timerScheduled)) {
1743 do_gettimeofday(&ts);
1744 tvsub(&ts, &aptcTR.samplingTS);
1745 duration = ts.tv_sec * 1000 + ts.tv_usec / 1000; /* ms */
1746 numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
1747
1748 if (duration > APTC_TRAFFIC_SAMPLING_INTERVAL) {
1749 /* Initialize the time stamp and byte count */
1750 aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
1751 do_gettimeofday(&aptcTR.samplingTS);
1752
1753 /* Calculate and decide based on throughput thresholds */
1754 throughput = ((numbytes * 8) / duration);
1755 if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) {
1756 /* Disable Sleep and schedule a timer */
1757 A_ASSERT(ar->arWmiReady == TRUE);
1758 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1759 status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER);
1760 AR6000_SPIN_LOCK(&ar->arLock, 0);
1761 A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
1762 aptcTR.timerScheduled = TRUE;
1763 }
1764 }
1765 }
1766
1767 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1768 }
1769 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
1770
1771 static void
1772 ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint)
1773 {
1774 AR_SOFTC_T *ar = (AR_SOFTC_T *) Context;
1775
1776 if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) {
1777 if (!bypasswmi) {
1778 /* under normal WMI if this is getting full, then something is running rampant
1779 * the host should not be exhausting the WMI queue with too many commands
1780 * the only exception to this is during testing using endpointping */
1781
1782 AR6000_SPIN_LOCK(&ar->arLock, 0);
1783 /* set flag to handle subsequent messages */
1784 ar->arWMIControlEpFull = TRUE;
1785 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1786 AR_DEBUG_PRINTF("WMI Control Endpoint is FULL!!! \n");
1787 }
1788 } else {
1789 /* one of the data endpoints queues is getting full..need to stop network stack
1790 * the queue will resume after credits received */
1791 netif_stop_queue(ar->arNetDev);
1792 }
1793 }
1794
1795 static void
1796 ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint)
1797 {
1798 AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
1799
1800 if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) {
1801 /* FIXME: what do for it? */
1802 } else {
1803 /* Wake up interface, rescheduling prevented. */
1804 if (ar->arConnected == TRUE || bypasswmi)
1805 netif_wake_queue(ar->arNetDev);
1806 }
1807 }
1808
1809 static void
1810 ar6000_tx_complete(void *Context, HTC_PACKET *pPacket)
1811 {
1812 AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
1813 void *cookie = (void *)pPacket->pPktContext;
1814 struct sk_buff *skb = NULL;
1815 A_UINT32 mapNo = 0;
1816 A_STATUS status;
1817 struct ar_cookie * ar_cookie;
1818 WMI_PRI_STREAM_ID streamID;
1819 A_BOOL wakeEvent = FALSE;
1820
1821 status = pPacket->Status;
1822 ar_cookie = (struct ar_cookie *)cookie;
1823 skb = (struct sk_buff *)ar_cookie->arc_bp[0];
1824 streamID = arEndpoint2WMIStreamID(ar,pPacket->Endpoint);
1825 mapNo = ar_cookie->arc_bp[1];
1826
1827 A_ASSERT(skb);
1828 A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(skb));
1829
1830 if (A_SUCCESS(status)) {
1831 A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(skb));
1832 }
1833
1834 AR_DEBUG2_PRINTF("ar6000_tx_complete skb=0x%x data=0x%x len=0x%x sid=%d ",
1835 (A_UINT32)skb, (A_UINT32)pPacket->pBuffer,
1836 pPacket->ActualLength,
1837 streamID);
1838
1839 /* lock the driver as we update internal state */
1840 AR6000_SPIN_LOCK(&ar->arLock, 0);
1841
1842 ar->arTxPending[streamID]--;
1843
1844 if ((streamID != WMI_CONTROL_PRI) || bypasswmi) {
1845 ar->arTotalTxDataPending--;
1846 }
1847
1848 if (streamID == WMI_CONTROL_PRI)
1849 {
1850 if (ar->arWMIControlEpFull) {
1851 /* since this packet completed, the WMI EP is no longer full */
1852 ar->arWMIControlEpFull = FALSE;
1853 }
1854
1855 if (ar->arTxPending[streamID] == 0) {
1856 wakeEvent = TRUE;
1857 }
1858 }
1859
1860 if (A_FAILED(status)) {
1861 AR_DEBUG_PRINTF("%s() -TX ERROR, status: 0x%x\n", __func__,
1862 status);
1863 AR6000_STAT_INC(ar, tx_errors);
1864 } else {
1865 AR_DEBUG2_PRINTF("OK\n");
1866 AR6000_STAT_INC(ar, tx_packets);
1867 ar->arNetStats.tx_bytes += A_NETBUF_LEN(skb);
1868 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
1869 aptcTR.bytesTransmitted += a_netbuf_to_len(skb);
1870 applyAPTCHeuristics(ar);
1871 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
1872 }
1873
1874 // TODO this needs to be looked at
1875 if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable
1876 && (streamID != WMI_CONTROL_PRI) && mapNo)
1877 {
1878 mapNo --;
1879 ar->arNodeMap[mapNo].txPending --;
1880
1881 if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) {
1882 A_UINT32 i;
1883 for (i = ar->arNodeNum; i > 0; i --) {
1884 if (!ar->arNodeMap[i - 1].txPending) {
1885 A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping));
1886 ar->arNodeNum --;
1887 } else {
1888 break;
1889 }
1890 }
1891 }
1892 }
1893
1894 /* Freeing a cookie should not be contingent on either of */
1895 /* these flags, just if we have a cookie or not. */
1896 /* Can we even get here without a cookie? Fix later. */
1897 if (ar->arWmiReady == TRUE || (bypasswmi))
1898 {
1899 ar6000_free_cookie(ar, cookie);
1900 }
1901
1902 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1903
1904 /* lock is released, we can freely call other kernel APIs */
1905
1906 /* this indirectly frees the HTC_PACKET */
1907 A_NETBUF_FREE(skb);
1908
1909 if (wakeEvent) {
1910 wake_up(&arEvent);
1911 }
1912 }
1913
1914 /*
1915 * Receive event handler. This is called by HTC when a packet is received
1916 */
1917 int pktcount;
1918 static void
1919 ar6000_rx(void *Context, HTC_PACKET *pPacket)
1920 {
1921 AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
1922 struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext;
1923 int minHdrLen;
1924 A_STATUS status = pPacket->Status;
1925 WMI_PRI_STREAM_ID streamID = arEndpoint2WMIStreamID(ar,pPacket->Endpoint);
1926 HTC_ENDPOINT_ID ept = pPacket->Endpoint;
1927
1928 A_ASSERT((status != A_OK) || (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN)));
1929
1930 AR_DEBUG2_PRINTF("ar6000_rx ar=0x%x sid=%d, skb=0x%x, data=0x%x, len=0x%x ",
1931 (A_UINT32)ar, streamID, (A_UINT32)skb, (A_UINT32)pPacket->pBuffer,
1932 pPacket->ActualLength);
1933 if (status != A_OK) {
1934 AR_DEBUG2_PRINTF("ERR\n");
1935 } else {
1936 AR_DEBUG2_PRINTF("OK\n");
1937 }
1938
1939 /* take lock to protect buffer counts
1940 * and adaptive power throughput state */
1941 AR6000_SPIN_LOCK(&ar->arLock, 0);
1942
1943 ar->arRxBuffers[streamID]--;
1944
1945 if (A_SUCCESS(status)) {
1946 AR6000_STAT_INC(ar, rx_packets);
1947 ar->arNetStats.rx_bytes += pPacket->ActualLength;
1948 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
1949 aptcTR.bytesReceived += a_netbuf_to_len(skb);
1950 applyAPTCHeuristics(ar);
1951 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
1952
1953 A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN);
1954 A_NETBUF_PULL(skb, HTC_HEADER_LEN);
1955
1956 #ifdef DEBUG
1957 if (debugdriver >= 2) {
1958 ar6000_dump_skb(skb);
1959 }
1960 #endif /* DEBUG */
1961 }
1962
1963 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
1964
1965 if (status != A_OK) {
1966 AR6000_STAT_INC(ar, rx_errors);
1967 A_NETBUF_FREE(skb);
1968 } else if (ar->arWmiEnabled == TRUE) {
1969 if (streamID == WMI_CONTROL_PRI) {
1970 /*
1971 * this is a wmi control msg
1972 */
1973 wmi_control_rx(ar->arWmi, skb);
1974 } else {
1975 WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb);
1976 if (WMI_DATA_HDR_IS_MSG_TYPE(dhdr, CNTL_MSGTYPE)) {
1977 /*
1978 * this is a wmi control msg
1979 */
1980 /* strip off WMI hdr */
1981 wmi_data_hdr_remove(ar->arWmi, skb);
1982 wmi_control_rx(ar->arWmi, skb);
1983 } else {
1984 /*
1985 * this is a wmi data packet
1986 */
1987 minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) +
1988 sizeof(ATH_LLC_SNAP_HDR);
1989
1990 if ((pPacket->ActualLength < minHdrLen) ||
1991 (pPacket->ActualLength > AR6000_BUFFER_SIZE))
1992 {
1993 /*
1994 * packet is too short or too long
1995 */
1996 AR_DEBUG_PRINTF("TOO SHORT or TOO LONG\n");
1997 AR6000_STAT_INC(ar, rx_errors);
1998 AR6000_STAT_INC(ar, rx_length_errors);
1999 A_NETBUF_FREE(skb);
2000 } else {
2001 if (ar->arWmmEnabled) {
2002 wmi_implicit_create_pstream(ar->arWmi, skb,
2003 DNLINK_TRAFFIC, UNDEFINED_PRI);
2004 }
2005 #if 0
2006 /* Access RSSI values here */
2007 AR_DEBUG_PRINTF("RSSI %d\n",
2008 ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi);
2009 #endif
2010 wmi_data_hdr_remove(ar->arWmi, skb);
2011 wmi_dot3_2_dix(ar->arWmi, skb);
2012
2013 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
2014 /*
2015 * extra push and memcpy, for eth_type_trans() of 2.4 kernel
2016 * will pull out hard_header_len bytes of the skb.
2017 */
2018 A_NETBUF_PUSH(skb, sizeof(WMI_DATA_HDR) + sizeof(ATH_LLC_SNAP_HDR) + HTC_HEADER_LEN);
2019 A_MEMCPY(A_NETBUF_DATA(skb), A_NETBUF_DATA(skb) + sizeof(WMI_DATA_HDR) +
2020 sizeof(ATH_LLC_SNAP_HDR) + HTC_HEADER_LEN, sizeof(ATH_MAC_HDR));
2021 #endif
2022 if ((ar->arNetDev->flags & IFF_UP) == IFF_UP)
2023 {
2024 skb->dev = ar->arNetDev;
2025 skb->protocol = eth_type_trans(skb, ar->arNetDev);
2026 netif_rx(skb);
2027 }
2028 else
2029 {
2030 A_NETBUF_FREE(skb);
2031 }
2032 }
2033 }
2034 }
2035 } else {
2036 if ((ar->arNetDev->flags & IFF_UP) == IFF_UP)
2037 {
2038 skb->dev = ar->arNetDev;
2039 skb->protocol = eth_type_trans(skb, ar->arNetDev);
2040 netif_rx(skb);
2041 }
2042 else
2043 {
2044 A_NETBUF_FREE(skb);
2045 }
2046 }
2047
2048 if (status != A_ECANCELED) {
2049 /*
2050 * HTC provides A_ECANCELED status when it doesn't want to be refilled
2051 * (probably due to a shutdown)
2052 */
2053 ar6000_rx_refill(Context, ept);
2054 }
2055
2056
2057 }
2058
2059 static void
2060 ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint)
2061 {
2062 AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
2063 void *osBuf;
2064 int RxBuffers;
2065 int buffersToRefill;
2066 HTC_PACKET *pPacket;
2067 WMI_PRI_STREAM_ID streamId = arEndpoint2WMIStreamID(ar,Endpoint);
2068
2069 buffersToRefill = (int)AR6000_MAX_RX_BUFFERS -
2070 (int)ar->arRxBuffers[streamId];
2071
2072 if (buffersToRefill <= 0) {
2073 /* fast return, nothing to fill */
2074 return;
2075 }
2076
2077 AR_DEBUG2_PRINTF("ar6000_rx_refill: providing htc with %d buffers at eid=%d\n",
2078 buffersToRefill, Endpoint);
2079
2080 for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) {
2081 osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE);
2082 if (NULL == osBuf) {
2083 break;
2084 }
2085 /* the HTC packet wrapper is at the head of the reserved area
2086 * in the skb */
2087 pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf));
2088 /* set re-fill info */
2089 SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint);
2090 /* add this packet */
2091 HTCAddReceivePkt(ar->arHtcTarget, pPacket);
2092 }
2093
2094 /* update count */
2095 AR6000_SPIN_LOCK(&ar->arLock, 0);
2096 ar->arRxBuffers[streamId] += RxBuffers;
2097 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2098 }
2099
2100 static struct net_device_stats *
2101 ar6000_get_stats(struct net_device *dev)
2102 {
2103 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
2104 return &ar->arNetStats;
2105 }
2106
2107 static struct iw_statistics *
2108 ar6000_get_iwstats(struct net_device * dev)
2109 {
2110 AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
2111 TARGET_STATS *pStats = &ar->arTargetStats;
2112 struct iw_statistics * pIwStats = &ar->arIwStats;
2113
2114 if ((ar->arWmiReady == FALSE)
2115 /*
2116 * The in_atomic function is used to determine if the scheduling is
2117 * allowed in the current context or not. This was introduced in 2.6
2118 * From what I have read on the differences between 2.4 and 2.6, the
2119 * 2.4 kernel did not support preemption and so this check might not
2120 * be required for 2.4 kernels.
2121 */
2122 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2123 || (in_atomic())
2124 #endif
2125 )
2126 {
2127 pIwStats->status = 0;
2128 pIwStats->qual.qual = 0;
2129 pIwStats->qual.level =0;
2130 pIwStats->qual.noise = 0;
2131 pIwStats->discard.code =0;
2132 pIwStats->discard.retries=0;
2133 pIwStats->miss.beacon =0;
2134 return pIwStats;
2135 }
2136 if (down_interruptible(&ar->arSem)) {
2137 pIwStats->status = 0;
2138 return pIwStats;
2139 }
2140
2141
2142 ar->statsUpdatePending = TRUE;
2143
2144 if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
2145 up(&ar->arSem);
2146 pIwStats->status = 0;
2147 return pIwStats;
2148 }
2149
2150 wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
2151
2152 if (signal_pending(current)) {
2153 AR_DEBUG_PRINTF("ar6000 : WMI get stats timeout \n");
2154 up(&ar->arSem);
2155 pIwStats->status = 0;
2156 return pIwStats;
2157 }
2158 pIwStats->status = 1 ;
2159 pIwStats->qual.qual = pStats->cs_aveBeacon_rssi;
2160 pIwStats->qual.level =pStats->cs_aveBeacon_rssi + 161; /* noise is -95 dBm */
2161 pIwStats->qual.noise = pStats->noise_floor_calibation;
2162 pIwStats->discard.code = pStats->rx_decrypt_err;
2163 pIwStats->discard.retries = pStats->tx_retry_cnt;
2164 pIwStats->miss.beacon = pStats->cs_bmiss_cnt;
2165 up(&ar->arSem);
2166 return pIwStats;
2167 }
2168
2169 void
2170 ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap)
2171 {
2172 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
2173 struct net_device *dev = ar->arNetDev;
2174
2175 ar->arWmiReady = TRUE;
2176 wake_up(&arEvent);
2177 A_MEMCPY(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN);
2178 AR_DEBUG_PRINTF("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
2179 dev->dev_addr[0], dev->dev_addr[1],
2180 dev->dev_addr[2], dev->dev_addr[3],
2181 dev->dev_addr[4], dev->dev_addr[5]);
2182
2183 ar->arPhyCapability = phyCap;
2184 }
2185
2186 A_UINT8
2187 ar6000_iptos_to_userPriority(A_UINT8 *pkt)
2188 {
2189 struct iphdr *ipHdr = (struct iphdr *)pkt;
2190 A_UINT8 userPriority;
2191
2192 /*
2193 * IP Tos format :
2194 * (Refer Pg 57 WMM-test-plan-v1.2)
2195 * IP-TOS - 8bits
2196 * : DSCP(6-bits) ECN(2-bits)
2197 * : DSCP - P2 P1 P0 X X X
2198 * where (P2 P1 P0) form 802.1D
2199 */
2200 userPriority = ipHdr->tos >> 5;
2201 return (userPriority & 0x7);
2202 }
2203
2204 void
2205 ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid,
2206 A_UINT16 listenInterval, A_UINT16 beaconInterval,
2207 NETWORK_TYPE networkType, A_UINT8 beaconIeLen,
2208 A_UINT8 assocReqLen, A_UINT8 assocRespLen,
2209 A_UINT8 *assocInfo)
2210 {
2211 union iwreq_data wrqu;
2212 int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos;
2213 static const char *tag1 = "ASSOCINFO(ReqIEs=";
2214 static const char *tag2 = "ASSOCRESPIE=";
2215 static const char *beaconIetag = "BEACONIE=";
2216 char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + sizeof(tag1)];
2217 char *pos;
2218 A_UINT8 key_op_ctrl;
2219
2220 A_MEMCPY(ar->arBssid, bssid, sizeof(ar->arBssid));
2221 ar->arBssChannel = channel;
2222
2223 A_PRINTF("AR6000 connected event on freq %d ", channel);
2224 A_PRINTF("with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
2225 " listenInterval=%d, beaconInterval = %d, beaconIeLen = %d assocReqLen=%d"
2226 " assocRespLen =%d\n",
2227 bssid[0], bssid[1], bssid[2],
2228 bssid[3], bssid[4], bssid[5],
2229 listenInterval, beaconInterval,
2230 beaconIeLen, assocReqLen, assocRespLen);
2231 if (networkType & ADHOC_NETWORK) {
2232 if (networkType & ADHOC_CREATOR) {
2233 A_PRINTF("Network: Adhoc (Creator)\n");
2234 } else {
2235 A_PRINTF("Network: Adhoc (Joiner)\n");
2236 }
2237 } else {
2238 A_PRINTF("Network: Infrastructure\n");
2239 }
2240
2241 if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) {
2242 AR_DEBUG_PRINTF("\nBeaconIEs= ");
2243
2244 beacon_ie_pos = 0;
2245 A_MEMZERO(buf, sizeof(buf));
2246 sprintf(buf, "%s", beaconIetag);
2247 pos = buf + 9;
2248 for (i = beacon_ie_pos; i < beacon_ie_pos + beaconIeLen; i++) {
2249 AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
2250 sprintf(pos, "%2.2x", assocInfo[i]);
2251 pos += 2;
2252 }
2253 AR_DEBUG_PRINTF("\n");
2254
2255 A_MEMZERO(&wrqu, sizeof(wrqu));
2256 wrqu.data.length = strlen(buf);
2257 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2258 }
2259
2260 if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2))))
2261 {
2262 assoc_resp_ie_pos = beaconIeLen + assocReqLen +
2263 sizeof(A_UINT16) + /* capinfo*/
2264 sizeof(A_UINT16) + /* status Code */
2265 sizeof(A_UINT16) ; /* associd */
2266 A_MEMZERO(buf, sizeof(buf));
2267 sprintf(buf, "%s", tag2);
2268 pos = buf + 12;
2269 AR_DEBUG_PRINTF("\nAssocRespIEs= ");
2270 /*
2271 * The Association Response Frame w.o. the WLAN header is delivered to
2272 * the host, so skip over to the IEs
2273 */
2274 for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i++)
2275 {
2276 AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
2277 sprintf(pos, "%2.2x", assocInfo[i]);
2278 pos += 2;
2279 }
2280 AR_DEBUG_PRINTF("\n");
2281
2282 A_MEMZERO(&wrqu, sizeof(wrqu));
2283 wrqu.data.length = strlen(buf);
2284 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2285 }
2286
2287 if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) {
2288 /*
2289 * assoc Request includes capability and listen interval. Skip these.
2290 */
2291 assoc_req_ie_pos = beaconIeLen +
2292 sizeof(A_UINT16) + /* capinfo*/
2293 sizeof(A_UINT16); /* listen interval */
2294
2295 A_MEMZERO(buf, sizeof(buf));
2296 sprintf(buf, "%s", tag1);
2297 pos = buf + 17;
2298 AR_DEBUG_PRINTF("AssocReqIEs= ");
2299 for (i = assoc_req_ie_pos; i < assoc_req_ie_pos + assocReqLen - 4; i++) {
2300 AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
2301 sprintf(pos, "%2.2x", assocInfo[i]);
2302 pos += 2;;
2303 }
2304 AR_DEBUG_PRINTF("\n");
2305
2306 A_MEMZERO(&wrqu, sizeof(wrqu));
2307 wrqu.data.length = strlen(buf);
2308 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2309 }
2310
2311 #ifdef USER_KEYS
2312 if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN &&
2313 ar->user_saved_keys.keyOk == TRUE)
2314 {
2315
2316 key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC;
2317 if (ar->user_key_ctrl & AR6000_USER_SETKEYS_RSC_UNCHANGED) {
2318 key_op_ctrl &= ~KEY_OP_INIT_RSC;
2319 } else {
2320 key_op_ctrl |= KEY_OP_INIT_RSC;
2321 }
2322 ar6000_reinstall_keys(ar, key_op_ctrl);
2323 }
2324 #endif /* USER_KEYS */
2325
2326 /* flush data queues */
2327 ar6000_TxDataCleanup(ar);
2328
2329 netif_start_queue(ar->arNetDev);
2330
2331 if ((OPEN_AUTH == ar->arDot11AuthMode) &&
2332 (NONE_AUTH == ar->arAuthMode) &&
2333 (WEP_CRYPT == ar->arPairwiseCrypto))
2334 {
2335 if (!ar->arConnected) {
2336 ar6000_install_static_wep_keys(ar);
2337 }
2338 }
2339
2340 ar->arConnected = TRUE;
2341 ar->arConnectPending = FALSE;
2342
2343 reconnect_flag = 0;
2344
2345 A_MEMZERO(&wrqu, sizeof(wrqu));
2346 A_MEMCPY(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN);
2347 wrqu.addr.sa_family = ARPHRD_ETHER;
2348 wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL);
2349 if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) {
2350 A_MEMZERO(ar->arNodeMap, sizeof(ar->arNodeMap));
2351 ar->arNodeNum = 0;
2352 ar->arNexEpId = ENDPOINT_2;
2353 }
2354
2355 }
2356
2357 void ar6000_set_numdataendpts(AR_SOFTC_T *ar, A_UINT32 num)
2358 {
2359 A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1));
2360 ar->arNumDataEndPts = num;
2361 }
2362
2363 void
2364 ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
2365 A_UINT8 assocRespLen, A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus)
2366 {
2367 A_UINT8 i;
2368
2369 A_PRINTF("AR6000 disconnected");
2370 if (bssid[0] || bssid[1] || bssid[2] || bssid[3] || bssid[4] || bssid[5]) {
2371 A_PRINTF(" from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",
2372 bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
2373 }
2374 A_PRINTF("\n");
2375
2376 AR_DEBUG_PRINTF("\nDisconnect Reason is %d", reason);
2377 AR_DEBUG_PRINTF("\nProtocol Reason/Status Code is %d", protocolReasonStatus);
2378 AR_DEBUG_PRINTF("\nAssocResp Frame = %s",
2379 assocRespLen ? " " : "NULL");
2380 for (i = 0; i < assocRespLen; i++) {
2381 if (!(i % 0x10)) {
2382 AR_DEBUG_PRINTF("\n");
2383 }
2384 AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
2385 }
2386 AR_DEBUG_PRINTF("\n");
2387 /*
2388 * If the event is due to disconnect cmd from the host, only they the target
2389 * would stop trying to connect. Under any other condition, target would
2390 * keep trying to connect.
2391 *
2392 */
2393 if( reason == DISCONNECT_CMD)
2394 {
2395 ar->arConnectPending = FALSE;
2396 } else {
2397 ar->arConnectPending = TRUE;
2398 if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) ||
2399 ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) {
2400 ar->arConnected = TRUE;
2401 return;
2402 }
2403 }
2404 ar->arConnected = FALSE;
2405
2406 if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) {
2407 reconnect_flag = 0;
2408 }
2409
2410 #ifdef USER_KEYS
2411 if (reason != CSERV_DISCONNECT)
2412 {
2413 ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
2414 ar->user_key_ctrl = 0;
2415 }
2416 #endif /* USER_KEYS */
2417
2418 netif_stop_queue(ar->arNetDev);
2419 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2420 ar->arBssChannel = 0;
2421 ar->arBeaconInterval = 0;
2422
2423 ar6000_TxDataCleanup(ar);
2424 }
2425
2426 void
2427 ar6000_regDomain_event(AR_SOFTC_T *ar, A_UINT32 regCode)
2428 {
2429 A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode);
2430 ar->arRegCode = regCode;
2431 }
2432
2433 void
2434 ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info)
2435 {
2436 static const char *tag = "PRE-AUTH";
2437 char buf[128];
2438 union iwreq_data wrqu;
2439 int i;
2440
2441 AR_DEBUG_PRINTF("AR6000 Neighbor Report Event\n");
2442 for (i=0; i < numAps; info++, i++) {
2443 AR_DEBUG_PRINTF("bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",
2444 info->bssid[0], info->bssid[1], info->bssid[2],
2445 info->bssid[3], info->bssid[4], info->bssid[5]);
2446 if (info->bssFlags & WMI_PREAUTH_CAPABLE_BSS) {
2447 AR_DEBUG_PRINTF("preauth-cap");
2448 }
2449 if (info->bssFlags & WMI_PMKID_VALID_BSS) {
2450 AR_DEBUG_PRINTF(" pmkid-valid\n");
2451 continue; /* we skip bss if the pmkid is already valid */
2452 }
2453 AR_DEBUG_PRINTF("\n");
2454 snprintf(buf, sizeof(buf), "%s%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
2455 tag,
2456 info->bssid[0], info->bssid[1], info->bssid[2],
2457 info->bssid[3], info->bssid[4], info->bssid[5],
2458 i, info->bssFlags);
2459 A_MEMZERO(&wrqu, sizeof(wrqu));
2460 wrqu.data.length = strlen(buf);
2461 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2462 }
2463 }
2464
2465 void
2466 ar6000_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
2467 {
2468 static const char *tag = "MLME-MICHAELMICFAILURE.indication";
2469 char buf[128];
2470 union iwreq_data wrqu;
2471
2472 A_PRINTF("AR6000 TKIP MIC error received for keyid %d %scast\n",
2473 keyid, ismcast ? "multi": "uni");
2474 snprintf(buf, sizeof(buf), "%s(keyid=%d %scat)", tag, keyid,
2475 ismcast ? "multi" : "uni");
2476 memset(&wrqu, 0, sizeof(wrqu));
2477 wrqu.data.length = strlen(buf);
2478 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
2479 }
2480
2481 void
2482 ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
2483 {
2484 AR_DEBUG_PRINTF("AR6000 scan complete: %d\n", status);
2485
2486 ar->scan_complete = 1;
2487 wake_up_interruptible(&ar6000_scan_queue);
2488 }
2489
2490 void
2491 ar6000_targetStats_event(AR_SOFTC_T *ar, WMI_TARGET_STATS *pTarget)
2492 {
2493 TARGET_STATS *pStats = &ar->arTargetStats;
2494 A_UINT8 ac;
2495
2496 /*A_PRINTF("AR6000 updating target stats\n");*/
2497 pStats->tx_packets += pTarget->txrxStats.tx_stats.tx_packets;
2498 pStats->tx_bytes += pTarget->txrxStats.tx_stats.tx_bytes;
2499 pStats->tx_unicast_pkts += pTarget->txrxStats.tx_stats.tx_unicast_pkts;
2500 pStats->tx_unicast_bytes += pTarget->txrxStats.tx_stats.tx_unicast_bytes;
2501 pStats->tx_multicast_pkts += pTarget->txrxStats.tx_stats.tx_multicast_pkts;
2502 pStats->tx_multicast_bytes += pTarget->txrxStats.tx_stats.tx_multicast_bytes;
2503 pStats->tx_broadcast_pkts += pTarget->txrxStats.tx_stats.tx_broadcast_pkts;
2504 pStats->tx_broadcast_bytes += pTarget->txrxStats.tx_stats.tx_broadcast_bytes;
2505 pStats->tx_rts_success_cnt += pTarget->txrxStats.tx_stats.tx_rts_success_cnt;
2506 for(ac = 0; ac < WMM_NUM_AC; ac++)
2507 pStats->tx_packet_per_ac[ac] += pTarget->txrxStats.tx_stats.tx_packet_per_ac[ac];
2508 pStats->tx_errors += pTarget->txrxStats.tx_stats.tx_errors;
2509 pStats->tx_failed_cnt += pTarget->txrxStats.tx_stats.tx_failed_cnt;
2510 pStats->tx_retry_cnt += pTarget->txrxStats.tx_stats.tx_retry_cnt;
2511 pStats->tx_rts_fail_cnt += pTarget->txrxStats.tx_stats.tx_rts_fail_cnt;
2512 pStats->tx_unicast_rate = wmi_get_rate(pTarget->txrxStats.tx_stats.tx_unicast_rate);
2513
2514 pStats->rx_packets += pTarget->txrxStats.rx_stats.rx_packets;
2515 pStats->rx_bytes += pTarget->txrxStats.rx_stats.rx_bytes;
2516 pStats->rx_unicast_pkts += pTarget->txrxStats.rx_stats.rx_unicast_pkts;
2517 pStats->rx_unicast_bytes += pTarget->txrxStats.rx_stats.rx_unicast_bytes;
2518 pStats->rx_multicast_pkts += pTarget->txrxStats.rx_stats.rx_multicast_pkts;
2519 pStats->rx_multicast_bytes += pTarget->txrxStats.rx_stats.rx_multicast_bytes;
2520 pStats->rx_broadcast_pkts += pTarget->txrxStats.rx_stats.rx_broadcast_pkts;
2521 pStats->rx_broadcast_bytes += pTarget->txrxStats.rx_stats.rx_broadcast_bytes;
2522 pStats->rx_fragment_pkt += pTarget->txrxStats.rx_stats.rx_fragment_pkt;
2523 pStats->rx_errors += pTarget->txrxStats.rx_stats.rx_errors;
2524 pStats->rx_crcerr += pTarget->txrxStats.rx_stats.rx_crcerr;
2525 pStats->rx_key_cache_miss += pTarget->txrxStats.rx_stats.rx_key_cache_miss;
2526 pStats->rx_decrypt_err += pTarget->txrxStats.rx_stats.rx_decrypt_err;
2527 pStats->rx_duplicate_frames += pTarget->txrxStats.rx_stats.rx_duplicate_frames;
2528 pStats->rx_unicast_rate = wmi_get_rate(pTarget->txrxStats.rx_stats.rx_unicast_rate);
2529
2530
2531 pStats->tkip_local_mic_failure
2532 += pTarget->txrxStats.tkipCcmpStats.tkip_local_mic_failure;
2533 pStats->tkip_counter_measures_invoked
2534 += pTarget->txrxStats.tkipCcmpStats.tkip_counter_measures_invoked;
2535 pStats->tkip_replays += pTarget->txrxStats.tkipCcmpStats.tkip_replays;
2536 pStats->tkip_format_errors += pTarget->txrxStats.tkipCcmpStats.tkip_format_errors;
2537 pStats->ccmp_format_errors += pTarget->txrxStats.tkipCcmpStats.ccmp_format_errors;
2538 pStats->ccmp_replays += pTarget->txrxStats.tkipCcmpStats.ccmp_replays;
2539
2540
2541 pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cnt;
2542 pStats->noise_floor_calibation = pTarget->noise_floor_calibation;
2543
2544 pStats->cs_bmiss_cnt += pTarget->cservStats.cs_bmiss_cnt;
2545 pStats->cs_lowRssi_cnt += pTarget->cservStats.cs_lowRssi_cnt;
2546 pStats->cs_connect_cnt += pTarget->cservStats.cs_connect_cnt;
2547 pStats->cs_disconnect_cnt += pTarget->cservStats.cs_disconnect_cnt;
2548 pStats->cs_aveBeacon_snr = pTarget->cservStats.cs_aveBeacon_snr;
2549 pStats->cs_aveBeacon_rssi = pTarget->cservStats.cs_aveBeacon_rssi;
2550 pStats->cs_lastRoam_msec = pTarget->cservStats.cs_lastRoam_msec;
2551 pStats->cs_snr = pTarget->cservStats.cs_snr;
2552 pStats->cs_rssi = pTarget->cservStats.cs_rssi;
2553
2554 pStats->lq_val = pTarget->lqVal;
2555
2556 pStats->wow_num_pkts_dropped += pTarget->wowStats.wow_num_pkts_dropped;
2557 pStats->wow_num_host_pkt_wakeups += pTarget->wowStats.wow_num_host_pkt_wakeups;
2558 pStats->wow_num_host_event_wakeups += pTarget->wowStats.wow_num_host_event_wakeups;
2559 pStats->wow_num_events_discarded += pTarget->wowStats.wow_num_events_discarded;
2560
2561 ar->statsUpdatePending = FALSE;
2562 wake_up(&arEvent);
2563 }
2564
2565 void
2566 ar6000_rssiThreshold_event(AR_SOFTC_T *ar, WMI_RSSI_THRESHOLD_VAL newThreshold, A_INT16 rssi)
2567 {
2568 USER_RSSI_THOLD userRssiThold;
2569
2570 userRssiThold.tag = rssi_map[newThreshold].tag;
2571 userRssiThold.rssi = rssi;
2572 AR_DEBUG2_PRINTF("rssi Threshold range = %d tag = %d rssi = %d\n", newThreshold, userRssiThold.tag, rssi);
2573 #ifdef SEND_EVENT_TO_APP
2574 ar6000_send_event_to_app(ar, WMI_RSSI_THRESHOLD_EVENTID,(A_UINT8 *)&userRssiThold, sizeof(USER_RSSI_THOLD));
2575 #endif
2576 }
2577
2578
2579 void
2580 ar6000_hbChallengeResp_event(AR_SOFTC_T *ar, A_UINT32 cookie, A_UINT32 source)
2581 {
2582 if (source == APP_HB_CHALLENGE) {
2583 /* Report it to the app in case it wants a positive acknowledgement */
2584 #ifdef SEND_EVENT_TO_APP
2585 ar6000_send_event_to_app(ar, WMIX_HB_CHALLENGE_RESP_EVENTID,
2586 (A_UINT8 *)&cookie, sizeof(cookie));
2587 #endif
2588 } else {
2589 /* This would ignore the replys that come in after their due time */
2590 if (cookie == ar->arHBChallengeResp.seqNum) {
2591 ar->arHBChallengeResp.outstanding = FALSE;
2592 }
2593 }
2594 }
2595
2596
2597 void
2598 ar6000_reportError_event(AR_SOFTC_T *ar, WMI_TARGET_ERROR_VAL errorVal)
2599 {
2600 char *errString[] = {
2601 [WMI_TARGET_PM_ERR_FAIL] "WMI_TARGET_PM_ERR_FAIL",
2602 [WMI_TARGET_KEY_NOT_FOUND] "WMI_TARGET_KEY_NOT_FOUND",
2603 [WMI_TARGET_DECRYPTION_ERR] "WMI_TARGET_DECRYPTION_ERR",
2604 [WMI_TARGET_BMISS] "WMI_TARGET_BMISS",
2605 [WMI_PSDISABLE_NODE_JOIN] "WMI_PSDISABLE_NODE_JOIN"
2606 };
2607
2608 A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal);
2609
2610 /* One error is reported at a time, and errorval is a bitmask */
2611 if(errorVal & (errorVal - 1))
2612 return;
2613
2614 A_PRINTF("AR6000 Error type = ");
2615 switch(errorVal)
2616 {
2617 case WMI_TARGET_PM_ERR_FAIL:
2618 case WMI_TARGET_KEY_NOT_FOUND:
2619 case WMI_TARGET_DECRYPTION_ERR:
2620 case WMI_TARGET_BMISS:
2621 case WMI_PSDISABLE_NODE_JOIN:
2622 A_PRINTF("%s\n", errString[errorVal]);
2623 break;
2624 default:
2625 A_PRINTF("INVALID\n");
2626 break;
2627 }
2628
2629 }
2630
2631
2632 void
2633 ar6000_cac_event(AR_SOFTC_T *ar, A_UINT8 ac, A_UINT8 cacIndication,
2634 A_UINT8 statusCode, A_UINT8 *tspecSuggestion)
2635 {
2636 WMM_TSPEC_IE *tspecIe;
2637
2638 /*
2639 * This is the TSPEC IE suggestion from AP.
2640 * Suggestion provided by AP under some error
2641 * cases, could be helpful for the host app.
2642 * Check documentation.
2643 */
2644 tspecIe = (WMM_TSPEC_IE *)tspecSuggestion;
2645
2646 /*
2647 * What do we do, if we get TSPEC rejection? One thought
2648 * that comes to mind is implictly delete the pstream...
2649 */
2650 A_PRINTF("AR6000 CAC notification. "
2651 "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n",
2652 ac, cacIndication, statusCode);
2653 }
2654
2655 #define AR6000_PRINT_BSSID(_pBss) do { \
2656 A_PRINTF("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",\
2657 (_pBss)[0],(_pBss)[1],(_pBss)[2],(_pBss)[3],\
2658 (_pBss)[4],(_pBss)[5]); \
2659 } while(0)
2660
2661 void
2662 ar6000_roam_tbl_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_TBL *pTbl)
2663 {
2664 A_UINT8 i;
2665
2666 A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n",
2667 pTbl->numEntries, pTbl->roamMode);
2668 for (i= 0; i < pTbl->numEntries; i++) {
2669 A_PRINTF("[%d]bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", i,
2670 pTbl->bssRoamInfo[i].bssid[0], pTbl->bssRoamInfo[i].bssid[1],
2671 pTbl->bssRoamInfo[i].bssid[2],
2672 pTbl->bssRoamInfo[i].bssid[3],
2673 pTbl->bssRoamInfo[i].bssid[4],
2674 pTbl->bssRoamInfo[i].bssid[5]);
2675 A_PRINTF("RSSI %d RSSIDT %d LAST RSSI %d UTIL %d ROAM_UTIL %d"
2676 " BIAS %d\n",
2677 pTbl->bssRoamInfo[i].rssi,
2678 pTbl->bssRoamInfo[i].rssidt,
2679 pTbl->bssRoamInfo[i].last_rssi,
2680 pTbl->bssRoamInfo[i].util,
2681 pTbl->bssRoamInfo[i].roam_util,
2682 pTbl->bssRoamInfo[i].bias);
2683 }
2684 }
2685
2686 void
2687 ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply)
2688 {
2689 A_UINT8 i,j;
2690
2691 /*Each event now contains exactly one filter, see bug 26613*/
2692 A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num, wow_reply->num_filters);
2693 A_PRINTF("wow mode = %s host mode = %s\n",
2694 (wow_reply->wow_mode == 0? "disabled":"enabled"),
2695 (wow_reply->host_mode == 1 ? "awake":"asleep"));
2696
2697
2698 /*If there are no patterns, the reply will only contain generic
2699 WoW information. Pattern information will exist only if there are
2700 patterns present. Bug 26716*/
2701
2702 /* If this event contains pattern information, display it*/
2703 if (wow_reply->this_filter_num) {
2704 i=0;
2705 A_PRINTF("id=%d size=%d offset=%d\n",
2706 wow_reply->wow_filters[i].wow_filter_id,
2707 wow_reply->wow_filters[i].wow_filter_size,
2708 wow_reply->wow_filters[i].wow_filter_offset);
2709 A_PRINTF("wow pattern = ");
2710 for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) {
2711 A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_pattern[j]);
2712 }
2713
2714 A_PRINTF("\nwow mask = ");
2715 for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) {
2716 A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_mask[j]);
2717 }
2718 A_PRINTF("\n");
2719 }
2720 }
2721
2722 /*
2723 * Report the Roaming related data collected on the target
2724 */
2725 void
2726 ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p)
2727 {
2728 A_PRINTF("Disconnect Data : BSSID: ");
2729 AR6000_PRINT_BSSID(p->disassoc_bssid);
2730 A_PRINTF(" RSSI %d DISASSOC Time %d NO_TXRX_TIME %d\n",
2731 p->disassoc_bss_rssi,p->disassoc_time,
2732 p->no_txrx_time);
2733 A_PRINTF("Connect Data: BSSID: ");
2734 AR6000_PRINT_BSSID(p->assoc_bssid);
2735 A_PRINTF(" RSSI %d ASSOC Time %d TXRX_TIME %d\n",
2736 p->assoc_bss_rssi,p->assoc_time,
2737 p->allow_txrx_time);
2738 A_PRINTF("Last Data Tx Time (b4 Disassoc) %d "\
2739 "First Data Tx Time (after Assoc) %d\n",
2740 p->last_data_txrx_time, p->first_data_txrx_time);
2741 }
2742
2743 void
2744 ar6000_roam_data_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_DATA *p)
2745 {
2746 switch (p->roamDataType) {
2747 case ROAM_DATA_TIME:
2748 ar6000_display_roam_time(&p->u.roamTime);
2749 break;
2750 default:
2751 break;
2752 }
2753 }
2754
2755 void
2756 ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len)
2757 {
2758 struct sk_buff *skb;
2759 WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap;
2760
2761
2762 if (!ar->arMgmtFilter) {
2763 return;
2764 }
2765 if (((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_BEACON) &&
2766 (bih->frameType != BEACON_FTYPE)) ||
2767 ((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_PROBE_RESP) &&
2768 (bih->frameType != PROBERESP_FTYPE)))
2769 {
2770 return;
2771 }
2772
2773 if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) {
2774
2775 A_NETBUF_PUT(skb, len);
2776 A_MEMCPY(A_NETBUF_DATA(skb), datap, len);
2777 skb->dev = ar->arNetDev;
2778 printk("MAC RAW...\n");
2779 // skb->mac.raw = A_NETBUF_DATA(skb);
2780 skb->ip_summed = CHECKSUM_NONE;
2781 skb->pkt_type = PACKET_OTHERHOST;
2782 skb->protocol = __constant_htons(0x0019);
2783 netif_rx(skb);
2784 }
2785 }
2786
2787 A_UINT32 wmiSendCmdNum;