staging: wilc1000: remove WILC_Uint8
[firefly-linux-kernel-4.4.55.git] / drivers / staging / wilc1000 / wilc_wlan.c
1 /* ////////////////////////////////////////////////////////////////////////// */
2 /*  */
3 /* Copyright (c) Atmel Corporation.  All rights reserved. */
4 /*  */
5 /* Module Name:  wilc_wlan.c */
6 /*  */
7 /*  */
8 /* //////////////////////////////////////////////////////////////////////////// */
9
10 #include "wilc_wlan_if.h"
11 #include "wilc_wlan.h"
12 #define INLINE static __inline
13
14 /********************************************
15  *
16  *      Global
17  *
18  ********************************************/
19 extern unsigned int int_clrd;
20 extern wilc_hif_func_t hif_sdio;
21 extern wilc_hif_func_t hif_spi;
22 extern wilc_cfg_func_t mac_cfg;
23 #if defined(PLAT_RK3026_TCHIP)
24 extern u8 g_wilc_initialized; /* AMR : 0422 RK3026 Crash issue */
25 #endif
26 extern void WILC_WFI_mgmt_rx(uint8_t *buff, uint32_t size);
27 extern void frmw_to_linux(uint8_t *buff, uint32_t size);
28 int sdio_xfer_cnt(void);
29 uint32_t wilc_get_chipid(uint8_t update);
30 WILC_Uint16 Set_machw_change_vir_if(WILC_Bool bValue);
31
32 /* static uint32_t vmm_table[WILC_VMM_TBL_SIZE]; */
33 /* static uint32_t vmm_table_rbk[WILC_VMM_TBL_SIZE]; */
34
35 /* static uint32_t vmm_table_rbk[WILC_VMM_TBL_SIZE]; */
36
37
38 typedef struct {
39         int quit;
40
41         /**
42          *      input interface functions
43          **/
44         wilc_wlan_os_func_t os_func;
45         wilc_wlan_io_func_t io_func;
46         wilc_wlan_net_func_t net_func;
47         wilc_wlan_indicate_func_t indicate_func;
48
49         /**
50          *      host interface functions
51          **/
52         wilc_hif_func_t hif_func;
53         void *hif_lock;
54
55         /**
56          *      configuration interface functions
57          **/
58         wilc_cfg_func_t cif_func;
59         int cfg_frame_in_use;
60         wilc_cfg_frame_t cfg_frame;
61         uint32_t cfg_frame_offset;
62         int cfg_seq_no;
63         void *cfg_wait;
64
65         /**
66          *      RX buffer
67          **/
68         #ifdef MEMORY_STATIC
69         uint32_t rx_buffer_size;
70         uint8_t *rx_buffer;
71         uint32_t rx_buffer_offset;
72         #endif
73         /**
74          *      TX buffer
75          **/
76         uint32_t tx_buffer_size;
77         uint8_t *tx_buffer;
78         uint32_t tx_buffer_offset;
79
80         /**
81          *      TX queue
82          **/
83         void *txq_lock;
84
85         /*Added by Amr - BugID_4720*/
86         void *txq_add_to_head_lock;
87         void *txq_spinlock;
88         unsigned long txq_spinlock_flags;
89
90         struct txq_entry_t *txq_head;
91         struct txq_entry_t *txq_tail;
92         int txq_entries;
93         void *txq_wait;
94         int txq_exit;
95
96         /**
97          *      RX queue
98          **/
99         void *rxq_lock;
100         struct rxq_entry_t *rxq_head;
101         struct rxq_entry_t *rxq_tail;
102         int rxq_entries;
103         void *rxq_wait;
104         int rxq_exit;
105
106
107 } wilc_wlan_dev_t;
108
109 static wilc_wlan_dev_t g_wlan;
110
111 INLINE void chip_allow_sleep(void);
112 INLINE void chip_wakeup(void);
113 /********************************************
114  *
115  *      Debug
116  *
117  ********************************************/
118
119 static uint32_t dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ;
120
121 static void wilc_debug(uint32_t flag, char *fmt, ...)
122 {
123         char buf[256];
124         va_list args;
125         int len;
126
127         if (flag & dbgflag) {
128                 va_start(args, fmt);
129                 len = vsprintf(buf, fmt, args);
130                 va_end(args);
131
132                 if (g_wlan.os_func.os_debug)
133                         g_wlan.os_func.os_debug(buf);
134         }
135
136         return;
137 }
138
139 static CHIP_PS_STATE_T genuChipPSstate = CHIP_WAKEDUP;
140
141 /*BugID_5213*/
142 /*acquire_bus() and release_bus() are made INLINE functions*/
143 /*as a temporary workaround to fix a problem of receiving*/
144 /*unknown interrupt from FW*/
145 INLINE void acquire_bus(BUS_ACQUIRE_T acquire)
146 {
147
148         g_wlan.os_func.os_enter_cs(g_wlan.hif_lock);
149         #ifndef WILC_OPTIMIZE_SLEEP_INT
150         if (genuChipPSstate != CHIP_WAKEDUP)
151         #endif
152         {
153                 if (acquire == ACQUIRE_AND_WAKEUP)
154                         chip_wakeup();
155         }
156
157 }
158 INLINE void release_bus(BUS_RELEASE_T release)
159 {
160         #ifdef WILC_OPTIMIZE_SLEEP_INT
161         if (release == RELEASE_ALLOW_SLEEP)
162                 chip_allow_sleep();
163         #endif
164         g_wlan.os_func.os_leave_cs(g_wlan.hif_lock);
165 }
166 /********************************************
167  *
168  *      Queue
169  *
170  ********************************************/
171
172 static void wilc_wlan_txq_remove(struct txq_entry_t *tqe)
173 {
174
175         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
176         /* unsigned long flags; */
177         /* p->os_func.os_spin_lock(p->txq_spinlock, &flags); */
178         if (tqe == p->txq_head) {
179
180                 p->txq_head = tqe->next;
181                 if (p->txq_head)
182                         p->txq_head->prev = NULL;
183
184
185         } else if (tqe == p->txq_tail)      {
186                 p->txq_tail = (tqe->prev);
187                 if (p->txq_tail)
188                         p->txq_tail->next = NULL;
189         } else {
190                 tqe->prev->next = tqe->next;
191                 tqe->next->prev = tqe->prev;
192         }
193         p->txq_entries -= 1;
194         /* p->os_func.os_spin_unlock(p->txq_spinlock, &flags); */
195
196 }
197
198 static struct txq_entry_t *wilc_wlan_txq_remove_from_head(void)
199 {
200         struct txq_entry_t *tqe;
201         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
202         unsigned long flags;
203         p->os_func.os_spin_lock(p->txq_spinlock, &flags);
204         if (p->txq_head) {
205                 /* p->os_func.os_enter_cs(p->txq_lock); */
206                 tqe = p->txq_head;
207                 p->txq_head = tqe->next;
208                 if (p->txq_head) {
209                         p->txq_head->prev = NULL;
210                 }
211                 p->txq_entries -= 1;
212
213                 /*Added by Amr - BugID_4720*/
214
215
216                 /* p->os_func.os_leave_cs(p->txq_lock); */
217
218         } else {
219                 tqe = NULL;
220         }
221         p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
222         return tqe;
223 }
224
225 static void wilc_wlan_txq_add_to_tail(struct txq_entry_t *tqe)
226 {
227         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
228         unsigned long flags;
229         /*Added by Amr - BugID_4720*/
230         p->os_func.os_spin_lock(p->txq_spinlock, &flags);
231
232 /*      p->os_func.os_enter_cs(p->txq_lock); */
233         if (p->txq_head == NULL) {
234                 tqe->next = NULL;
235                 tqe->prev = NULL;
236                 p->txq_head = tqe;
237                 p->txq_tail = tqe;
238                 /* p->os_func.os_signal(p->txq_wait); */
239         } else {
240                 tqe->next = NULL;
241                 tqe->prev = p->txq_tail;
242                 p->txq_tail->next = tqe;
243                 p->txq_tail = tqe;
244         }
245         p->txq_entries += 1;
246         PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries);
247 /*      p->os_func.os_leave_cs(p->txq_lock); */
248
249         /*Added by Amr - BugID_4720*/
250         p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
251
252         /**
253          *      wake up TX queue
254          **/
255         PRINT_D(TX_DBG, "Wake the txq_handling\n");
256
257         p->os_func.os_signal(p->txq_wait);
258
259
260 }
261
262 static int wilc_wlan_txq_add_to_head(struct txq_entry_t *tqe)
263 {
264         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
265         unsigned long flags;
266         /*Added by Amr - BugID_4720*/
267         if (p->os_func.os_wait(p->txq_add_to_head_lock, CFG_PKTS_TIMEOUT))
268                 return -1;
269
270         p->os_func.os_spin_lock(p->txq_spinlock, &flags);
271
272         /* p->os_func.os_enter_cs(p->txq_lock); */
273         if (p->txq_head == NULL) {
274                 tqe->next = NULL;
275                 tqe->prev = NULL;
276                 p->txq_head = tqe;
277                 p->txq_tail = tqe;
278         } else {
279                 tqe->next = p->txq_head;
280                 tqe->prev = NULL;
281                 p->txq_head->prev = tqe;
282                 p->txq_head = tqe;
283         }
284         p->txq_entries += 1;
285         PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", p->txq_entries);
286         /* p->os_func.os_leave_cs(p->txq_lock); */
287
288         /*Added by Amr - BugID_4720*/
289         p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
290         p->os_func.os_signal(p->txq_add_to_head_lock);
291
292
293         /**
294          *      wake up TX queue
295          **/
296         p->os_func.os_signal(p->txq_wait);
297         PRINT_D(TX_DBG, "Wake up the txq_handler\n");
298 /*      complete(p->txq_wait); */
299
300         /*Added by Amr - BugID_4720*/
301         return 0;
302
303 }
304
305 uint32_t Statisitcs_totalAcks = 0, Statisitcs_DroppedAcks = 0;
306
307 #ifdef  TCP_ACK_FILTER
308 struct Ack_session_info;
309 typedef struct Ack_session_info {
310         uint32_t Ack_seq_num;
311         uint32_t Bigger_Ack_num;
312         uint16_t src_port;
313         uint16_t dst_port;
314         uint16_t status;
315         /* struct Ack_session_info * next; */
316         /* struct Ack_session_info * prev; */
317 } Ack_session_info_t;
318
319 typedef struct {
320         uint32_t ack_num;
321         /* uint32_t seq_num; */
322         /* uint16_t src_port; */
323         /* uint16_t dst_port; */
324         /* uint32_t dst_ip_addr; */
325         uint32_t Session_index;
326         struct txq_entry_t  *txqe;
327         /* Ack_session_info * Ack_session; */
328 } Pending_Acks_info_t /*Ack_info_t*/;
329
330
331
332
333 struct Ack_session_info *Free_head;
334 struct Ack_session_info *Alloc_head;
335
336 #define TCP_FIN_MASK            (1 << 0)
337 #define TCP_SYN_MASK            (1 << 1)
338 #define TCP_Ack_MASK            (1 << 4)
339 #define NOT_TCP_ACK                     (-1)
340
341 #define MAX_TCP_SESSION         25
342 #define MAX_PENDING_ACKS                256
343 Ack_session_info_t Acks_keep_track_info[2 * MAX_TCP_SESSION];
344 Pending_Acks_info_t Pending_Acks_info[MAX_PENDING_ACKS];
345
346 uint32_t PendingAcks_arrBase;
347 uint32_t Opened_TCP_session;
348 uint32_t Pending_Acks;
349
350
351
352 static __inline int Init_TCP_tracking(void)
353 {
354
355         /*uint32_t i;
356          * Free_head=&Acks_keep_track_info[0];
357          * i=1;
358          * Acks_keep_track_info[0].next=&Acks_keep_track_info[1];
359          * for(i=1<;i<MAX_TCP_SESSION-1;i++)
360          * {
361          *      Acks_keep_track_info[i].next=&Acks_keep_track_info[i+1];
362          *      Acks_keep_track_info[i].prev=&Acks_keep_track_info[i-1];
363          * }
364          * Acks_keep_track_info[49].prev=&Acks_keep_track_info[48];
365          */
366         return 0;
367
368 }
369 static __inline int add_TCP_track_session(uint32_t src_prt, uint32_t dst_prt, uint32_t seq)
370 {
371         Acks_keep_track_info[Opened_TCP_session].Ack_seq_num = seq;
372         Acks_keep_track_info[Opened_TCP_session].Bigger_Ack_num = 0;
373         Acks_keep_track_info[Opened_TCP_session].src_port = src_prt;
374         Acks_keep_track_info[Opened_TCP_session].dst_port = dst_prt;
375         Opened_TCP_session++;
376
377         PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", Opened_TCP_session, seq);
378         return 0;
379 }
380
381 static __inline int Update_TCP_track_session(uint32_t index, uint32_t Ack)
382 {
383
384         if (Ack > Acks_keep_track_info[index].Bigger_Ack_num) {
385                 Acks_keep_track_info[index].Bigger_Ack_num = Ack;
386         }
387         return 0;
388
389 }
390 static __inline int add_TCP_Pending_Ack(uint32_t Ack, uint32_t Session_index, struct txq_entry_t  *txqe)
391 {
392         Statisitcs_totalAcks++;
393         if (Pending_Acks < MAX_PENDING_ACKS) {
394                 Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].ack_num = Ack;
395                 Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].txqe = txqe;
396                 Pending_Acks_info[PendingAcks_arrBase + Pending_Acks].Session_index = Session_index;
397                 txqe->tcp_PendingAck_index = PendingAcks_arrBase + Pending_Acks;
398                 Pending_Acks++;
399
400         } else {
401
402         }
403         return 0;
404 }
405 static __inline int remove_TCP_related(void)
406 {
407         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
408         unsigned long flags;
409         p->os_func.os_spin_lock(p->txq_spinlock, &flags);
410
411         p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
412         return 0;
413 }
414
415 static __inline int tcp_process(struct txq_entry_t *tqe)
416 {
417         int ret;
418         uint8_t *eth_hdr_ptr;
419         uint8_t *buffer = tqe->buffer;
420         unsigned short h_proto;
421         int i;
422         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
423         unsigned long flags;
424         p->os_func.os_spin_lock(p->txq_spinlock, &flags);
425
426         eth_hdr_ptr = &buffer[0];
427         h_proto = ntohs(*((unsigned short *)&eth_hdr_ptr[12]));
428         if (h_proto == 0x0800) { /* IP */
429                 uint8_t *ip_hdr_ptr;
430                 uint8_t protocol;
431
432                 ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN];
433                 protocol = ip_hdr_ptr[9];
434
435
436                 if (protocol == 0x06) {
437                         uint8_t *tcp_hdr_ptr;
438                         uint32_t IHL, Total_Length, Data_offset;
439                         tcp_hdr_ptr = &ip_hdr_ptr[IP_HDR_LEN];
440                         IHL = (ip_hdr_ptr[0] & 0xf) << 2;
441                         Total_Length = (((uint32_t)ip_hdr_ptr[2]) << 8) + ((uint32_t)ip_hdr_ptr[3]);
442                         Data_offset = (((uint32_t)tcp_hdr_ptr[12] & 0xf0) >> 2);
443                         if (Total_Length == (IHL + Data_offset)) { /*we want to recognize the clear Acks(packet only carry Ack infos not with data) so data size must be equal zero*/
444                                 uint32_t seq_no, Ack_no;
445                                 seq_no  = (((uint32_t)tcp_hdr_ptr[4]) << 24) + (((uint32_t)tcp_hdr_ptr[5]) << 16) + (((uint32_t)tcp_hdr_ptr[6]) << 8) + ((uint32_t)tcp_hdr_ptr[7]);
446
447                                 Ack_no  = (((uint32_t)tcp_hdr_ptr[8]) << 24) + (((uint32_t)tcp_hdr_ptr[9]) << 16) + (((uint32_t)tcp_hdr_ptr[10]) << 8) + ((uint32_t)tcp_hdr_ptr[11]);
448
449
450                                 for (i = 0; i < Opened_TCP_session; i++) {
451                                         if (Acks_keep_track_info[i].Ack_seq_num == seq_no) {
452                                                 Update_TCP_track_session(i, Ack_no);
453                                                 break;
454                                         }
455                                 }
456                                 if (i == Opened_TCP_session) {
457                                         add_TCP_track_session(0, 0, seq_no);
458                                 }
459                                 add_TCP_Pending_Ack(Ack_no, i, tqe);
460
461
462                         }
463
464                 } else {
465                         ret = 0;
466                 }
467         } else {
468                 ret = 0;
469         }
470         p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
471         return ret;
472 }
473
474
475 static int wilc_wlan_txq_filter_dup_tcp_ack(void)
476 {
477
478         uint32_t i = 0;
479         uint32_t Dropped = 0;
480         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
481
482         p->os_func.os_spin_lock(p->txq_spinlock, &p->txq_spinlock_flags);
483         for (i = PendingAcks_arrBase; i < (PendingAcks_arrBase + Pending_Acks); i++) {
484                 if (Pending_Acks_info[i].ack_num < Acks_keep_track_info[Pending_Acks_info[i].Session_index].Bigger_Ack_num) {
485                         struct txq_entry_t *tqe;
486                         PRINT_D(TCP_ENH, "DROP ACK: %u \n", Pending_Acks_info[i].ack_num);
487                         tqe = Pending_Acks_info[i].txqe;
488                         if (tqe) {
489                                 wilc_wlan_txq_remove(tqe);
490                                 Statisitcs_DroppedAcks++;
491                                 tqe->status = 1;                                /* mark the packet send */
492                                 if (tqe->tx_complete_func)
493                                         tqe->tx_complete_func(tqe->priv, tqe->status);
494                                 p->os_func.os_free(tqe);
495                                 Dropped++;
496                                 /* p->txq_entries -= 1; */
497                         }
498                 }
499         }
500         Pending_Acks = 0;
501         Opened_TCP_session = 0;
502
503         if (PendingAcks_arrBase == 0) {
504                 PendingAcks_arrBase = MAX_TCP_SESSION;
505         } else {
506                 PendingAcks_arrBase = 0;
507         }
508
509
510         p->os_func.os_spin_unlock(p->txq_spinlock, &p->txq_spinlock_flags);
511
512         while (Dropped > 0) {
513                 /*consume the semaphore count of the removed packet*/
514                 p->os_func.os_wait(p->txq_wait, 1);
515                 Dropped--;
516         }
517
518         return 1;
519 }
520 #endif
521
522 #ifdef TCP_ENHANCEMENTS
523 WILC_Bool EnableTCPAckFilter = WILC_FALSE;
524
525 void Enable_TCP_ACK_Filter(WILC_Bool value)
526 {
527         EnableTCPAckFilter = value;
528 }
529
530 WILC_Bool is_TCP_ACK_Filter_Enabled(void)
531 {
532         return EnableTCPAckFilter;
533 }
534 #endif
535
536 static int wilc_wlan_txq_add_cfg_pkt(uint8_t *buffer, uint32_t buffer_size)
537 {
538         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
539         struct txq_entry_t *tqe;
540
541         PRINT_D(TX_DBG, "Adding config packet ...\n");
542         if (p->quit) {
543                 PRINT_D(TX_DBG, "Return due to clear function\n");
544                 p->os_func.os_signal(p->cfg_wait);
545                 return 0;
546         }
547
548         tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t));
549         if (tqe == NULL) {
550                 PRINT_ER("Failed to allocate memory\n");
551                 return 0;
552         }
553
554         tqe->type = WILC_CFG_PKT;
555         tqe->buffer = buffer;
556         tqe->buffer_size = buffer_size;
557         tqe->tx_complete_func = NULL;
558         tqe->priv = NULL;
559 #ifdef TCP_ACK_FILTER
560         tqe->tcp_PendingAck_index = NOT_TCP_ACK;
561 #endif
562         /**
563          *      Configuration packet always at the front
564          **/
565         PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n");
566
567         /*Edited by Amr - BugID_4720*/
568         if (wilc_wlan_txq_add_to_head(tqe))
569                 return 0;
570         /* wilc_wlan_txq_add_to_tail(tqe); */
571         return 1;
572 }
573
574 static int wilc_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func)
575 {
576         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
577         struct txq_entry_t *tqe;
578
579         if (p->quit)
580                 return 0;
581
582         tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t));
583
584         if (tqe == NULL)
585                 return 0;
586         tqe->type = WILC_NET_PKT;
587         tqe->buffer = buffer;
588         tqe->buffer_size = buffer_size;
589         tqe->tx_complete_func = func;
590         tqe->priv = priv;
591
592         PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n");
593 #ifdef TCP_ACK_FILTER
594         tqe->tcp_PendingAck_index = NOT_TCP_ACK;
595 #ifdef TCP_ENHANCEMENTS
596         if (is_TCP_ACK_Filter_Enabled() == WILC_TRUE)
597 #endif
598         tcp_process(tqe);
599 #endif
600         wilc_wlan_txq_add_to_tail(tqe);
601         /*return number of itemes in the queue*/
602         return p->txq_entries;
603 }
604 /*Bug3959: transmitting mgmt frames received from host*/
605 #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P)
606 int wilc_wlan_txq_add_mgmt_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func)
607 {
608
609         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
610         struct txq_entry_t *tqe;
611
612         if (p->quit)
613                 return 0;
614
615         tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t));
616
617         if (tqe == NULL)
618                 return 0;
619         tqe->type = WILC_MGMT_PKT;
620         tqe->buffer = buffer;
621         tqe->buffer_size = buffer_size;
622         tqe->tx_complete_func = func;
623         tqe->priv = priv;
624 #ifdef TCP_ACK_FILTER
625         tqe->tcp_PendingAck_index = NOT_TCP_ACK;
626 #endif
627         PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n");
628         wilc_wlan_txq_add_to_tail(tqe);
629         return 1;
630 }
631
632 #ifdef WILC_FULLY_HOSTING_AP
633 int wilc_FH_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func)
634 {
635         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
636         struct txq_entry_t *tqe;
637
638         if (p->quit)
639                 return 0;
640
641         tqe = (struct txq_entry_t *)p->os_func.os_malloc_atomic(sizeof(struct txq_entry_t));
642
643         if (tqe == NULL)
644                 return 0;
645         tqe->type = WILC_FH_DATA_PKT;
646         tqe->buffer = buffer;
647         tqe->buffer_size = buffer_size;
648         tqe->tx_complete_func = func;
649         tqe->priv = priv;
650         PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n");
651         wilc_wlan_txq_add_to_tail(tqe);
652         /*return number of itemes in the queue*/
653         return p->txq_entries;
654 }
655 #endif  /* WILC_FULLY_HOSTING_AP*/
656 #endif /*WILC_AP_EXTERNAL_MLME*/
657 static struct txq_entry_t *wilc_wlan_txq_get_first(void)
658 {
659         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
660         struct txq_entry_t *tqe;
661         unsigned long flags;
662
663         /*Added by Amr - BugID_4720*/
664         p->os_func.os_spin_lock(p->txq_spinlock, &flags);
665
666         /* p->os_func.os_enter_cs(p->txq_lock); */
667         tqe = p->txq_head;
668
669         /*Added by Amr - BugID_4720*/
670         p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
671
672         /* p->os_func.os_leave_cs(p->txq_lock); */
673
674         return tqe;
675 }
676
677 static struct txq_entry_t *wilc_wlan_txq_get_next(struct txq_entry_t *tqe)
678 {
679         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
680         unsigned long flags;
681         /*Added by Amr - BugID_4720*/
682         p->os_func.os_spin_lock(p->txq_spinlock, &flags);
683
684         /* p->os_func.os_enter_cs(p->txq_lock); */
685         tqe = tqe->next;
686
687         /*Added by Amr - BugID_4720*/
688         p->os_func.os_spin_unlock(p->txq_spinlock, &flags);
689
690         /* p->os_func.os_leave_cs(p->txq_lock); */
691
692         return tqe;
693 }
694
695 static int wilc_wlan_rxq_add(struct rxq_entry_t *rqe)
696 {
697         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
698
699         if (p->quit)
700                 return 0;
701
702         p->os_func.os_enter_cs(p->rxq_lock);
703         if (p->rxq_head == NULL) {
704                 PRINT_D(RX_DBG, "Add to Queue head\n");
705                 rqe->next = NULL;
706                 p->rxq_head = rqe;
707                 p->rxq_tail = rqe;
708         } else {
709                 PRINT_D(RX_DBG, "Add to Queue tail\n");
710                 p->rxq_tail->next = rqe;
711                 rqe->next = NULL;
712                 p->rxq_tail = rqe;
713         }
714         p->rxq_entries += 1;
715         PRINT_D(RX_DBG, "Number of queue entries: %d\n", p->rxq_entries);
716         p->os_func.os_leave_cs(p->rxq_lock);
717         return p->rxq_entries;
718 }
719
720 static struct rxq_entry_t *wilc_wlan_rxq_remove(void)
721 {
722         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
723
724         PRINT_D(RX_DBG, "Getting rxQ element\n");
725         if (p->rxq_head) {
726                 struct rxq_entry_t *rqe;
727
728                 p->os_func.os_enter_cs(p->rxq_lock);
729                 rqe = p->rxq_head;
730                 p->rxq_head = p->rxq_head->next;
731                 p->rxq_entries -= 1;
732                 PRINT_D(RX_DBG, "RXQ entries decreased\n");
733                 p->os_func.os_leave_cs(p->rxq_lock);
734                 return rqe;
735         }
736         PRINT_D(RX_DBG, "Nothing to get from Q\n");
737         return NULL;
738 }
739
740
741 /********************************************
742  *
743  *      Power Save handle functions
744  *
745  ********************************************/
746
747
748
749 #ifdef WILC_OPTIMIZE_SLEEP_INT
750
751 INLINE void chip_allow_sleep(void)
752 {
753         uint32_t reg = 0;
754
755         /* Clear bit 1 */
756         g_wlan.hif_func.hif_read_reg(0xf0, &reg);
757
758         g_wlan.hif_func.hif_write_reg(0xf0, reg & ~(1 << 0));
759 }
760
761 INLINE void chip_wakeup(void)
762 {
763         uint32_t reg, clk_status_reg, trials = 0;
764         uint32_t sleep_time;
765
766         if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
767                 do {
768                         g_wlan.hif_func.hif_read_reg(1, &reg);
769                         /* Set bit 1 */
770                         g_wlan.hif_func.hif_write_reg(1, reg | (1 << 1));
771
772                         /* Clear bit 1*/
773                         g_wlan.hif_func.hif_write_reg(1, reg & ~(1 << 1));
774
775                         do {
776                                 /* Wait for the chip to stabilize*/
777                                 WILC_Sleep(2);
778                                 /* Make sure chip is awake. This is an extra step that can be removed */
779                                 /* later to avoid the bus access overhead */
780                                 if ((wilc_get_chipid(WILC_TRUE) == 0)) {
781                                         wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
782                                 }
783                         } while ((wilc_get_chipid(WILC_TRUE) == 0) && ((++trials % 3) == 0));
784
785                 } while (wilc_get_chipid(WILC_TRUE) == 0);
786         } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO)   {
787                 g_wlan.hif_func.hif_read_reg(0xf0, &reg);
788                 do {
789                         /* Set bit 1 */
790                         g_wlan.hif_func.hif_write_reg(0xf0, reg | (1 << 0));
791
792                         /* Check the clock status */
793                         g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
794
795                         /* in case of clocks off, wait 2ms, and check it again. */
796                         /* if still off, wait for another 2ms, for a total wait of 6ms. */
797                         /* If still off, redo the wake up sequence */
798                         while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) {
799                                 /* Wait for the chip to stabilize*/
800                                 WILC_Sleep(2);
801
802                                 /* Make sure chip is awake. This is an extra step that can be removed */
803                                 /* later to avoid the bus access overhead */
804                                 g_wlan.hif_func.hif_read_reg(0xf1, &clk_status_reg);
805
806                                 if ((clk_status_reg & 0x1) == 0) {
807                                         wilc_debug(N_ERR, "clocks still OFF. Wake up failed\n");
808                                 }
809                         }
810                         /* in case of failure, Reset the wakeup bit to introduce a new edge on the next loop */
811                         if ((clk_status_reg & 0x1) == 0) {
812                                 /* Reset bit 0 */
813                                 g_wlan.hif_func.hif_write_reg(0xf0, reg & (~(1 << 0)));
814                         }
815                 } while ((clk_status_reg & 0x1) == 0);
816         }
817
818
819         if (genuChipPSstate == CHIP_SLEEPING_MANUAL) {
820                 g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
821                 reg &= ~(1 << 0);
822                 g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
823
824                 if (wilc_get_chipid(WILC_FALSE) >= 0x1002b0) {
825                         /* Enable PALDO back right after wakeup */
826                         uint32_t val32;
827                         g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
828                         val32 |= (1 << 6);
829                         g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
830
831                         g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
832                         val32 |= (1 << 6);
833                         g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
834                 }
835         }
836         genuChipPSstate = CHIP_WAKEDUP;
837 }
838 #else
839 INLINE void chip_wakeup(void)
840 {
841         uint32_t reg, trials = 0;
842         do {
843                 if ((g_wlan.io_func.io_type & 0x1) == HIF_SPI) {
844                         g_wlan.hif_func.hif_read_reg(1, &reg);
845                         /* Make sure bit 1 is 0 before we start. */
846                         g_wlan.hif_func.hif_write_reg(1, reg & ~(1 << 1));
847                         /* Set bit 1 */
848                         g_wlan.hif_func.hif_write_reg(1, reg | (1 << 1));
849                         /* Clear bit 1*/
850                         g_wlan.hif_func.hif_write_reg(1, reg  & ~(1 << 1));
851                 } else if ((g_wlan.io_func.io_type & 0x1) == HIF_SDIO)   {
852                         /* Make sure bit 0 is 0 before we start. */
853                         g_wlan.hif_func.hif_read_reg(0xf0, &reg);
854                         g_wlan.hif_func.hif_write_reg(0xf0, reg & ~(1 << 0));
855                         /* Set bit 1 */
856                         g_wlan.hif_func.hif_write_reg(0xf0, reg | (1 << 0));
857                         /* Clear bit 1 */
858                         g_wlan.hif_func.hif_write_reg(0xf0, reg  & ~(1 << 0));
859                 }
860
861                 do {
862                         /* Wait for the chip to stabilize*/
863 /*                      WILC_Sleep(2); */
864                         mdelay(3);
865
866                         /* Make sure chip is awake. This is an extra step that can be removed */
867                         /* later to avoid the bus access overhead */
868                         if ((wilc_get_chipid(WILC_TRUE) == 0)) {
869                                 wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
870                         }
871                 } while ((wilc_get_chipid(WILC_TRUE) == 0) && ((++trials % 3) == 0));
872
873         } while (wilc_get_chipid(WILC_TRUE) == 0);
874
875         if (genuChipPSstate == CHIP_SLEEPING_MANUAL) {
876                 g_wlan.hif_func.hif_read_reg(0x1C0C, &reg);
877                 reg &= ~(1 << 0);
878                 g_wlan.hif_func.hif_write_reg(0x1C0C, reg);
879
880                 if (wilc_get_chipid(WILC_FALSE) >= 0x1002b0) {
881                         /* Enable PALDO back right after wakeup */
882                         uint32_t val32;
883                         g_wlan.hif_func.hif_read_reg(0x1e1c, &val32);
884                         val32 |= (1 << 6);
885                         g_wlan.hif_func.hif_write_reg(0x1e1c, val32);
886
887                         g_wlan.hif_func.hif_read_reg(0x1e9c, &val32);
888                         val32 |= (1 << 6);
889                         g_wlan.hif_func.hif_write_reg(0x1e9c, val32);
890                 }
891         }
892         genuChipPSstate = CHIP_WAKEDUP;
893 }
894 #endif
895 void chip_sleep_manually(WILC_Uint32 u32SleepTime)
896 {
897         if (genuChipPSstate != CHIP_WAKEDUP) {
898                 /* chip is already sleeping. Do nothing */
899                 return;
900         }
901         acquire_bus(ACQUIRE_ONLY);
902
903 #ifdef WILC_OPTIMIZE_SLEEP_INT
904         chip_allow_sleep();
905 #endif
906
907         /* Trigger the manual sleep interrupt */
908         g_wlan.hif_func.hif_write_reg(0x10a8, 1);
909
910         genuChipPSstate = CHIP_SLEEPING_MANUAL;
911         release_bus(RELEASE_ONLY);
912
913 }
914
915
916 /********************************************
917  *
918  *      Tx, Rx queue handle functions
919  *
920  ********************************************/
921 static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount)
922 {
923         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
924         int i, entries = 0;
925         uint32_t sum;
926         uint32_t reg;
927         uint8_t *txb = p->tx_buffer;
928         uint32_t offset = 0;
929         int vmm_sz = 0;
930         struct txq_entry_t *tqe;
931         int ret = 0;
932         int counter;
933         int timeout;
934         uint32_t vmm_table[WILC_VMM_TBL_SIZE];
935         p->txq_exit = 0;
936         do {
937                 if (p->quit)
938                         break;
939
940                 /*Added by Amr - BugID_4720*/
941                 p->os_func.os_wait(p->txq_add_to_head_lock, CFG_PKTS_TIMEOUT);
942 #ifdef  TCP_ACK_FILTER
943                 wilc_wlan_txq_filter_dup_tcp_ack();
944 #endif
945                 /**
946                  *      build the vmm list
947                  **/
948                 PRINT_D(TX_DBG, "Getting the head of the TxQ\n");
949                 tqe = wilc_wlan_txq_get_first();
950                 i = 0;
951                 sum = 0;
952                 do {
953                         /* if ((tqe != NULL) && (i < (8)) && */
954                         /* if ((tqe != NULL) && (i < (WILC_VMM_TBL_SIZE-1)) && */
955                         if ((tqe != NULL) && (i < (WILC_VMM_TBL_SIZE - 1)) /* reserve last entry to 0 */) {
956
957                                 if (tqe->type == WILC_CFG_PKT) {
958                                         vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
959                                 }
960                                 /*Bug3959: transmitting mgmt frames received from host*/
961                                 /*vmm_sz will only be equal to tqe->buffer_size + 4 bytes (HOST_HDR_OFFSET)*/
962                                 /* in other cases WILC_MGMT_PKT and WILC_DATA_PKT_MAC_HDR*/
963                                 else if (tqe->type == WILC_NET_PKT) {
964                                         vmm_sz = ETH_ETHERNET_HDR_OFFSET;
965                                 }
966 #ifdef WILC_FULLY_HOSTING_AP
967                                 else if (tqe->type == WILC_FH_DATA_PKT) {
968                                         vmm_sz = FH_TX_HOST_HDR_OFFSET;
969                                 }
970 #endif
971 #ifdef WILC_AP_EXTERNAL_MLME
972                                 else {
973                                         vmm_sz = HOST_HDR_OFFSET;
974                                 }
975 #endif
976                                 vmm_sz += tqe->buffer_size;
977                                 PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz);
978                                 if (vmm_sz & 0x3) {                                                                                                     /* has to be word aligned */
979                                         vmm_sz = (vmm_sz + 4) & ~0x3;
980                                 }
981                                 if ((sum + vmm_sz) > p->tx_buffer_size) {
982                                         break;
983                                 }
984                                 PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz);
985                                 vmm_table[i] = vmm_sz / 4;                                                                                /* table take the word size */
986                                 PRINT_D(TX_DBG, "VMMTable entry size = %d\n", vmm_table[i]);
987
988                                 if (tqe->type == WILC_CFG_PKT) {
989                                         vmm_table[i] |= (1 << 10);
990                                         PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]);
991                                 }
992 #ifdef BIG_ENDIAN
993                                 vmm_table[i] = BYTE_SWAP(vmm_table[i]);
994 #endif
995                                 /* p->hif_func.hif_write_reg(0x1160,vmm_table[0]); */
996
997                                 /* wilc_debug(N_TXQ, "[wilc txq]: vmm table[%d] = %08x\n", i, vmm_table[i]); */
998                                 i++;
999                                 sum += vmm_sz;
1000                                 PRINT_D(TX_DBG, "sum = %d\n", sum);
1001                                 tqe = wilc_wlan_txq_get_next(tqe);
1002                         } else {
1003                                 break;
1004                         }
1005                 } while (1);
1006
1007                 if (i == 0) {           /* nothing in the queue */
1008                         PRINT_D(TX_DBG, "Nothing in TX-Q\n");
1009                         break;
1010                 } else {
1011                         PRINT_D(TX_DBG, "Mark the last entry in VMM table - number of previous entries = %d\n", i);
1012                         vmm_table[i] = 0x0;     /* mark the last element to 0 */
1013                 }
1014                 acquire_bus(ACQUIRE_AND_WAKEUP);
1015                 counter = 0;
1016                 do {
1017
1018                         ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
1019                         if (!ret) {
1020                                 wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n");
1021                                 break;
1022                         }
1023
1024                         if ((reg & 0x1) == 0) {
1025                                 /**
1026                                  *      write to vmm table
1027                                  **/
1028                                 PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4));
1029                                 break;
1030                         } else {
1031                                 counter++;
1032                                 if (counter > 200) {
1033                                         counter = 0;
1034                                         PRINT_D(TX_DBG, "Looping in tx ctrl , forcce quit\n");
1035                                         ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, 0);
1036                                         break;
1037                                 }
1038                                 /**
1039                                  *      wait for vmm table is ready
1040                                  **/
1041                                 PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait... \n");
1042                                 release_bus(RELEASE_ALLOW_SLEEP);
1043                                 p->os_func.os_sleep(3); /* wait 3 ms */
1044                                 acquire_bus(ACQUIRE_AND_WAKEUP);
1045                         }
1046                 } while (!p->quit);
1047
1048                 if (!ret) {
1049                         goto _end_;
1050                 }
1051
1052                 timeout = 200;
1053                 do {
1054
1055                         /**
1056                          * write to vmm table
1057                          **/
1058                         ret = p->hif_func.hif_block_tx(WILC_VMM_TBL_RX_SHADOW_BASE, (uint8_t *)vmm_table, ((i + 1) * 4)); /* Bug 4477 fix */
1059                         if (!ret) {
1060                                 wilc_debug(N_ERR, "ERR block TX of VMM table.\n");
1061                                 break;
1062                         }
1063
1064
1065                         /**
1066                          * interrupt firmware
1067                          **/
1068                         ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x2);
1069                         if (!ret) {
1070                                 wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n");
1071                                 break;
1072                         }
1073
1074                         /**
1075                          *      wait for confirm...
1076                          **/
1077
1078                         do {
1079                                 ret = p->hif_func.hif_read_reg(WILC_HOST_VMM_CTL, &reg);
1080                                 if (!ret) {
1081                                         wilc_debug(N_ERR, "[wilc txq]: fail can't read reg host_vmm_ctl..\n");
1082                                         break;
1083                                 }
1084                                 if ((reg >> 2) & 0x1) {
1085                                         /**
1086                                          *      Get the entries
1087                                          **/
1088                                         entries = ((reg >> 3) & 0x3f);
1089                                         /* entries = ((reg>>3)&0x2f); */
1090                                         break;
1091                                 } else {
1092                                         release_bus(RELEASE_ALLOW_SLEEP);
1093                                         p->os_func.os_sleep(3); /* wait 3 ms */
1094                                         acquire_bus(ACQUIRE_AND_WAKEUP);
1095                                         PRINT_WRN(GENERIC_DBG, "Can't get VMM entery - reg = %2x\n", reg);
1096                                 }
1097                         } while (--timeout);
1098                         if (timeout <= 0) {
1099                                 ret = p->hif_func.hif_write_reg(WILC_HOST_VMM_CTL, 0x0);
1100                                 break;
1101                         }
1102
1103                         if (!ret) {
1104                                 break;
1105                         }
1106
1107                         if (entries == 0) {
1108                                 PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]] \n", reg, i, vmm_table[i - 1]);
1109
1110                                 /* undo the transaction. */
1111                                 ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
1112                                 if (!ret) {
1113                                         wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n");
1114                                         break;
1115                                 }
1116                                 reg &= ~(1ul << 0);
1117                                 ret = p->hif_func.hif_write_reg(WILC_HOST_TX_CTRL, reg);
1118                                 if (!ret) {
1119                                         wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n");
1120                                         break;
1121                                 }
1122                                 break;
1123                         } else {
1124                                 break;
1125                         }
1126                 } while (1);
1127
1128                 if (!ret) {
1129                         goto _end_;
1130                 }
1131                 if (entries == 0) {
1132                         ret = WILC_TX_ERR_NO_BUF;
1133                         goto _end_;
1134                 }
1135
1136                 /* since copying data into txb takes some time, then
1137                  * allow the bus lock to be released let the RX task go. */
1138                 release_bus(RELEASE_ALLOW_SLEEP);
1139
1140                 /**
1141                  *      Copy data to the TX buffer
1142                  **/
1143                 offset = 0;
1144                 i = 0;
1145                 do {
1146                         tqe = wilc_wlan_txq_remove_from_head();
1147                         if (tqe != NULL && (vmm_table[i] != 0)) {
1148                                 uint32_t header, buffer_offset;
1149
1150 #ifdef BIG_ENDIAN
1151                                 vmm_table[i] = BYTE_SWAP(vmm_table[i]);
1152 #endif
1153                                 vmm_sz = (vmm_table[i] & 0x3ff);        /* in word unit */
1154                                 vmm_sz *= 4;
1155                                 header = (tqe->type << 31) | (tqe->buffer_size << 15) | vmm_sz;
1156                                 /*Bug3959: transmitting mgmt frames received from host*/
1157                                 /*setting bit 30 in the host header to indicate mgmt frame*/
1158 #ifdef WILC_AP_EXTERNAL_MLME
1159                                 if (tqe->type == WILC_MGMT_PKT) {
1160                                         header |= (1 << 30);
1161                                 } else {
1162                                         header &= ~(1 << 30);
1163                                 }
1164 #endif
1165                                 /*else if(tqe->type == WILC_DATA_PKT_MAC_HDR)
1166                                  * {
1167                                  *      header |= (1<< 29);
1168                                  * }*/
1169                                 /* wilc_debug(N_TXQ, "[wilc txq]: header (%08x), real size (%d), vmm size (%d)\n", header, tqe->buffer_size, vmm_sz); */
1170
1171 #ifdef BIG_ENDIAN
1172                                 header = BYTE_SWAP(header);
1173 #endif
1174                                 memcpy(&txb[offset], &header, 4);
1175                                 if (tqe->type == WILC_CFG_PKT) {
1176                                         buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
1177                                 }
1178                                 /*Bug3959: transmitting mgmt frames received from host*/
1179                                 /*buffer offset = HOST_HDR_OFFSET in other cases: WILC_MGMT_PKT*/
1180                                 /* and WILC_DATA_PKT_MAC_HDR*/
1181                                 else if (tqe->type == WILC_NET_PKT) {
1182                                         char *pBSSID = ((struct tx_complete_data *)(tqe->priv))->pBssid;
1183                                         buffer_offset = ETH_ETHERNET_HDR_OFFSET;
1184                                         /* copy the bssid at the sart of the buffer */
1185                                         memcpy(&txb[offset + 4], pBSSID, 6);
1186                                 }
1187 #ifdef WILC_FULLY_HOSTING_AP
1188                                 else if (tqe->type == WILC_FH_DATA_PKT) {
1189                                         buffer_offset = FH_TX_HOST_HDR_OFFSET;
1190                                 }
1191 #endif
1192                                 else {
1193                                         buffer_offset = HOST_HDR_OFFSET;
1194                                 }
1195
1196                                 memcpy(&txb[offset + buffer_offset], tqe->buffer, tqe->buffer_size);
1197                                 offset += vmm_sz;
1198                                 i++;
1199                                 tqe->status = 1;                                /* mark the packet send */
1200                                 if (tqe->tx_complete_func)
1201                                         tqe->tx_complete_func(tqe->priv, tqe->status);
1202                                 #ifdef TCP_ACK_FILTER
1203                                 if (tqe->tcp_PendingAck_index != NOT_TCP_ACK) {
1204                                         Pending_Acks_info[tqe->tcp_PendingAck_index].txqe = NULL;
1205                                 }
1206                                 #endif
1207                                 p->os_func.os_free(tqe);
1208                         } else {
1209                                 break;
1210                         }
1211                 } while (--entries);
1212
1213                 /**
1214                  *      lock the bus
1215                  **/
1216                 acquire_bus(ACQUIRE_AND_WAKEUP);
1217
1218                 ret = p->hif_func.hif_clear_int_ext(ENABLE_TX_VMM);
1219                 if (!ret) {
1220                         wilc_debug(N_ERR, "[wilc txq]: fail can't start tx VMM ...\n");
1221                         goto _end_;
1222                 }
1223
1224                 /**
1225                  *      transfer
1226                  **/
1227                 ret = p->hif_func.hif_block_tx_ext(0, txb, offset);
1228                 if (!ret) {
1229                         wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n");
1230                         goto _end_;
1231                 }
1232
1233 _end_:
1234
1235                 release_bus(RELEASE_ALLOW_SLEEP);
1236                 if (ret != 1)
1237                         break;
1238         } while (0);
1239         /* remove_TCP_related(); */
1240         /*Added by Amr - BugID_4720*/
1241         p->os_func.os_signal(p->txq_add_to_head_lock);
1242
1243         p->txq_exit = 1;
1244         PRINT_D(TX_DBG, "THREAD: Exiting txq\n");
1245         /* return tx[]q count */
1246         *pu32TxqCount = p->txq_entries;
1247         return ret;
1248 }
1249
1250 static void wilc_wlan_handle_rxq(void)
1251 {
1252         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1253         int offset = 0, size, has_packet = 0;
1254         uint8_t *buffer;
1255         struct rxq_entry_t *rqe;
1256
1257         p->rxq_exit = 0;
1258
1259
1260
1261
1262         do {
1263                 if (p->quit) {
1264                         PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function \n");
1265                         p->os_func.os_signal(p->cfg_wait);
1266                         break;
1267                 }
1268                 rqe = wilc_wlan_rxq_remove();
1269                 if (rqe == NULL) {
1270                         PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n");
1271                         break;
1272                 }
1273                 buffer = rqe->buffer;
1274                 size = rqe->buffer_size;
1275                 PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n", size, buffer);
1276                 offset = 0;
1277
1278
1279
1280                 do {
1281                         uint32_t header;
1282                         uint32_t pkt_len, pkt_offset, tp_len;
1283                         int is_cfg_packet;
1284                         PRINT_D(RX_DBG, "In the 2nd do-while\n");
1285                         memcpy(&header, &buffer[offset], 4);
1286 #ifdef BIG_ENDIAN
1287                         header = BYTE_SWAP(header);
1288 #endif
1289                         PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n", header, offset);
1290
1291
1292
1293                         is_cfg_packet = (header >> 31) & 0x1;
1294                         pkt_offset = (header >> 22) & 0x1ff;
1295                         tp_len = (header >> 11) & 0x7ff;
1296                         pkt_len = header & 0x7ff;
1297
1298                         if (pkt_len == 0 || tp_len == 0) {
1299                                 wilc_debug(N_RXQ, "[wilc rxq]: data corrupt, packet len or tp_len is 0 [%d][%d]\n", pkt_len, tp_len);
1300                                 break;
1301                         }
1302
1303 /*bug 3887: [AP] Allow Management frames to be passed to the host*/
1304                         #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P)
1305                         #define IS_MANAGMEMENT                          0x100
1306                         #define IS_MANAGMEMENT_CALLBACK                 0x080
1307                         #define IS_MGMT_STATUS_SUCCES                   0x040
1308
1309
1310                         if (pkt_offset & IS_MANAGMEMENT) {
1311                                 /* reset mgmt indicator bit, to use pkt_offeset in furthur calculations */
1312                                 pkt_offset &= ~(IS_MANAGMEMENT | IS_MANAGMEMENT_CALLBACK | IS_MGMT_STATUS_SUCCES);
1313
1314 #ifdef USE_WIRELESS
1315                                 WILC_WFI_mgmt_rx(&buffer[offset + HOST_HDR_OFFSET], pkt_len);
1316
1317 #endif
1318
1319                         }
1320                         /* BUG4530 fix */
1321                         else
1322                         #endif
1323                         {
1324                                 /* wilc_debug(N_RXQ, "[wilc rxq]: packet, tp len(%d), len (%d), offset (%d), cfg (%d)\n", tp_len, pkt_len, pkt_offset, is_cfg_packet); */
1325
1326                                 if (!is_cfg_packet) {
1327
1328                                         if (p->net_func.rx_indicate) {
1329                                                 if (pkt_len > 0) {
1330                                                         p->net_func.rx_indicate(&buffer[offset], pkt_len, pkt_offset);
1331                                                         has_packet = 1;
1332                                                 }
1333                                         }
1334                                 } else {
1335                                         wilc_cfg_rsp_t rsp;
1336
1337
1338
1339                                         p->cif_func.rx_indicate(&buffer[pkt_offset + offset], pkt_len, &rsp);
1340                                         if (rsp.type == WILC_CFG_RSP) {
1341                                                 /**
1342                                                  *      wake up the waiting task...
1343                                                  **/
1344                                                 PRINT_D(RX_DBG, "p->cfg_seq_no = %d - rsp.seq_no = %d\n", p->cfg_seq_no, rsp.seq_no);
1345                                                 if (p->cfg_seq_no == rsp.seq_no) {
1346                                                         p->os_func.os_signal(p->cfg_wait);
1347                                                 }
1348                                                 /* p->os_func.os_signal(p->cfg_wait); */
1349                                         } else if (rsp.type == WILC_CFG_RSP_STATUS) {
1350                                                 /**
1351                                                  *      Call back to indicate status...
1352                                                  **/
1353                                                 if (p->indicate_func.mac_indicate) {
1354                                                         p->indicate_func.mac_indicate(WILC_MAC_INDICATE_STATUS);
1355                                                 }
1356
1357                                         } else if (rsp.type == WILC_CFG_RSP_SCAN) {
1358                                                 if (p->indicate_func.mac_indicate)
1359                                                         p->indicate_func.mac_indicate(WILC_MAC_INDICATE_SCAN);
1360                                         }
1361                                 }
1362                         }
1363                         offset += tp_len;
1364                         if (offset >= size)
1365                                 break;
1366                 } while (1);
1367
1368
1369 #ifndef MEMORY_STATIC
1370                 if (buffer != NULL)
1371                         p->os_func.os_free((void *)buffer);
1372 #endif
1373                 if (rqe != NULL)
1374                         p->os_func.os_free((void *)rqe);
1375
1376                 if (has_packet) {
1377                         if (p->net_func.rx_complete)
1378                                 p->net_func.rx_complete();
1379                 }
1380         } while (1);
1381
1382         p->rxq_exit = 1;
1383         PRINT_D(RX_DBG, "THREAD: Exiting RX thread \n");
1384         return;
1385 }
1386
1387 /********************************************
1388  *
1389  *      Fast DMA Isr
1390  *
1391  ********************************************/
1392 static void wilc_unknown_isr_ext(void)
1393 {
1394         g_wlan.hif_func.hif_clear_int_ext(0);
1395 }
1396 static void wilc_pllupdate_isr_ext(uint32_t int_stats)
1397 {
1398
1399         int trials = 10;
1400
1401         g_wlan.hif_func.hif_clear_int_ext(PLL_INT_CLR);
1402
1403         /* Waiting for PLL */
1404         g_wlan.os_func.os_atomic_sleep(WILC_PLL_TO);
1405
1406         /* poll till read a valid data */
1407         while (!(ISWILC1000(wilc_get_chipid(WILC_TRUE)) && --trials)) {
1408                 PRINT_D(TX_DBG, "PLL update retrying\n");
1409                 g_wlan.os_func.os_atomic_sleep(1);
1410         }
1411 }
1412
1413 static void wilc_sleeptimer_isr_ext(uint32_t int_stats1)
1414 {
1415         g_wlan.hif_func.hif_clear_int_ext(SLEEP_INT_CLR);
1416 #ifndef WILC_OPTIMIZE_SLEEP_INT
1417         genuChipPSstate = CHIP_SLEEPING_AUTO;
1418 #endif
1419 }
1420
1421 static void wilc_wlan_handle_isr_ext(uint32_t int_status)
1422 {
1423         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1424 #ifdef MEMORY_STATIC
1425         uint32_t offset = p->rx_buffer_offset;
1426 #endif
1427         uint8_t *buffer = NULL;
1428         uint32_t size;
1429         uint32_t retries = 0;
1430         int ret = 0;
1431         struct rxq_entry_t *rqe;
1432
1433
1434         /**
1435          *      Get the rx size
1436          **/
1437
1438         size = ((int_status & 0x7fff) << 2);
1439
1440         while (!size && retries < 10) {
1441                 uint32_t time = 0;
1442                 /*looping more secure*/
1443                 /*zero size make a crashe because the dma will not happen and that will block the firmware*/
1444                 wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++);
1445                 p->hif_func.hif_read_size(&size);
1446                 size = ((size & 0x7fff) << 2);
1447                 retries++;
1448
1449         }
1450
1451         if (size > 0) {
1452 #ifdef MEMORY_STATIC
1453                 if (p->rx_buffer_size - offset < size)
1454                         offset = 0;
1455
1456                 if (p->rx_buffer)
1457                         buffer = &p->rx_buffer[offset];
1458                 else {
1459                         wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size);
1460                         goto _end_;
1461                 }
1462
1463 #else
1464                 buffer = p->os_func.os_malloc(size);
1465                 if (buffer == NULL) {
1466                         wilc_debug(N_ERR, "[wilc isr]: fail alloc host memory...drop the packets (%d)\n", size);
1467                         WILC_Sleep(100);
1468                         goto _end_;
1469                 }
1470 #endif
1471
1472                 /**
1473                  *      clear the chip's interrupt       after getting size some register getting corrupted after clear the interrupt
1474                  **/
1475                 p->hif_func.hif_clear_int_ext(DATA_INT_CLR | ENABLE_RX_VMM);
1476
1477
1478                 /**
1479                  * start transfer
1480                  **/
1481                 ret = p->hif_func.hif_block_rx_ext(0, buffer, size);
1482
1483                 if (!ret) {
1484                         wilc_debug(N_ERR, "[wilc isr]: fail block rx...\n");
1485                         goto _end_;
1486                 }
1487 _end_:
1488
1489
1490                 if (ret) {
1491 #ifdef MEMORY_STATIC
1492                         offset += size;
1493                         p->rx_buffer_offset = offset;
1494 #endif
1495                         /**
1496                          *      add to rx queue
1497                          **/
1498                         rqe = (struct rxq_entry_t *)p->os_func.os_malloc(sizeof(struct rxq_entry_t));
1499                         if (rqe != NULL) {
1500                                 rqe->buffer = buffer;
1501                                 rqe->buffer_size = size;
1502                                 PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer);
1503                                 wilc_wlan_rxq_add(rqe);
1504                                 p->os_func.os_signal(p->rxq_wait);
1505                         }
1506                 } else {
1507 #ifndef MEMORY_STATIC
1508                         if (buffer != NULL)
1509                                 p->os_func.os_free(buffer);
1510 #endif
1511                 }
1512         }
1513 #ifdef TCP_ENHANCEMENTS
1514         wilc_wlan_handle_rxq();
1515 #endif
1516 }
1517
1518 void wilc_handle_isr(void)
1519 {
1520         uint32_t int_status;
1521
1522         acquire_bus(ACQUIRE_AND_WAKEUP);
1523         g_wlan.hif_func.hif_read_int(&int_status);
1524
1525         if (int_status & PLL_INT_EXT) {
1526                 wilc_pllupdate_isr_ext(int_status);
1527         }
1528         if (int_status & DATA_INT_EXT) {
1529                 wilc_wlan_handle_isr_ext(int_status);
1530         #ifndef WILC_OPTIMIZE_SLEEP_INT
1531                 /* Chip is up and talking*/
1532                 genuChipPSstate = CHIP_WAKEDUP;
1533         #endif
1534         }
1535         if (int_status & SLEEP_INT_EXT) {
1536                 wilc_sleeptimer_isr_ext(int_status);
1537         }
1538
1539         if (!(int_status & (ALL_INT_EXT))) {
1540 #ifdef WILC_SDIO
1541                 PRINT_D(TX_DBG, ">> UNKNOWN_INTERRUPT - 0x%08x\n", int_status);
1542 #endif
1543                 wilc_unknown_isr_ext();
1544         }
1545 #if ((!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO))
1546         linux_wlan_enable_irq();
1547 #endif
1548         release_bus(RELEASE_ALLOW_SLEEP);
1549 }
1550
1551 /********************************************
1552  *
1553  *      Firmware download
1554  *
1555  ********************************************/
1556 static int wilc_wlan_firmware_download(const uint8_t *buffer, uint32_t buffer_size)
1557 {
1558         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1559         uint32_t offset;
1560         uint32_t addr, size, size2, blksz;
1561         uint8_t *dma_buffer;
1562         int ret = 0;
1563
1564         blksz = (1ul << 12); /* Bug 4703: 4KB Good enough size for most platforms = PAGE_SIZE. */
1565         /* Allocate a DMA coherent  buffer. */
1566
1567 #if (defined WILC_PREALLOC_AT_BOOT)
1568         {
1569                 extern void *get_fw_buffer(void);
1570                 dma_buffer = (uint8_t *)get_fw_buffer();
1571                 PRINT_D(TX_DBG, "fw_buffer = 0x%x\n", dma_buffer);
1572         }
1573 #else
1574         dma_buffer = (uint8_t *)g_wlan.os_func.os_malloc(blksz);
1575 #endif
1576         if (dma_buffer == NULL) {
1577                 /*EIO   5*/
1578                 ret = -5;
1579                 PRINT_ER("Can't allocate buffer for firmware download IO error\n ");
1580                 goto _fail_1;
1581         }
1582
1583         PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size);
1584         /**
1585          *      load the firmware
1586          **/
1587         offset = 0;
1588         do {
1589                 memcpy(&addr, &buffer[offset], 4);
1590                 memcpy(&size, &buffer[offset + 4], 4);
1591 #ifdef BIG_ENDIAN
1592                 addr = BYTE_SWAP(addr);
1593                 size = BYTE_SWAP(size);
1594 #endif
1595                 acquire_bus(ACQUIRE_ONLY);
1596                 offset += 8;
1597                 while (((int)size) && (offset < buffer_size)) {
1598                         if (size <= blksz) {
1599                                 size2 = size;
1600                         } else {
1601                                 size2 = blksz;
1602                         }
1603                         /* Copy firmware into a DMA coherent buffer */
1604                         memcpy(dma_buffer, &buffer[offset], size2);
1605                         ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2);
1606                         if (!ret)
1607                                 break;
1608
1609                         addr += size2;
1610                         offset += size2;
1611                         size -= size2;
1612                 }
1613                 release_bus(RELEASE_ONLY);
1614
1615                 if (!ret) {
1616                         /*EIO   5*/
1617                         ret = -5;
1618                         PRINT_ER("Can't download firmware IO error\n ");
1619                         goto _fail_;
1620                 }
1621                 PRINT_D(INIT_DBG, "Offset = %d\n", offset);
1622         } while (offset < buffer_size);
1623
1624 _fail_:
1625
1626 #if (defined WILC_PREALLOC_AT_BOOT)
1627
1628 #else
1629         if (dma_buffer)
1630                 g_wlan.os_func.os_free(dma_buffer);
1631 #endif
1632
1633 _fail_1:
1634
1635         return (ret < 0) ? ret : 0;
1636 }
1637
1638 /********************************************
1639  *
1640  *      Common
1641  *
1642  ********************************************/
1643 static int wilc_wlan_start(void)
1644 {
1645         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1646         uint32_t reg = 0;
1647         int ret;
1648         uint32_t chipid;
1649
1650         /**
1651          *      Set the host interface
1652          **/
1653 #ifdef OLD_FPGA_BITFILE
1654         acquire_bus(ACQUIRE_ONLY);
1655         ret = p->hif_func.hif_read_reg(WILC_VMM_CORE_CTL, &reg);
1656         if (!ret) {
1657                 wilc_debug(N_ERR, "[wilc start]: fail read reg vmm_core_ctl...\n");
1658                 release_bus(RELEASE_ALLOW_SLEEP);
1659                 return ret;
1660         }
1661         reg |= (p->io_func.io_type << 2);
1662         ret = p->hif_func.hif_write_reg(WILC_VMM_CORE_CTL, reg);
1663         if (!ret) {
1664                 wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_ctl...\n");
1665                 release_bus(RELEASE_ONLY);
1666                 return ret;
1667         }
1668 #else
1669         if (p->io_func.io_type == HIF_SDIO) {
1670                 reg = 0;
1671                 reg |= (1 << 3); /* bug 4456 and 4557 */
1672         } else if (p->io_func.io_type == HIF_SPI) {
1673                 reg = 1;
1674         }
1675         acquire_bus(ACQUIRE_ONLY);
1676         ret = p->hif_func.hif_write_reg(WILC_VMM_CORE_CFG, reg);
1677         if (!ret) {
1678                 wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n");
1679                 release_bus(RELEASE_ONLY);
1680                 /* EIO  5*/
1681                 ret = -5;
1682                 return ret;
1683         }
1684         reg = 0;
1685 #ifdef WILC_SDIO_IRQ_GPIO
1686         reg |= WILC_HAVE_SDIO_IRQ_GPIO;
1687 #endif
1688
1689 #ifdef WILC_DISABLE_PMU
1690 #else
1691         reg |= WILC_HAVE_USE_PMU;
1692 #endif
1693
1694 #ifdef WILC_SLEEP_CLK_SRC_XO
1695         reg |= WILC_HAVE_SLEEP_CLK_SRC_XO;
1696 #elif defined WILC_SLEEP_CLK_SRC_RTC
1697         reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC;
1698 #endif
1699
1700 #ifdef WILC_EXT_PA_INV_TX_RX
1701         reg |= WILC_HAVE_EXT_PA_INV_TX_RX;
1702 #endif
1703
1704         reg |= WILC_HAVE_LEGACY_RF_SETTINGS;
1705
1706
1707 /*BugID_5257*/
1708 /*Set oscillator frequency*/
1709 #ifdef XTAL_24
1710         reg |= WILC_HAVE_XTAL_24;
1711 #endif
1712
1713 /*BugID_5271*/
1714 /*Enable/Disable GPIO configuration for FW logs*/
1715 #ifdef DISABLE_WILC_UART
1716         reg |= WILC_HAVE_DISABLE_WILC_UART;
1717 #endif
1718
1719         ret = p->hif_func.hif_write_reg(WILC_GP_REG_1, reg);
1720         if (!ret) {
1721                 wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n");
1722                 release_bus(RELEASE_ONLY);
1723                 /* EIO  5*/
1724                 ret = -5;
1725                 return ret;
1726         }
1727 #endif
1728
1729
1730         /**
1731          *      Bus related
1732          **/
1733         p->hif_func.hif_sync_ext(NUM_INT_EXT);
1734
1735         ret = p->hif_func.hif_read_reg(0x1000, &chipid);
1736         if (!ret) {
1737                 wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n");
1738                 release_bus(RELEASE_ONLY);
1739                 /* EIO  5*/
1740                 ret = -5;
1741                 return ret;
1742         }
1743
1744         /**
1745          *      Go...
1746          **/
1747
1748         /* p->hif_func.hif_write_reg(0x150014, reg); */
1749
1750         p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1751         if ((reg & (1ul << 10)) == (1ul << 10)) {
1752                 reg &= ~(1ul << 10);
1753                 p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1754                 p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1755         }
1756
1757         reg |= (1ul << 10);
1758         ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1759         p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1760         release_bus(RELEASE_ONLY);
1761
1762         return (ret < 0) ? ret : 0;
1763 }
1764
1765 void wilc_wlan_global_reset(void)
1766 {
1767
1768         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1769         acquire_bus(ACQUIRE_AND_WAKEUP);
1770         p->hif_func.hif_write_reg(WILC_GLB_RESET_0, 0x0);
1771         release_bus(RELEASE_ONLY);
1772 }
1773 static int wilc_wlan_stop(void)
1774 {
1775         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1776         uint32_t reg = 0;
1777         int ret;
1778         uint8_t timeout = 10;
1779         /**
1780          *      TODO: stop the firmware, need a re-download
1781          **/
1782         acquire_bus(ACQUIRE_AND_WAKEUP);
1783
1784         ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1785         if (!ret) {
1786                 PRINT_ER("Error while reading reg\n");
1787                 release_bus(RELEASE_ALLOW_SLEEP);
1788                 return ret;
1789         }
1790
1791         reg &= ~(1 << 10);
1792
1793
1794         ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1795         if (!ret) {
1796                 PRINT_ER("Error while writing reg\n");
1797                 release_bus(RELEASE_ALLOW_SLEEP);
1798                 return ret;
1799         }
1800
1801
1802
1803         do {
1804                 ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1805                 if (!ret) {
1806                         PRINT_ER("Error while reading reg\n");
1807                         release_bus(RELEASE_ALLOW_SLEEP);
1808                         return ret;
1809                 }
1810                 PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
1811                 /*Workaround to ensure that the chip is actually reset*/
1812                 if ((reg & (1 << 10))) {
1813                         PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", timeout);
1814                         reg &= ~(1 << 10);
1815                         ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);
1816                         timeout--;
1817                 } else {
1818                         PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", timeout);
1819                         ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, &reg);
1820                         if (!ret) {
1821                                 PRINT_ER("Error while reading reg\n");
1822                                 release_bus(RELEASE_ALLOW_SLEEP);
1823                                 return ret;
1824                         }
1825                         PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", reg, timeout);
1826                         break;
1827                 }
1828
1829         } while (timeout);
1830 #if 1
1831 /******************************************************************************/
1832 /* This was add at Bug 4595 to reset the chip while maintaining the bus state */
1833 /******************************************************************************/
1834         reg = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 8) | (1 << 9) | (1 << 26) | (1 << 29) | (1 << 30) | (1 << 31)); /**/
1835         /**/
1836         ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);                                 /**/
1837         reg = ~(1 << 10);                                                                                               /**/
1838         /**/
1839         ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);                                 /**/
1840 /******************************************************************************/
1841 #endif
1842
1843         release_bus(RELEASE_ALLOW_SLEEP);
1844
1845         return ret;
1846 }
1847
1848 static void wilc_wlan_cleanup(void)
1849 {
1850         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1851         struct txq_entry_t *tqe;
1852         struct rxq_entry_t *rqe;
1853         uint32_t reg = 0;
1854         int ret;
1855
1856         p->quit = 1;
1857         /**
1858          *      wait for queue end
1859          **/
1860         /* p->os_func.os_signal(p->txq_wait); */
1861         /* p->os_func.os_signal(p->rxq_wait); */
1862
1863         /* complete(p->txq_wait); */
1864         /* complete(p->rxq_wait); */
1865         /*do {
1866          *      if (p->txq_exit && p->rxq_exit)
1867          *              break;
1868          * } while (1);*/
1869
1870         /**
1871          *      clean up the queue
1872          **/
1873         do {
1874                 tqe = wilc_wlan_txq_remove_from_head();
1875                 if (tqe == NULL)
1876                         break;
1877                 if (tqe->tx_complete_func)
1878                         tqe->tx_complete_func(tqe->priv, 0);
1879                 p->os_func.os_free((void *)tqe);
1880         } while (1);
1881
1882         do {
1883                 rqe = wilc_wlan_rxq_remove();
1884                 if (rqe == NULL)
1885                         break;
1886 #ifdef MEMORY_DYNAMIC
1887                 p->os_func.os_free((void *)tqe->buffer);
1888 #endif
1889                 p->os_func.os_free((void *)rqe);
1890         } while (1);
1891
1892         /**
1893          *      clean up buffer
1894          **/
1895
1896 #if (defined WILC_PREALLOC_AT_BOOT)
1897
1898 #else
1899         #ifdef MEMORY_STATIC
1900         if (p->rx_buffer) {
1901                 p->os_func.os_free(p->rx_buffer);
1902                 p->rx_buffer = NULL;
1903         }
1904         #endif
1905         if (p->tx_buffer) {
1906                 p->os_func.os_free(p->tx_buffer);
1907                 p->tx_buffer = NULL;
1908         }
1909 #endif
1910
1911         acquire_bus(ACQUIRE_AND_WAKEUP);
1912
1913
1914         ret = p->hif_func.hif_read_reg(WILC_GP_REG_0, &reg);
1915         if (!ret) {
1916                 PRINT_ER("Error while reading reg\n");
1917                 release_bus(RELEASE_ALLOW_SLEEP);
1918         }
1919         PRINT_ER("Writing ABORT reg\n");
1920         ret = p->hif_func.hif_write_reg(WILC_GP_REG_0, (reg | ABORT_INT));
1921         if (!ret) {
1922                 PRINT_ER("Error while writing reg\n");
1923                 release_bus(RELEASE_ALLOW_SLEEP);
1924         }
1925         release_bus(RELEASE_ALLOW_SLEEP);
1926         /**
1927          *      io clean up
1928          **/
1929         p->hif_func.hif_deinit(NULL);
1930
1931 }
1932
1933 static int wilc_wlan_cfg_commit(int type, uint32_t drvHandler)
1934 {
1935         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1936         wilc_cfg_frame_t *cfg = &p->cfg_frame;
1937         int total_len = p->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE;
1938         int seq_no = p->cfg_seq_no % 256;
1939         int driver_handler = (WILC_Uint32)drvHandler;
1940
1941
1942         /**
1943          *      Set up header
1944          **/
1945         if (type == WILC_CFG_SET) {             /* Set */
1946                 cfg->wid_header[0] = 'W';
1947         } else {                                        /* Query */
1948                 cfg->wid_header[0] = 'Q';
1949         }
1950         cfg->wid_header[1] = seq_no;    /* sequence number */
1951         cfg->wid_header[2] = (uint8_t)total_len;
1952         cfg->wid_header[3] = (uint8_t)(total_len >> 8);
1953         cfg->wid_header[4] = (uint8_t)driver_handler;
1954         cfg->wid_header[5] = (uint8_t)(driver_handler >> 8);
1955         cfg->wid_header[6] = (uint8_t)(driver_handler >> 16);
1956         cfg->wid_header[7] = (uint8_t)(driver_handler >> 24);
1957         p->cfg_seq_no = seq_no;
1958
1959         /**
1960          *      Add to TX queue
1961          **/
1962
1963         /*Edited by Amr - BugID_4720*/
1964         if (!wilc_wlan_txq_add_cfg_pkt(&cfg->wid_header[0], total_len))
1965                 return -1;
1966
1967         return 0;
1968 }
1969
1970 static int wilc_wlan_cfg_set(int start, uint32_t wid, uint8_t *buffer, uint32_t buffer_size, int commit, uint32_t drvHandler)
1971 {
1972         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
1973         uint32_t offset;
1974         int ret_size;
1975
1976
1977         if (p->cfg_frame_in_use)
1978                 return 0;
1979
1980         if (start)
1981                 p->cfg_frame_offset = 0;
1982
1983         offset = p->cfg_frame_offset;
1984         ret_size = p->cif_func.cfg_wid_set(p->cfg_frame.frame, offset, (uint16_t)wid, buffer, buffer_size);
1985         offset += ret_size;
1986         p->cfg_frame_offset = offset;
1987
1988         if (commit) {
1989                 PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n", p->cfg_seq_no);
1990                 PRINT_D(RX_DBG, "Processing cfg_set()\n");
1991                 p->cfg_frame_in_use = 1;
1992
1993                 /*Edited by Amr - BugID_4720*/
1994                 if (wilc_wlan_cfg_commit(WILC_CFG_SET, drvHandler))
1995                         ret_size = 0;   /* BugID_5213 */
1996
1997                 if (p->os_func.os_wait(p->cfg_wait, CFG_PKTS_TIMEOUT)) {
1998                         PRINT_D(TX_DBG, "Set Timed Out\n");
1999                         ret_size = 0;
2000                 }
2001                 p->cfg_frame_in_use = 0;
2002                 p->cfg_frame_offset = 0;
2003                 p->cfg_seq_no += 1;
2004
2005         }
2006
2007         return ret_size;
2008 }
2009 static int wilc_wlan_cfg_get(int start, uint32_t wid, int commit, uint32_t drvHandler)
2010 {
2011         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
2012         uint32_t offset;
2013         int ret_size;
2014
2015
2016         if (p->cfg_frame_in_use)
2017                 return 0;
2018
2019         if (start)
2020                 p->cfg_frame_offset = 0;
2021
2022         offset = p->cfg_frame_offset;
2023         ret_size = p->cif_func.cfg_wid_get(p->cfg_frame.frame, offset, (uint16_t)wid);
2024         offset += ret_size;
2025         p->cfg_frame_offset = offset;
2026
2027         if (commit) {
2028                 p->cfg_frame_in_use = 1;
2029
2030                 /*Edited by Amr - BugID_4720*/
2031                 if (wilc_wlan_cfg_commit(WILC_CFG_QUERY, drvHandler))
2032                         ret_size = 0;   /* BugID_5213 */
2033
2034
2035                 if (p->os_func.os_wait(p->cfg_wait, CFG_PKTS_TIMEOUT)) {
2036                         PRINT_D(TX_DBG, "Get Timed Out\n");
2037                         ret_size = 0;
2038                 }
2039                 PRINT_D(GENERIC_DBG, "[WILC]Get Response received\n");
2040                 p->cfg_frame_in_use = 0;
2041                 p->cfg_frame_offset = 0;
2042                 p->cfg_seq_no += 1;
2043         }
2044
2045         return ret_size;
2046 }
2047
2048 static int wilc_wlan_cfg_get_val(uint32_t wid, uint8_t *buffer, uint32_t buffer_size)
2049 {
2050         wilc_wlan_dev_t *p = (wilc_wlan_dev_t *)&g_wlan;
2051         int ret;
2052
2053         ret = p->cif_func.cfg_wid_get_val((uint16_t)wid, buffer, buffer_size);
2054
2055         return ret;
2056 }
2057
2058 void wilc_bus_set_max_speed(void)
2059 {
2060
2061         /* Increase bus speed to max possible.  */
2062         g_wlan.hif_func.hif_set_max_bus_speed();
2063 }
2064
2065 void wilc_bus_set_default_speed(void)
2066 {
2067
2068         /* Restore bus speed to default.  */
2069         g_wlan.hif_func.hif_set_default_bus_speed();
2070 }
2071 uint32_t init_chip(void)
2072 {
2073         uint32_t chipid;
2074         uint32_t reg, ret = 0;
2075
2076 #if defined(PLAT_RK3026_TCHIP)
2077         acquire_bus(ACQUIRE_AND_WAKEUP); /* AMR : 0422 RK3026 Crash issue */
2078 #else
2079         acquire_bus(ACQUIRE_ONLY);
2080 #endif
2081
2082         chipid = wilc_get_chipid(WILC_TRUE);
2083
2084
2085
2086         if ((chipid & 0xfff) != 0xa0) {
2087                 /**
2088                  * Avoid booting from boot ROM. Make sure that Drive IRQN [SDIO platform]
2089                  * or SD_DAT3 [SPI platform] to ?1?
2090                  **/
2091                 /* Set cortus reset register to register control. */
2092                 ret = g_wlan.hif_func.hif_read_reg(0x1118, &reg);
2093                 if (!ret) {
2094                         wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1118 ...\n");
2095                         return ret;
2096                 }
2097                 reg |= (1 << 0);
2098                 ret = g_wlan.hif_func.hif_write_reg(0x1118, reg);
2099                 if (!ret) {
2100                         wilc_debug(N_ERR, "[wilc start]: fail write reg 0x1118 ...\n");
2101                         return ret;
2102                 }
2103                 /**
2104                  * Write branch intruction to IRAM (0x71 trap) at location 0xFFFF0000
2105                  * (Cortus map) or C0000 (AHB map).
2106                  **/
2107                 ret = g_wlan.hif_func.hif_write_reg(0xc0000, 0x71);
2108                 if (!ret) {
2109                         wilc_debug(N_ERR, "[wilc start]: fail write reg 0xc0000 ...\n");
2110                         return ret;
2111                 }
2112         }
2113
2114
2115         #if 0
2116         if ((chipid & 0xfff) < 0xf0) {
2117                 /* Setting MUX to probe sleep signal on pin 6 of J216*/
2118                 g_wlan.hif_func.hif_write_reg(0x1060, 0x1);
2119                 g_wlan.hif_func.hif_write_reg(0x1180, 0x33333333);
2120                 g_wlan.hif_func.hif_write_reg(0x1184, 0x33333333);
2121                 g_wlan.hif_func.hif_read_reg(0x1408, &reg);
2122                 /* set MUX for GPIO_4 (pin 4) to cortus GPIO*/
2123                 reg &= ~((0x7 << 16));
2124                 g_wlan.hif_func.hif_write_reg(0x1408, (reg | (0x7 << 12)));
2125         } else {
2126                 /* Enable test bus*/
2127                 g_wlan.hif_func.hif_write_reg(0x1060, 0x1);
2128                 /* Rotate bus signals to get sleep signal on pin 6 like it was on previous chips*/
2129                 g_wlan.hif_func.hif_write_reg(0x1188, 0x70);
2130                 /* Set output of pin 6 to test bus 0x1*/
2131                 /* Set output of pin 9 to test bus 0x2*/
2132                 g_wlan.hif_func.hif_write_reg(0x1180, 0x200100);
2133                 g_wlan.hif_func.hif_read_reg(0x1408, &reg);
2134
2135                 /* set MUX for GPIO_4 (pin 4) to cortus GPIO*/
2136                 reg &= ~((0x7 << 16));
2137                 /* set MUX for GPIO_3 (pin 6) to test bus*/
2138                 reg |= (0x7 << 12) | (0x7 << 24);
2139                 g_wlan.hif_func.hif_write_reg(0x1408, reg);
2140         }
2141         #endif
2142
2143
2144
2145         release_bus(RELEASE_ONLY);
2146
2147         return ret;
2148
2149 }
2150
2151 uint32_t wilc_get_chipid(uint8_t update)
2152 {
2153         static uint32_t chipid;
2154         /* SDIO can't read into global variables */
2155         /* Use this variable as a temp, then copy to the global */
2156         uint32_t tempchipid = 0;
2157         uint32_t rfrevid;
2158
2159         if (chipid == 0 || update != 0) {
2160                 g_wlan.hif_func.hif_read_reg(0x1000, &tempchipid);
2161                 g_wlan.hif_func.hif_read_reg(0x13f4, &rfrevid);
2162                 if (!ISWILC1000(tempchipid)) {
2163                         chipid = 0;
2164                         goto _fail_;
2165                 }
2166                 if (tempchipid == 0x1002a0) {
2167                         if (rfrevid == 0x1) { /* 1002A0 */
2168                         } else { /* if (rfrevid == 0x2) */   /* 1002A1 */
2169                                 tempchipid = 0x1002a1;
2170                         }
2171                 } else if (tempchipid == 0x1002b0) {
2172                         if (rfrevid == 3) { /* 1002B0 */
2173                         } else if (rfrevid == 4) { /* 1002B1 */
2174                                 tempchipid = 0x1002b1;
2175                         } else { /* if(rfrevid == 5) */   /* 1002B2 */
2176                                 tempchipid = 0x1002b2;
2177                         }
2178                 } else {
2179                 }
2180
2181                 chipid = tempchipid;
2182         }
2183 _fail_:
2184         return chipid;
2185 }
2186
2187 #ifdef COMPLEMENT_BOOT
2188 uint8_t core_11b_ready(void)
2189 {
2190         uint32_t reg_val;
2191
2192         acquire_bus(ACQUIRE_ONLY);
2193         g_wlan.hif_func.hif_write_reg(0x16082c, 1);
2194         g_wlan.hif_func.hif_write_reg(0x161600, 0x90);
2195         g_wlan.hif_func.hif_read_reg(0x161600, &reg_val);
2196         release_bus(RELEASE_ONLY);
2197
2198         if (reg_val == 0x90)
2199                 return 0;
2200         else
2201                 return 1;
2202 }
2203 #endif
2204
2205 int wilc_wlan_init(wilc_wlan_inp_t *inp, wilc_wlan_oup_t *oup)
2206 {
2207
2208         int ret = 0;
2209
2210         PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n");
2211
2212         memset((void *)&g_wlan, 0, sizeof(wilc_wlan_dev_t));
2213
2214         /**
2215          *      store the input
2216          **/
2217         memcpy((void *)&g_wlan.os_func, (void *)&inp->os_func, sizeof(wilc_wlan_os_func_t));
2218         memcpy((void *)&g_wlan.io_func, (void *)&inp->io_func, sizeof(wilc_wlan_io_func_t));
2219         memcpy((void *)&g_wlan.net_func, (void *)&inp->net_func, sizeof(wilc_wlan_net_func_t));
2220         memcpy((void *)&g_wlan.indicate_func, (void *)&inp->indicate_func, sizeof(wilc_wlan_net_func_t));
2221         g_wlan.hif_lock = inp->os_context.hif_critical_section;
2222         g_wlan.txq_lock = inp->os_context.txq_critical_section;
2223
2224         /*Added by Amr - BugID_4720*/
2225         g_wlan.txq_add_to_head_lock = inp->os_context.txq_add_to_head_critical_section;
2226
2227         /*Added by Amr - BugID_4720*/
2228         g_wlan.txq_spinlock = inp->os_context.txq_spin_lock;
2229
2230         g_wlan.rxq_lock = inp->os_context.rxq_critical_section;
2231         g_wlan.txq_wait = inp->os_context.txq_wait_event;
2232         g_wlan.rxq_wait = inp->os_context.rxq_wait_event;
2233         g_wlan.cfg_wait = inp->os_context.cfg_wait_event;
2234         g_wlan.tx_buffer_size = inp->os_context.tx_buffer_size;
2235 #if defined (MEMORY_STATIC)
2236         g_wlan.rx_buffer_size = inp->os_context.rx_buffer_size;
2237 #endif
2238         /* g_wlan.os_func.os_lock(g_wlan.cfg_wait); */
2239         /***
2240          *      host interface init
2241          **/
2242 #if defined(PLAT_RK3026_TCHIP) /* AMR : 0422 RK3026 Crash issue */
2243         if (!g_wilc_initialized) {
2244                 custom_lock_bus(g_mac_open);
2245                 custom_wakeup(g_mac_open);
2246         }
2247 #endif
2248
2249         if ((inp->io_func.io_type & 0x1) == HIF_SDIO) {
2250                 if (!hif_sdio.hif_init(inp, wilc_debug)) {
2251                         /* EIO  5 */
2252                         ret = -5;
2253                         goto _fail_;
2254                 }
2255                 memcpy((void *)&g_wlan.hif_func, &hif_sdio, sizeof(wilc_hif_func_t));
2256         } else {
2257                 if ((inp->io_func.io_type & 0x1) == HIF_SPI) {
2258                         /**
2259                          *      TODO:
2260                          **/
2261                         if (!hif_spi.hif_init(inp, wilc_debug)) {
2262                                 /* EIO  5 */
2263                                 ret = -5;
2264                                 goto _fail_;
2265                         }
2266                         memcpy((void *)&g_wlan.hif_func, &hif_spi, sizeof(wilc_hif_func_t));
2267                 } else {
2268                         /* EIO  5 */
2269                         ret = -5;
2270                         goto _fail_;
2271                 }
2272         }
2273
2274         /***
2275          *      mac interface init
2276          **/
2277         if (!mac_cfg.cfg_init(wilc_debug)) {
2278                 /* ENOBUFS      105 */
2279                 ret = -105;
2280                 goto _fail_;
2281         }
2282         memcpy((void *)&g_wlan.cif_func, &mac_cfg, sizeof(wilc_cfg_func_t));
2283
2284
2285         /**
2286          *      alloc tx, rx buffer
2287          **/
2288 #if (defined WILC_PREALLOC_AT_BOOT)
2289         extern void *get_tx_buffer(void);
2290         extern void *get_rx_buffer(void);
2291
2292         PRINT_D(TX_DBG, "malloc before, g_wlan.tx_buffer = 0x%x, g_wlan.rx_buffer = 0x%x\n", g_wlan.tx_buffer, g_wlan.rx_buffer);
2293 #endif
2294
2295
2296
2297         if (g_wlan.tx_buffer == NULL)
2298 #if (defined WILC_PREALLOC_AT_BOOT)
2299                 g_wlan.tx_buffer = (uint8_t *)get_tx_buffer();
2300 #else
2301                 g_wlan.tx_buffer = (uint8_t *)g_wlan.os_func.os_malloc(g_wlan.tx_buffer_size);
2302 #endif
2303         PRINT_D(TX_DBG, "g_wlan.tx_buffer = %p\n", g_wlan.tx_buffer);
2304
2305         if (g_wlan.tx_buffer == NULL) {
2306                 /* ENOBUFS      105 */
2307                 ret = -105;
2308                 PRINT_ER("Can't allocate Tx Buffer");
2309                 goto _fail_;
2310         }
2311
2312 /* rx_buffer is not used unless we activate USE_MEM STATIC which is not applicable, allocating such memory is useless*/
2313 #if defined (MEMORY_STATIC)
2314         if (g_wlan.rx_buffer == NULL)
2315   #if (defined WILC_PREALLOC_AT_BOOT)
2316                 g_wlan.rx_buffer = (uint8_t *)get_rx_buffer();
2317   #else
2318                 g_wlan.rx_buffer = (uint8_t *)g_wlan.os_func.os_malloc(g_wlan.rx_buffer_size);
2319   #endif
2320         PRINT_D(TX_DBG, "g_wlan.rx_buffer =%p\n", g_wlan.rx_buffer);
2321         if (g_wlan.rx_buffer == NULL) {
2322                 /* ENOBUFS      105 */
2323                 ret = -105;
2324                 PRINT_ER("Can't allocate Rx Buffer");
2325                 goto _fail_;
2326         }
2327 #endif
2328
2329         /**
2330          *      export functions
2331          **/
2332         oup->wlan_firmware_download = wilc_wlan_firmware_download;
2333         oup->wlan_start = wilc_wlan_start;
2334         oup->wlan_stop = wilc_wlan_stop;
2335         oup->wlan_add_to_tx_que = wilc_wlan_txq_add_net_pkt;
2336         oup->wlan_handle_tx_que = wilc_wlan_handle_txq;
2337         oup->wlan_handle_rx_que = wilc_wlan_handle_rxq;
2338         /* oup->wlan_handle_rx_isr = wilc_wlan_handle_isr; */
2339         oup->wlan_handle_rx_isr = wilc_handle_isr;
2340         oup->wlan_cleanup = wilc_wlan_cleanup;
2341         oup->wlan_cfg_set = wilc_wlan_cfg_set;
2342         oup->wlan_cfg_get = wilc_wlan_cfg_get;
2343         oup->wlan_cfg_get_value = wilc_wlan_cfg_get_val;
2344
2345         /*Bug3959: transmitting mgmt frames received from host*/
2346         #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P)
2347         oup->wlan_add_mgmt_to_tx_que = wilc_wlan_txq_add_mgmt_pkt;
2348
2349         #ifdef WILC_FULLY_HOSTING_AP
2350         oup->wlan_add_data_to_tx_que = wilc_FH_wlan_txq_add_net_pkt;
2351         #endif
2352         #endif
2353
2354         if (!init_chip()) {
2355                 /* EIO  5 */
2356                 ret = -5;
2357                 goto _fail_;
2358         }
2359 #ifdef  TCP_ACK_FILTER
2360         Init_TCP_tracking();
2361 #endif
2362
2363 #if defined(PLAT_RK3026_TCHIP) /* AMR : 0422 RK3026 Crash issue */
2364         if (!g_wilc_initialized)
2365                 custom_unlock_bus(g_mac_open);
2366 #endif
2367
2368         return 1;
2369
2370 _fail_:
2371
2372 #if (defined WILC_PREALLOC_AT_BOOT)
2373
2374 #else
2375   #ifdef MEMORY_STATIC
2376         if (g_wlan.rx_buffer) {
2377                 g_wlan.os_func.os_free(g_wlan.rx_buffer);
2378                 g_wlan.rx_buffer = NULL;
2379         }
2380   #endif
2381         if (g_wlan.tx_buffer) {
2382                 g_wlan.os_func.os_free(g_wlan.tx_buffer);
2383                 g_wlan.tx_buffer = NULL;
2384         }
2385 #endif
2386
2387 #if defined(PLAT_RK3026_TCHIP) /* AMR : 0422 RK3026 Crash issue */
2388         if (!g_wilc_initialized)
2389                 custom_unlock_bus(g_mac_open);
2390 #endif
2391
2392         return ret;
2393
2394 }
2395
2396 #define BIT31 (1 << 31)
2397 WILC_Uint16 Set_machw_change_vir_if(WILC_Bool bValue)
2398 {
2399         WILC_Uint16 ret;
2400         WILC_Uint32 reg;
2401
2402         /*Reset WILC_CHANGING_VIR_IF register to allow adding futrue keys to CE H/W*/
2403         (&g_wlan)->os_func.os_enter_cs((&g_wlan)->hif_lock);
2404         ret = (&g_wlan)->hif_func.hif_read_reg(WILC_CHANGING_VIR_IF, &reg);
2405         if (!ret) {
2406                 PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n");
2407         }
2408
2409         if (bValue == WILC_TRUE) {
2410                 reg |= (BIT31);
2411         } else {
2412                 reg &= ~(BIT31);
2413         }
2414
2415         ret = (&g_wlan)->hif_func.hif_write_reg(WILC_CHANGING_VIR_IF, reg);
2416
2417         if (!ret) {
2418                 PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n");
2419         }
2420         (&g_wlan)->os_func.os_leave_cs((&g_wlan)->hif_lock);
2421
2422         return ret;
2423 }
2424
2425 #ifdef WILC_FULLY_HOSTING_AP
2426 wilc_wlan_dev_t *Get_wlan_context(WILC_Uint16 *pu16size)
2427 {
2428         *pu16size = sizeof(wilc_wlan_dev_t);
2429         return &g_wlan;
2430 }
2431 #endif
2432