]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/wilc1000/wilc_wlan.c
0843ccf47422550f26d17b7aef23e4fe6ae52e52
[karo-tx-linux.git] / drivers / staging / wilc1000 / wilc_wlan.c
1 #include "wilc_wlan_if.h"
2 #include "wilc_wlan.h"
3 #include "wilc_wfi_netdevice.h"
4 #include "wilc_wlan_cfg.h"
5
6 static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ;
7
8 /* FIXME: replace with dev_debug() */
9 static void wilc_debug(u32 flag, char *fmt, ...)
10 {
11         char buf[256];
12         va_list args;
13
14         if (flag & dbgflag) {
15                 va_start(args, fmt);
16                 vsprintf(buf, fmt, args);
17                 va_end(args);
18         }
19 }
20
21 static CHIP_PS_STATE_T chip_ps_state = CHIP_WAKEDUP;
22
23 static inline void acquire_bus(struct wilc *wilc, BUS_ACQUIRE_T acquire)
24 {
25         mutex_lock(&wilc->hif_cs);
26         if (acquire == ACQUIRE_AND_WAKEUP)
27                 chip_wakeup(wilc);
28 }
29
30 static inline void release_bus(struct wilc *wilc, BUS_RELEASE_T release)
31 {
32         if (release == RELEASE_ALLOW_SLEEP)
33                 chip_allow_sleep(wilc);
34         mutex_unlock(&wilc->hif_cs);
35 }
36
37 static void wilc_wlan_txq_remove(struct wilc *wilc, struct txq_entry_t *tqe)
38 {
39
40         if (tqe == wilc->txq_head) {
41                 wilc->txq_head = tqe->next;
42                 if (wilc->txq_head)
43                         wilc->txq_head->prev = NULL;
44         } else if (tqe == wilc->txq_tail) {
45                 wilc->txq_tail = (tqe->prev);
46                 if (wilc->txq_tail)
47                         wilc->txq_tail->next = NULL;
48         } else {
49                 tqe->prev->next = tqe->next;
50                 tqe->next->prev = tqe->prev;
51         }
52         wilc->txq_entries -= 1;
53 }
54
55 static struct txq_entry_t *
56 wilc_wlan_txq_remove_from_head(struct net_device *dev)
57 {
58         struct txq_entry_t *tqe;
59         unsigned long flags;
60         struct wilc_vif *vif;
61         struct wilc *wilc;
62
63         vif = netdev_priv(dev);
64         wilc = vif->wilc;
65
66         spin_lock_irqsave(&wilc->txq_spinlock, flags);
67         if (wilc->txq_head) {
68                 tqe = wilc->txq_head;
69                 wilc->txq_head = tqe->next;
70                 if (wilc->txq_head)
71                         wilc->txq_head->prev = NULL;
72
73                 wilc->txq_entries -= 1;
74         } else {
75                 tqe = NULL;
76         }
77         spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
78         return tqe;
79 }
80
81 static void wilc_wlan_txq_add_to_tail(struct net_device *dev,
82                                       struct txq_entry_t *tqe)
83 {
84         unsigned long flags;
85         struct wilc_vif *vif;
86         struct wilc *wilc;
87
88         vif = netdev_priv(dev);
89         wilc = vif->wilc;
90
91         spin_lock_irqsave(&wilc->txq_spinlock, flags);
92
93         if (!wilc->txq_head) {
94                 tqe->next = NULL;
95                 tqe->prev = NULL;
96                 wilc->txq_head = tqe;
97                 wilc->txq_tail = tqe;
98         } else {
99                 tqe->next = NULL;
100                 tqe->prev = wilc->txq_tail;
101                 wilc->txq_tail->next = tqe;
102                 wilc->txq_tail = tqe;
103         }
104         wilc->txq_entries += 1;
105
106         spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
107
108         up(&wilc->txq_event);
109 }
110
111 static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif,
112                                      struct txq_entry_t *tqe)
113 {
114         unsigned long flags;
115         struct wilc *wilc = vif->wilc;
116
117         if (wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs,
118                                     CFG_PKTS_TIMEOUT))
119                 return -1;
120
121         spin_lock_irqsave(&wilc->txq_spinlock, flags);
122
123         if (!wilc->txq_head) {
124                 tqe->next = NULL;
125                 tqe->prev = NULL;
126                 wilc->txq_head = tqe;
127                 wilc->txq_tail = tqe;
128         } else {
129                 tqe->next = wilc->txq_head;
130                 tqe->prev = NULL;
131                 wilc->txq_head->prev = tqe;
132                 wilc->txq_head = tqe;
133         }
134         wilc->txq_entries += 1;
135
136         spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
137         up(&wilc->txq_add_to_head_cs);
138         up(&wilc->txq_event);
139
140         return 0;
141 }
142
143 struct ack_session_info;
144 struct ack_session_info {
145         u32 seq_num;
146         u32 bigger_ack_num;
147         u16 src_port;
148         u16 dst_port;
149         u16 status;
150 };
151
152 struct pending_acks_info {
153         u32 ack_num;
154         u32 session_index;
155         struct txq_entry_t  *txqe;
156 };
157
158
159 #define NOT_TCP_ACK                     (-1)
160
161 #define MAX_TCP_SESSION         25
162 #define MAX_PENDING_ACKS                256
163 static struct ack_session_info ack_session_info[2 * MAX_TCP_SESSION];
164 static struct pending_acks_info pending_acks_info[MAX_PENDING_ACKS];
165
166 static u32 pending_base;
167 static u32 tcp_session;
168 static u32 pending_acks;
169
170 static inline int init_tcp_tracking(void)
171 {
172         return 0;
173 }
174
175 static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq)
176 {
177         if (tcp_session < 2 * MAX_TCP_SESSION) {
178                 ack_session_info[tcp_session].seq_num = seq;
179                 ack_session_info[tcp_session].bigger_ack_num = 0;
180                 ack_session_info[tcp_session].src_port = src_prt;
181                 ack_session_info[tcp_session].dst_port = dst_prt;
182                 tcp_session++;
183         }
184         return 0;
185 }
186
187 static inline int update_tcp_session(u32 index, u32 ack)
188 {
189         if (index < 2 * MAX_TCP_SESSION &&
190             ack > ack_session_info[index].bigger_ack_num)
191                 ack_session_info[index].bigger_ack_num = ack;
192         return 0;
193 }
194
195 static inline int add_tcp_pending_ack(u32 ack, u32 session_index,
196                                       struct txq_entry_t *txqe)
197 {
198         if (pending_base + pending_acks < MAX_PENDING_ACKS) {
199                 pending_acks_info[pending_base + pending_acks].ack_num = ack;
200                 pending_acks_info[pending_base + pending_acks].txqe = txqe;
201                 pending_acks_info[pending_base + pending_acks].session_index = session_index;
202                 txqe->tcp_pending_ack_idx = pending_base + pending_acks;
203                 pending_acks++;
204         }
205         return 0;
206 }
207
208 static inline void tcp_process(struct net_device *dev, struct txq_entry_t *tqe)
209 {
210         u8 *eth_hdr_ptr;
211         u8 *buffer = tqe->buffer;
212         unsigned short h_proto;
213         int i;
214         unsigned long flags;
215         struct wilc_vif *vif;
216         struct wilc *wilc;
217
218         vif = netdev_priv(dev);
219         wilc = vif->wilc;
220
221         spin_lock_irqsave(&wilc->txq_spinlock, flags);
222
223         eth_hdr_ptr = &buffer[0];
224         h_proto = ntohs(*((unsigned short *)&eth_hdr_ptr[12]));
225         if (h_proto == ETH_P_IP) {
226                 u8 *ip_hdr_ptr;
227                 u8 protocol;
228
229                 ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN];
230                 protocol = ip_hdr_ptr[9];
231
232                 if (protocol == 0x06) {
233                         u8 *tcp_hdr_ptr;
234                         u32 IHL, total_length, data_offset;
235
236                         tcp_hdr_ptr = &ip_hdr_ptr[IP_HDR_LEN];
237                         IHL = (ip_hdr_ptr[0] & 0xf) << 2;
238                         total_length = ((u32)ip_hdr_ptr[2] << 8) +
239                                         (u32)ip_hdr_ptr[3];
240                         data_offset = ((u32)tcp_hdr_ptr[12] & 0xf0) >> 2;
241                         if (total_length == (IHL + data_offset)) {
242                                 u32 seq_no, ack_no;
243
244                                 seq_no = ((u32)tcp_hdr_ptr[4] << 24) +
245                                          ((u32)tcp_hdr_ptr[5] << 16) +
246                                          ((u32)tcp_hdr_ptr[6] << 8) +
247                                          (u32)tcp_hdr_ptr[7];
248
249                                 ack_no = ((u32)tcp_hdr_ptr[8] << 24) +
250                                          ((u32)tcp_hdr_ptr[9] << 16) +
251                                          ((u32)tcp_hdr_ptr[10] << 8) +
252                                          (u32)tcp_hdr_ptr[11];
253
254                                 for (i = 0; i < tcp_session; i++) {
255                                         if (i < 2 * MAX_TCP_SESSION &&
256                                             ack_session_info[i].seq_num == seq_no) {
257                                                 update_tcp_session(i, ack_no);
258                                                 break;
259                                         }
260                                 }
261                                 if (i == tcp_session)
262                                         add_tcp_session(0, 0, seq_no);
263
264                                 add_tcp_pending_ack(ack_no, i, tqe);
265                         }
266
267                 }
268         }
269         spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
270 }
271
272 static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev)
273 {
274         struct wilc_vif *vif;
275         struct wilc *wilc;
276         u32 i = 0;
277         u32 dropped = 0;
278
279         vif = netdev_priv(dev);
280         wilc = vif->wilc;
281
282         spin_lock_irqsave(&wilc->txq_spinlock, wilc->txq_spinlock_flags);
283         for (i = pending_base; i < (pending_base + pending_acks); i++) {
284                 if (i >= MAX_PENDING_ACKS ||
285                     pending_acks_info[i].session_index >= 2 * MAX_TCP_SESSION)
286                         break;
287                 if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) {
288                         struct txq_entry_t *tqe;
289
290                         tqe = pending_acks_info[i].txqe;
291                         if (tqe) {
292                                 wilc_wlan_txq_remove(wilc, tqe);
293                                 tqe->status = 1;
294                                 if (tqe->tx_complete_func)
295                                         tqe->tx_complete_func(tqe->priv,
296                                                               tqe->status);
297                                 kfree(tqe);
298                                 dropped++;
299                         }
300                 }
301         }
302         pending_acks = 0;
303         tcp_session = 0;
304
305         if (pending_base == 0)
306                 pending_base = MAX_TCP_SESSION;
307         else
308                 pending_base = 0;
309
310         spin_unlock_irqrestore(&wilc->txq_spinlock, wilc->txq_spinlock_flags);
311
312         while (dropped > 0) {
313                 wilc_lock_timeout(wilc, &wilc->txq_event, 1);
314                 dropped--;
315         }
316
317         return 1;
318 }
319
320 static bool enabled;
321
322 void wilc_enable_tcp_ack_filter(bool value)
323 {
324         enabled = value;
325 }
326
327 static bool is_tcp_ack_filter_enabled(void)
328 {
329         return enabled;
330 }
331
332 static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
333                                      u32 buffer_size)
334 {
335         struct txq_entry_t *tqe;
336         struct wilc *wilc = vif->wilc;
337
338         netdev_dbg(vif->ndev, "Adding config packet ...\n");
339         if (wilc->quit) {
340                 netdev_dbg(vif->ndev, "Return due to clear function\n");
341                 up(&wilc->cfg_event);
342                 return 0;
343         }
344
345         tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
346         if (!tqe) {
347                 netdev_err(vif->ndev, "Failed to allocate memory\n");
348                 return 0;
349         }
350
351         tqe->type = WILC_CFG_PKT;
352         tqe->buffer = buffer;
353         tqe->buffer_size = buffer_size;
354         tqe->tx_complete_func = NULL;
355         tqe->priv = NULL;
356         tqe->tcp_pending_ack_idx = NOT_TCP_ACK;
357
358         if (wilc_wlan_txq_add_to_head(vif, tqe))
359                 return 0;
360         return 1;
361 }
362
363 int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
364                               u32 buffer_size, wilc_tx_complete_func_t func)
365 {
366         struct txq_entry_t *tqe;
367         struct wilc_vif *vif = netdev_priv(dev);
368         struct wilc *wilc;
369
370         wilc = vif->wilc;
371
372         if (wilc->quit)
373                 return 0;
374
375         tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
376
377         if (!tqe)
378                 return 0;
379         tqe->type = WILC_NET_PKT;
380         tqe->buffer = buffer;
381         tqe->buffer_size = buffer_size;
382         tqe->tx_complete_func = func;
383         tqe->priv = priv;
384
385         tqe->tcp_pending_ack_idx = NOT_TCP_ACK;
386         if (is_tcp_ack_filter_enabled())
387                 tcp_process(dev, tqe);
388         wilc_wlan_txq_add_to_tail(dev, tqe);
389         return wilc->txq_entries;
390 }
391
392 int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
393                                u32 buffer_size, wilc_tx_complete_func_t func)
394 {
395         struct txq_entry_t *tqe;
396         struct wilc_vif *vif = netdev_priv(dev);
397         struct wilc *wilc;
398
399         wilc = vif->wilc;
400
401         if (wilc->quit)
402                 return 0;
403
404         tqe = kmalloc(sizeof(*tqe), GFP_KERNEL);
405
406         if (!tqe)
407                 return 0;
408         tqe->type = WILC_MGMT_PKT;
409         tqe->buffer = buffer;
410         tqe->buffer_size = buffer_size;
411         tqe->tx_complete_func = func;
412         tqe->priv = priv;
413         tqe->tcp_pending_ack_idx = NOT_TCP_ACK;
414         wilc_wlan_txq_add_to_tail(dev, tqe);
415         return 1;
416 }
417
418 static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc)
419 {
420         struct txq_entry_t *tqe;
421         unsigned long flags;
422
423         spin_lock_irqsave(&wilc->txq_spinlock, flags);
424
425         tqe = wilc->txq_head;
426
427         spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
428
429         return tqe;
430 }
431
432 static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc,
433                                                   struct txq_entry_t *tqe)
434 {
435         unsigned long flags;
436
437         spin_lock_irqsave(&wilc->txq_spinlock, flags);
438
439         tqe = tqe->next;
440         spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
441
442         return tqe;
443 }
444
445 static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe)
446 {
447
448         if (wilc->quit)
449                 return 0;
450
451         mutex_lock(&wilc->rxq_cs);
452         if (!wilc->rxq_head) {
453                 rqe->next = NULL;
454                 wilc->rxq_head = rqe;
455                 wilc->rxq_tail = rqe;
456         } else {
457                 wilc->rxq_tail->next = rqe;
458                 rqe->next = NULL;
459                 wilc->rxq_tail = rqe;
460         }
461         wilc->rxq_entries += 1;
462         mutex_unlock(&wilc->rxq_cs);
463         return wilc->rxq_entries;
464 }
465
466 static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
467 {
468
469         if (wilc->rxq_head) {
470                 struct rxq_entry_t *rqe;
471
472                 mutex_lock(&wilc->rxq_cs);
473                 rqe = wilc->rxq_head;
474                 wilc->rxq_head = wilc->rxq_head->next;
475                 wilc->rxq_entries -= 1;
476                 mutex_unlock(&wilc->rxq_cs);
477                 return rqe;
478         }
479         return NULL;
480 }
481
482 void chip_allow_sleep(struct wilc *wilc)
483 {
484         u32 reg = 0;
485
486         wilc->hif_func->hif_read_reg(wilc, 0xf0, &reg);
487
488         wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0));
489         wilc->hif_func->hif_write_reg(wilc, 0xfa, 0);
490 }
491 EXPORT_SYMBOL_GPL(chip_allow_sleep);
492
493 void chip_wakeup(struct wilc *wilc)
494 {
495         u32 reg, clk_status_reg, trials = 0;
496
497         if ((wilc->io_type & 0x1) == HIF_SPI) {
498                 do {
499                         wilc->hif_func->hif_read_reg(wilc, 1, &reg);
500                         wilc->hif_func->hif_write_reg(wilc, 1, reg | BIT(1));
501                         wilc->hif_func->hif_write_reg(wilc, 1, reg & ~BIT(1));
502
503                         do {
504                                 usleep_range(2 * 1000, 2 * 1000);
505                                 if ((wilc_get_chipid(wilc, true) == 0))
506                                         wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
507
508                         } while ((wilc_get_chipid(wilc, true) == 0) && ((++trials % 3) == 0));
509
510                 } while (wilc_get_chipid(wilc, true) == 0);
511         } else if ((wilc->io_type & 0x1) == HIF_SDIO)    {
512                 wilc->hif_func->hif_write_reg(wilc, 0xfa, 1);
513                 udelay(200);
514                 wilc->hif_func->hif_read_reg(wilc, 0xf0, &reg);
515                 do {
516                         wilc->hif_func->hif_write_reg(wilc, 0xf0,
517                                                       reg | BIT(0));
518                         wilc->hif_func->hif_read_reg(wilc, 0xf1,
519                                                      &clk_status_reg);
520
521                         while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) {
522                                 usleep_range(2 * 1000, 2 * 1000);
523
524                                 wilc->hif_func->hif_read_reg(wilc, 0xf1,
525                                                              &clk_status_reg);
526
527                                 if ((clk_status_reg & 0x1) == 0)
528                                         wilc_debug(N_ERR, "clocks still OFF. Wake up failed\n");
529                         }
530                         if ((clk_status_reg & 0x1) == 0) {
531                                 wilc->hif_func->hif_write_reg(wilc, 0xf0,
532                                                               reg & (~BIT(0)));
533                         }
534                 } while ((clk_status_reg & 0x1) == 0);
535         }
536
537         if (chip_ps_state == CHIP_SLEEPING_MANUAL) {
538                 if (wilc_get_chipid(wilc, false) < 0x1002b0) {
539                         u32 val32;
540
541                         wilc->hif_func->hif_read_reg(wilc, 0x1e1c, &val32);
542                         val32 |= BIT(6);
543                         wilc->hif_func->hif_write_reg(wilc, 0x1e1c, val32);
544
545                         wilc->hif_func->hif_read_reg(wilc, 0x1e9c, &val32);
546                         val32 |= BIT(6);
547                         wilc->hif_func->hif_write_reg(wilc, 0x1e9c, val32);
548                 }
549         }
550         chip_ps_state = CHIP_WAKEDUP;
551 }
552 EXPORT_SYMBOL_GPL(chip_wakeup);
553
554 void wilc_chip_sleep_manually(struct wilc *wilc)
555 {
556         if (chip_ps_state != CHIP_WAKEDUP)
557                 return;
558         acquire_bus(wilc, ACQUIRE_ONLY);
559
560         chip_allow_sleep(wilc);
561         wilc->hif_func->hif_write_reg(wilc, 0x10a8, 1);
562
563         chip_ps_state = CHIP_SLEEPING_MANUAL;
564         release_bus(wilc, RELEASE_ONLY);
565 }
566 EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually);
567
568 void host_wakeup_notify(struct wilc *wilc)
569 {
570         acquire_bus(wilc, ACQUIRE_ONLY);
571         wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1);
572         release_bus(wilc, RELEASE_ONLY);
573 }
574 EXPORT_SYMBOL_GPL(host_wakeup_notify);
575
576 void host_sleep_notify(struct wilc *wilc)
577 {
578         acquire_bus(wilc, ACQUIRE_ONLY);
579         wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1);
580         release_bus(wilc, RELEASE_ONLY);
581 }
582 EXPORT_SYMBOL_GPL(host_sleep_notify);
583
584 int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
585 {
586         int i, entries = 0;
587         u32 sum;
588         u32 reg;
589         u8 *txb;
590         u32 offset = 0;
591         int vmm_sz = 0;
592         struct txq_entry_t *tqe;
593         int ret = 0;
594         int counter;
595         int timeout;
596         u32 vmm_table[WILC_VMM_TBL_SIZE];
597         struct wilc_vif *vif;
598         struct wilc *wilc;
599
600         vif = netdev_priv(dev);
601         wilc = vif->wilc;
602
603         txb = wilc->tx_buffer;
604         wilc->txq_exit = 0;
605         do {
606                 if (wilc->quit)
607                         break;
608
609                 wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs,
610                                         CFG_PKTS_TIMEOUT);
611                 wilc_wlan_txq_filter_dup_tcp_ack(dev);
612                 tqe = wilc_wlan_txq_get_first(wilc);
613                 i = 0;
614                 sum = 0;
615                 do {
616                         if (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) {
617                                 if (tqe->type == WILC_CFG_PKT)
618                                         vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET;
619
620                                 else if (tqe->type == WILC_NET_PKT)
621                                         vmm_sz = ETH_ETHERNET_HDR_OFFSET;
622
623                                 else
624                                         vmm_sz = HOST_HDR_OFFSET;
625
626                                 vmm_sz += tqe->buffer_size;
627
628                                 if (vmm_sz & 0x3)
629                                         vmm_sz = (vmm_sz + 4) & ~0x3;
630
631                                 if ((sum + vmm_sz) > LINUX_TX_SIZE)
632                                         break;
633
634                                 vmm_table[i] = vmm_sz / 4;
635                                 if (tqe->type == WILC_CFG_PKT)
636                                         vmm_table[i] |= BIT(10);
637                                 vmm_table[i] = cpu_to_le32(vmm_table[i]);
638
639                                 i++;
640                                 sum += vmm_sz;
641                                 tqe = wilc_wlan_txq_get_next(wilc, tqe);
642                         } else {
643                                 break;
644                         }
645                 } while (1);
646
647                 if (i == 0)
648                         break;
649                 else
650                         vmm_table[i] = 0x0;
651
652                 acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
653                 counter = 0;
654                 do {
655                         ret = wilc->hif_func->hif_read_reg(wilc,
656                                                            WILC_HOST_TX_CTRL,
657                                                            &reg);
658                         if (!ret)
659                                 break;
660
661                         if ((reg & 0x1) == 0) {
662                                 break;
663                         } else {
664                                 counter++;
665                                 if (counter > 200) {
666                                         counter = 0;
667                                         ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0);
668                                         break;
669                                 }
670                         }
671                 } while (!wilc->quit);
672
673                 if (!ret)
674                         goto _end_;
675
676                 timeout = 200;
677                 do {
678                         ret = wilc->hif_func->hif_block_tx(wilc, WILC_VMM_TBL_RX_SHADOW_BASE, (u8 *)vmm_table, ((i + 1) * 4));
679                         if (!ret)
680                                 break;
681
682                         ret = wilc->hif_func->hif_write_reg(wilc,
683                                                             WILC_HOST_VMM_CTL,
684                                                             0x2);
685                         if (!ret)
686                                 break;
687
688                         do {
689                                 ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, &reg);
690                                 if (!ret)
691                                         break;
692                                 if ((reg >> 2) & 0x1) {
693                                         entries = ((reg >> 3) & 0x3f);
694                                         break;
695                                 } else {
696                                         release_bus(wilc, RELEASE_ALLOW_SLEEP);
697                                 }
698                         } while (--timeout);
699                         if (timeout <= 0) {
700                                 ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0);
701                                 break;
702                         }
703
704                         if (!ret)
705                                 break;
706
707                         if (entries == 0) {
708                                 ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, &reg);
709                                 if (!ret)
710                                         break;
711                                 reg &= ~BIT(0);
712                                 ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg);
713                                 if (!ret)
714                                         break;
715                                 break;
716                         } else {
717                                 break;
718                         }
719                 } while (1);
720
721                 if (!ret)
722                         goto _end_;
723
724                 if (entries == 0) {
725                         ret = WILC_TX_ERR_NO_BUF;
726                         goto _end_;
727                 }
728
729                 release_bus(wilc, RELEASE_ALLOW_SLEEP);
730
731                 offset = 0;
732                 i = 0;
733                 do {
734                         tqe = wilc_wlan_txq_remove_from_head(dev);
735                         if (tqe && (vmm_table[i] != 0)) {
736                                 u32 header, buffer_offset;
737
738                                 vmm_table[i] = cpu_to_le32(vmm_table[i]);
739                                 vmm_sz = (vmm_table[i] & 0x3ff);
740                                 vmm_sz *= 4;
741                                 header = (tqe->type << 31) |
742                                          (tqe->buffer_size << 15) |
743                                          vmm_sz;
744                                 if (tqe->type == WILC_MGMT_PKT)
745                                         header |= BIT(30);
746                                 else
747                                         header &= ~BIT(30);
748
749                                 header = cpu_to_le32(header);
750                                 memcpy(&txb[offset], &header, 4);
751                                 if (tqe->type == WILC_CFG_PKT) {
752                                         buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
753                                 } else if (tqe->type == WILC_NET_PKT) {
754                                         char *bssid = ((struct tx_complete_data *)(tqe->priv))->bssid;
755
756                                         buffer_offset = ETH_ETHERNET_HDR_OFFSET;
757                                         memcpy(&txb[offset + 4], bssid, 6);
758                                 } else {
759                                         buffer_offset = HOST_HDR_OFFSET;
760                                 }
761
762                                 memcpy(&txb[offset + buffer_offset],
763                                        tqe->buffer, tqe->buffer_size);
764                                 offset += vmm_sz;
765                                 i++;
766                                 tqe->status = 1;
767                                 if (tqe->tx_complete_func)
768                                         tqe->tx_complete_func(tqe->priv,
769                                                               tqe->status);
770                                 if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK &&
771                                     tqe->tcp_pending_ack_idx < MAX_PENDING_ACKS)
772                                         pending_acks_info[tqe->tcp_pending_ack_idx].txqe = NULL;
773                                 kfree(tqe);
774                         } else {
775                                 break;
776                         }
777                 } while (--entries);
778
779                 acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
780
781                 ret = wilc->hif_func->hif_clear_int_ext(wilc, ENABLE_TX_VMM);
782                 if (!ret)
783                         goto _end_;
784
785                 ret = wilc->hif_func->hif_block_tx_ext(wilc, 0, txb, offset);
786                 if (!ret)
787                         goto _end_;
788
789 _end_:
790
791                 release_bus(wilc, RELEASE_ALLOW_SLEEP);
792                 if (ret != 1)
793                         break;
794         } while (0);
795         up(&wilc->txq_add_to_head_cs);
796
797         wilc->txq_exit = 1;
798         *txq_count = wilc->txq_entries;
799         return ret;
800 }
801
802 static void wilc_wlan_handle_rxq(struct wilc *wilc)
803 {
804         int offset = 0, size;
805         u8 *buffer;
806         struct rxq_entry_t *rqe;
807
808         wilc->rxq_exit = 0;
809
810         do {
811                 if (wilc->quit) {
812                         up(&wilc->cfg_event);
813                         break;
814                 }
815                 rqe = wilc_wlan_rxq_remove(wilc);
816                 if (!rqe)
817                         break;
818
819                 buffer = rqe->buffer;
820                 size = rqe->buffer_size;
821                 offset = 0;
822
823                 do {
824                         u32 header;
825                         u32 pkt_len, pkt_offset, tp_len;
826                         int is_cfg_packet;
827
828                         memcpy(&header, &buffer[offset], 4);
829                         header = cpu_to_le32(header);
830
831                         is_cfg_packet = (header >> 31) & 0x1;
832                         pkt_offset = (header >> 22) & 0x1ff;
833                         tp_len = (header >> 11) & 0x7ff;
834                         pkt_len = header & 0x7ff;
835
836                         if (pkt_len == 0 || tp_len == 0)
837                                 break;
838
839                         #define IS_MANAGMEMENT                          0x100
840                         #define IS_MANAGMEMENT_CALLBACK                 0x080
841                         #define IS_MGMT_STATUS_SUCCES                   0x040
842
843                         if (pkt_offset & IS_MANAGMEMENT) {
844                                 pkt_offset &= ~(IS_MANAGMEMENT |
845                                                 IS_MANAGMEMENT_CALLBACK |
846                                                 IS_MGMT_STATUS_SUCCES);
847
848                                 WILC_WFI_mgmt_rx(wilc, &buffer[offset + HOST_HDR_OFFSET], pkt_len);
849                         } else {
850                                 if (!is_cfg_packet) {
851                                         if (pkt_len > 0) {
852                                                 wilc_frmw_to_linux(wilc,
853                                                               &buffer[offset],
854                                                               pkt_len,
855                                                               pkt_offset);
856                                         }
857                                 } else {
858                                         struct wilc_cfg_rsp rsp;
859
860                                         wilc_wlan_cfg_indicate_rx(wilc, &buffer[pkt_offset + offset], pkt_len, &rsp);
861                                         if (rsp.type == WILC_CFG_RSP) {
862                                                 if (wilc->cfg_seq_no == rsp.seq_no)
863                                                         up(&wilc->cfg_event);
864                                         } else if (rsp.type == WILC_CFG_RSP_STATUS) {
865                                                 wilc_mac_indicate(wilc, WILC_MAC_INDICATE_STATUS);
866
867                                         } else if (rsp.type == WILC_CFG_RSP_SCAN) {
868                                                 wilc_mac_indicate(wilc, WILC_MAC_INDICATE_SCAN);
869                                         }
870                                 }
871                         }
872                         offset += tp_len;
873                         if (offset >= size)
874                                 break;
875                 } while (1);
876                 kfree(rqe);
877         } while (1);
878
879         wilc->rxq_exit = 1;
880 }
881
882 static void wilc_unknown_isr_ext(struct wilc *wilc)
883 {
884         wilc->hif_func->hif_clear_int_ext(wilc, 0);
885 }
886
887 static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats)
888 {
889         int trials = 10;
890
891         wilc->hif_func->hif_clear_int_ext(wilc, PLL_INT_CLR);
892
893         if (wilc->io_type == HIF_SDIO)
894                 mdelay(WILC_PLL_TO_SDIO);
895         else
896                 mdelay(WILC_PLL_TO_SPI);
897
898         while (!(ISWILC1000(wilc_get_chipid(wilc, true)) && --trials))
899                 mdelay(1);
900 }
901
902 static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1)
903 {
904         wilc->hif_func->hif_clear_int_ext(wilc, SLEEP_INT_CLR);
905 }
906
907 static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
908 {
909         u32 offset = wilc->rx_buffer_offset;
910         u8 *buffer = NULL;
911         u32 size;
912         u32 retries = 0;
913         int ret = 0;
914         struct rxq_entry_t *rqe;
915
916         size = (int_status & 0x7fff) << 2;
917
918         while (!size && retries < 10) {
919                 wilc->hif_func->hif_read_size(wilc, &size);
920                 size = (size & 0x7fff) << 2;
921                 retries++;
922         }
923
924         if (size > 0) {
925                 if (LINUX_RX_SIZE - offset < size)
926                         offset = 0;
927
928                 if (wilc->rx_buffer)
929                         buffer = &wilc->rx_buffer[offset];
930                 else
931                         goto _end_;
932
933                 wilc->hif_func->hif_clear_int_ext(wilc,
934                                               DATA_INT_CLR | ENABLE_RX_VMM);
935                 ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size);
936
937                 if (!ret)
938                         goto _end_;
939 _end_:
940                 if (ret) {
941                         offset += size;
942                         wilc->rx_buffer_offset = offset;
943                         rqe = kmalloc(sizeof(*rqe), GFP_KERNEL);
944                         if (rqe) {
945                                 rqe->buffer = buffer;
946                                 rqe->buffer_size = size;
947                                 wilc_wlan_rxq_add(wilc, rqe);
948                         }
949                 }
950         }
951         wilc_wlan_handle_rxq(wilc);
952 }
953
954 void wilc_handle_isr(struct wilc *wilc)
955 {
956         u32 int_status;
957
958         acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
959         wilc->hif_func->hif_read_int(wilc, &int_status);
960
961         if (int_status & PLL_INT_EXT)
962                 wilc_pllupdate_isr_ext(wilc, int_status);
963
964         if (int_status & DATA_INT_EXT)
965                 wilc_wlan_handle_isr_ext(wilc, int_status);
966
967         if (int_status & SLEEP_INT_EXT)
968                 wilc_sleeptimer_isr_ext(wilc, int_status);
969
970         if (!(int_status & (ALL_INT_EXT)))
971                 wilc_unknown_isr_ext(wilc);
972
973         release_bus(wilc, RELEASE_ALLOW_SLEEP);
974 }
975 EXPORT_SYMBOL_GPL(wilc_handle_isr);
976
977 int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
978                                 u32 buffer_size)
979 {
980         u32 offset;
981         u32 addr, size, size2, blksz;
982         u8 *dma_buffer;
983         int ret = 0;
984
985         blksz = BIT(12);
986
987         dma_buffer = kmalloc(blksz, GFP_KERNEL);
988         if (!dma_buffer) {
989                 ret = -EIO;
990                 goto _fail_1;
991         }
992
993         offset = 0;
994         do {
995                 memcpy(&addr, &buffer[offset], 4);
996                 memcpy(&size, &buffer[offset + 4], 4);
997                 addr = cpu_to_le32(addr);
998                 size = cpu_to_le32(size);
999                 acquire_bus(wilc, ACQUIRE_ONLY);
1000                 offset += 8;
1001                 while (((int)size) && (offset < buffer_size)) {
1002                         if (size <= blksz)
1003                                 size2 = size;
1004                         else
1005                                 size2 = blksz;
1006
1007                         memcpy(dma_buffer, &buffer[offset], size2);
1008                         ret = wilc->hif_func->hif_block_tx(wilc, addr,
1009                                                            dma_buffer, size2);
1010                         if (!ret)
1011                                 break;
1012
1013                         addr += size2;
1014                         offset += size2;
1015                         size -= size2;
1016                 }
1017                 release_bus(wilc, RELEASE_ONLY);
1018
1019                 if (!ret) {
1020                         ret = -EIO;
1021                         goto _fail_;
1022                 }
1023         } while (offset < buffer_size);
1024
1025 _fail_:
1026
1027         kfree(dma_buffer);
1028
1029 _fail_1:
1030
1031         return (ret < 0) ? ret : 0;
1032 }
1033
1034 int wilc_wlan_start(struct wilc *wilc)
1035 {
1036         u32 reg = 0;
1037         int ret;
1038         u32 chipid;
1039
1040         if (wilc->io_type == HIF_SDIO) {
1041                 reg = 0;
1042                 reg |= BIT(3);
1043         } else if (wilc->io_type == HIF_SPI) {
1044                 reg = 1;
1045         }
1046         acquire_bus(wilc, ACQUIRE_ONLY);
1047         ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg);
1048         if (!ret) {
1049                 release_bus(wilc, RELEASE_ONLY);
1050                 ret = -EIO;
1051                 return ret;
1052         }
1053         reg = 0;
1054         if (wilc->io_type == HIF_SDIO && wilc->dev_irq_num)
1055                 reg |= WILC_HAVE_SDIO_IRQ_GPIO;
1056
1057 #ifdef WILC_DISABLE_PMU
1058 #else
1059         reg |= WILC_HAVE_USE_PMU;
1060 #endif
1061
1062 #ifdef WILC_SLEEP_CLK_SRC_XO
1063         reg |= WILC_HAVE_SLEEP_CLK_SRC_XO;
1064 #elif defined WILC_SLEEP_CLK_SRC_RTC
1065         reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC;
1066 #endif
1067
1068 #ifdef WILC_EXT_PA_INV_TX_RX
1069         reg |= WILC_HAVE_EXT_PA_INV_TX_RX;
1070 #endif
1071         reg |= WILC_HAVE_USE_IRQ_AS_HOST_WAKE;
1072         reg |= WILC_HAVE_LEGACY_RF_SETTINGS;
1073 #ifdef XTAL_24
1074         reg |= WILC_HAVE_XTAL_24;
1075 #endif
1076 #ifdef DISABLE_WILC_UART
1077         reg |= WILC_HAVE_DISABLE_WILC_UART;
1078 #endif
1079
1080         ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg);
1081         if (!ret) {
1082                 release_bus(wilc, RELEASE_ONLY);
1083                 ret = -EIO;
1084                 return ret;
1085         }
1086
1087         wilc->hif_func->hif_sync_ext(wilc, NUM_INT_EXT);
1088
1089         ret = wilc->hif_func->hif_read_reg(wilc, 0x1000, &chipid);
1090         if (!ret) {
1091                 release_bus(wilc, RELEASE_ONLY);
1092                 ret = -EIO;
1093                 return ret;
1094         }
1095
1096         wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
1097         if ((reg & BIT(10)) == BIT(10)) {
1098                 reg &= ~BIT(10);
1099                 wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1100                 wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
1101         }
1102
1103         reg |= BIT(10);
1104         ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1105         wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
1106         release_bus(wilc, RELEASE_ONLY);
1107
1108         return (ret < 0) ? ret : 0;
1109 }
1110
1111 int wilc_wlan_stop(struct wilc *wilc)
1112 {
1113         u32 reg = 0;
1114         int ret;
1115         u8 timeout = 10;
1116
1117         acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
1118
1119         ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
1120         if (!ret) {
1121                 release_bus(wilc, RELEASE_ALLOW_SLEEP);
1122                 return ret;
1123         }
1124
1125         reg &= ~BIT(10);
1126         ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1127         if (!ret) {
1128                 release_bus(wilc, RELEASE_ALLOW_SLEEP);
1129                 return ret;
1130         }
1131
1132         do {
1133                 ret = wilc->hif_func->hif_read_reg(wilc,
1134                                                    WILC_GLB_RESET_0, &reg);
1135                 if (!ret) {
1136                         release_bus(wilc, RELEASE_ALLOW_SLEEP);
1137                         return ret;
1138                 }
1139
1140                 if ((reg & BIT(10))) {
1141                         reg &= ~BIT(10);
1142                         ret = wilc->hif_func->hif_write_reg(wilc,
1143                                                             WILC_GLB_RESET_0,
1144                                                             reg);
1145                         timeout--;
1146                 } else {
1147                         ret = wilc->hif_func->hif_read_reg(wilc,
1148                                                            WILC_GLB_RESET_0,
1149                                                            &reg);
1150                         if (!ret) {
1151                                 release_bus(wilc, RELEASE_ALLOW_SLEEP);
1152                                 return ret;
1153                         }
1154                         break;
1155                 }
1156
1157         } while (timeout);
1158         reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) | BIT(26) |
1159                BIT(29) | BIT(30) | BIT(31));
1160
1161         wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1162         reg = (u32)~BIT(10);
1163
1164         ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
1165
1166         release_bus(wilc, RELEASE_ALLOW_SLEEP);
1167
1168         return ret;
1169 }
1170
1171 void wilc_wlan_cleanup(struct net_device *dev)
1172 {
1173         struct txq_entry_t *tqe;
1174         struct rxq_entry_t *rqe;
1175         u32 reg = 0;
1176         int ret;
1177         struct wilc_vif *vif;
1178         struct wilc *wilc;
1179
1180         vif = netdev_priv(dev);
1181         wilc = vif->wilc;
1182
1183         wilc->quit = 1;
1184         do {
1185                 tqe = wilc_wlan_txq_remove_from_head(dev);
1186                 if (!tqe)
1187                         break;
1188                 if (tqe->tx_complete_func)
1189                         tqe->tx_complete_func(tqe->priv, 0);
1190                 kfree(tqe);
1191         } while (1);
1192
1193         do {
1194                 rqe = wilc_wlan_rxq_remove(wilc);
1195                 if (!rqe)
1196                         break;
1197                 kfree(rqe);
1198         } while (1);
1199
1200         kfree(wilc->rx_buffer);
1201         wilc->rx_buffer = NULL;
1202         kfree(wilc->tx_buffer);
1203         wilc->tx_buffer = NULL;
1204
1205         acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
1206
1207         ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, &reg);
1208         if (!ret)
1209                 release_bus(wilc, RELEASE_ALLOW_SLEEP);
1210
1211         ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0,
1212                                         (reg | ABORT_INT));
1213         if (!ret)
1214                 release_bus(wilc, RELEASE_ALLOW_SLEEP);
1215
1216         release_bus(wilc, RELEASE_ALLOW_SLEEP);
1217         wilc->hif_func->hif_deinit(NULL);
1218 }
1219
1220 static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type,
1221                                 u32 drv_handler)
1222 {
1223         struct wilc *wilc = vif->wilc;
1224         struct wilc_cfg_frame *cfg = &wilc->cfg_frame;
1225         int total_len = wilc->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE;
1226         int seq_no = wilc->cfg_seq_no % 256;
1227         int driver_handler = (u32)drv_handler;
1228
1229         if (type == WILC_CFG_SET)
1230                 cfg->wid_header[0] = 'W';
1231         else
1232                 cfg->wid_header[0] = 'Q';
1233         cfg->wid_header[1] = seq_no;
1234         cfg->wid_header[2] = (u8)total_len;
1235         cfg->wid_header[3] = (u8)(total_len >> 8);
1236         cfg->wid_header[4] = (u8)driver_handler;
1237         cfg->wid_header[5] = (u8)(driver_handler >> 8);
1238         cfg->wid_header[6] = (u8)(driver_handler >> 16);
1239         cfg->wid_header[7] = (u8)(driver_handler >> 24);
1240         wilc->cfg_seq_no = seq_no;
1241
1242         if (!wilc_wlan_txq_add_cfg_pkt(vif, &cfg->wid_header[0], total_len))
1243                 return -1;
1244
1245         return 0;
1246 }
1247
1248 int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer,
1249                       u32 buffer_size, int commit, u32 drv_handler)
1250 {
1251         u32 offset;
1252         int ret_size;
1253         struct wilc *wilc = vif->wilc;
1254
1255         if (wilc->cfg_frame_in_use)
1256                 return 0;
1257
1258         if (start)
1259                 wilc->cfg_frame_offset = 0;
1260
1261         offset = wilc->cfg_frame_offset;
1262         ret_size = wilc_wlan_cfg_set_wid(wilc->cfg_frame.frame, offset,
1263                                          (u16)wid, buffer, buffer_size);
1264         offset += ret_size;
1265         wilc->cfg_frame_offset = offset;
1266
1267         if (commit) {
1268                 netdev_dbg(vif->ndev,
1269                            "[WILC]PACKET Commit with sequence number %d\n",
1270                            wilc->cfg_seq_no);
1271                 netdev_dbg(vif->ndev, "Processing cfg_set()\n");
1272                 wilc->cfg_frame_in_use = 1;
1273
1274                 if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler))
1275                         ret_size = 0;
1276
1277                 if (wilc_lock_timeout(wilc, &wilc->cfg_event,
1278                                             CFG_PKTS_TIMEOUT)) {
1279                         netdev_dbg(vif->ndev, "Set Timed Out\n");
1280                         ret_size = 0;
1281                 }
1282                 wilc->cfg_frame_in_use = 0;
1283                 wilc->cfg_frame_offset = 0;
1284                 wilc->cfg_seq_no += 1;
1285         }
1286
1287         return ret_size;
1288 }
1289
1290 int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit,
1291                       u32 drv_handler)
1292 {
1293         u32 offset;
1294         int ret_size;
1295         struct wilc *wilc = vif->wilc;
1296
1297         if (wilc->cfg_frame_in_use)
1298                 return 0;
1299
1300         if (start)
1301                 wilc->cfg_frame_offset = 0;
1302
1303         offset = wilc->cfg_frame_offset;
1304         ret_size = wilc_wlan_cfg_get_wid(wilc->cfg_frame.frame, offset,
1305                                          (u16)wid);
1306         offset += ret_size;
1307         wilc->cfg_frame_offset = offset;
1308
1309         if (commit) {
1310                 wilc->cfg_frame_in_use = 1;
1311
1312                 if (wilc_wlan_cfg_commit(vif, WILC_CFG_QUERY, drv_handler))
1313                         ret_size = 0;
1314
1315                 if (wilc_lock_timeout(wilc, &wilc->cfg_event,
1316                                             CFG_PKTS_TIMEOUT)) {
1317                         netdev_dbg(vif->ndev, "Get Timed Out\n");
1318                         ret_size = 0;
1319                 }
1320                 wilc->cfg_frame_in_use = 0;
1321                 wilc->cfg_frame_offset = 0;
1322                 wilc->cfg_seq_no += 1;
1323         }
1324
1325         return ret_size;
1326 }
1327
1328 int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size)
1329 {
1330         int ret;
1331
1332         ret = wilc_wlan_cfg_get_wid_value((u16)wid, buffer, buffer_size);
1333
1334         return ret;
1335 }
1336
1337 int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
1338                          u32 count, u32 drv)
1339 {
1340         int i;
1341         int ret = 0;
1342
1343         if (mode == GET_CFG) {
1344                 for (i = 0; i < count; i++) {
1345                         if (!wilc_wlan_cfg_get(vif, !i,
1346                                                wids[i].id,
1347                                                (i == count - 1),
1348                                                drv)) {
1349                                 ret = -ETIMEDOUT;
1350                                 break;
1351                         }
1352                 }
1353                 for (i = 0; i < count; i++) {
1354                         wids[i].size = wilc_wlan_cfg_get_val(wids[i].id,
1355                                                              wids[i].val,
1356                                                              wids[i].size);
1357                 }
1358         } else if (mode == SET_CFG) {
1359                 for (i = 0; i < count; i++) {
1360                         if (!wilc_wlan_cfg_set(vif, !i,
1361                                                wids[i].id,
1362                                                wids[i].val,
1363                                                wids[i].size,
1364                                                (i == count - 1),
1365                                                drv)) {
1366                                 ret = -ETIMEDOUT;
1367                                 break;
1368                         }
1369                 }
1370         }
1371
1372         return ret;
1373 }
1374
1375 static u32 init_chip(struct net_device *dev)
1376 {
1377         u32 chipid;
1378         u32 reg, ret = 0;
1379         struct wilc_vif *vif;
1380         struct wilc *wilc;
1381
1382         vif = netdev_priv(dev);
1383         wilc = vif->wilc;
1384
1385         acquire_bus(wilc, ACQUIRE_ONLY);
1386
1387         chipid = wilc_get_chipid(wilc, true);
1388
1389         if ((chipid & 0xfff) != 0xa0) {
1390                 ret = wilc->hif_func->hif_read_reg(wilc, 0x1118, &reg);
1391                 if (!ret) {
1392                         netdev_err(dev, "fail read reg 0x1118\n");
1393                         return ret;
1394                 }
1395                 reg |= BIT(0);
1396                 ret = wilc->hif_func->hif_write_reg(wilc, 0x1118, reg);
1397                 if (!ret) {
1398                         netdev_err(dev, "fail write reg 0x1118\n");
1399                         return ret;
1400                 }
1401                 ret = wilc->hif_func->hif_write_reg(wilc, 0xc0000, 0x71);
1402                 if (!ret) {
1403                         netdev_err(dev, "fail write reg 0xc0000\n");
1404                         return ret;
1405                 }
1406         }
1407
1408         release_bus(wilc, RELEASE_ONLY);
1409
1410         return ret;
1411 }
1412
1413 u32 wilc_get_chipid(struct wilc *wilc, bool update)
1414 {
1415         static u32 chipid;
1416         u32 tempchipid = 0;
1417         u32 rfrevid = 0;
1418
1419         if (chipid == 0 || update) {
1420                 wilc->hif_func->hif_read_reg(wilc, 0x1000, &tempchipid);
1421                 wilc->hif_func->hif_read_reg(wilc, 0x13f4, &rfrevid);
1422                 if (!ISWILC1000(tempchipid)) {
1423                         chipid = 0;
1424                         return chipid;
1425                 }
1426                 if (tempchipid == 0x1002a0) {
1427                         if (rfrevid != 0x1)
1428                                 tempchipid = 0x1002a1;
1429                 } else if (tempchipid == 0x1002b0) {
1430                         if (rfrevid == 0x4)
1431                                 tempchipid = 0x1002b1;
1432                         else if (rfrevid != 0x3)
1433                                 tempchipid = 0x1002b2;
1434                 }
1435
1436                 chipid = tempchipid;
1437         }
1438         return chipid;
1439 }
1440
1441 int wilc_wlan_init(struct net_device *dev)
1442 {
1443         int ret = 0;
1444         struct wilc_vif *vif = netdev_priv(dev);
1445         struct wilc *wilc;
1446
1447         wilc = vif->wilc;
1448
1449         wilc->quit = 0;
1450
1451         if (!wilc->hif_func->hif_init(wilc, false)) {
1452                 ret = -EIO;
1453                 goto _fail_;
1454         }
1455
1456         if (!wilc_wlan_cfg_init(wilc_debug)) {
1457                 ret = -ENOBUFS;
1458                 goto _fail_;
1459         }
1460
1461         if (!wilc->tx_buffer)
1462                 wilc->tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL);
1463
1464         if (!wilc->tx_buffer) {
1465                 ret = -ENOBUFS;
1466                 goto _fail_;
1467         }
1468
1469         if (!wilc->rx_buffer)
1470                 wilc->rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL);
1471
1472         if (!wilc->rx_buffer) {
1473                 ret = -ENOBUFS;
1474                 goto _fail_;
1475         }
1476
1477         if (!init_chip(dev)) {
1478                 ret = -EIO;
1479                 goto _fail_;
1480         }
1481         init_tcp_tracking();
1482
1483         return 1;
1484
1485 _fail_:
1486
1487         kfree(wilc->rx_buffer);
1488         wilc->rx_buffer = NULL;
1489         kfree(wilc->tx_buffer);
1490         wilc->tx_buffer = NULL;
1491
1492         return ret;
1493 }