staging: wilc1000: change the type of wilc1000_initialized
[deliverable/linux.git] / drivers / staging / wilc1000 / linux_wlan.c
CommitLineData
c5c77ba1
JK
1#include "wilc_wfi_cfgoperations.h"
2#include "linux_wlan_common.h"
3#include "wilc_wlan_if.h"
4#include "wilc_wlan.h"
c5c77ba1
JK
5
6#include <linux/slab.h>
7#include <linux/sched.h>
8#include <linux/delay.h>
9#include <linux/workqueue.h>
10#include <linux/interrupt.h>
11#include <linux/irq.h>
f1a99830 12#include <linux/gpio.h>
c5c77ba1
JK
13
14#include <linux/kthread.h>
15#include <linux/firmware.h>
16#include <linux/delay.h>
17
18#include <linux/init.h>
19#include <linux/netdevice.h>
c5c77ba1 20#include <linux/inetdevice.h>
c5c77ba1
JK
21#include <linux/etherdevice.h>
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/skbuff.h>
25
26#include <linux/version.h>
27#include <linux/semaphore.h>
28
29#ifdef WILC_SDIO
30#include "linux_wlan_sdio.h"
31#else
32#include "linux_wlan_spi.h"
33#endif
34
c5c77ba1
JK
35#if defined(CUSTOMER_PLATFORM)
36/*
37 TODO : Write power control functions as customer platform.
38 */
39#else
40
41 #define _linux_wlan_device_power_on() {}
42 #define _linux_wlan_device_power_off() {}
43
44 #define _linux_wlan_device_detection() {}
45 #define _linux_wlan_device_removal() {}
46#endif
47
72ed4dc7 48extern bool g_obtainingIP;
72ed4dc7 49extern u16 Set_machw_change_vir_if(bool bValue);
c5c77ba1 50extern void resolve_disconnect_aberration(void *drvHandler);
63d03e47 51extern u8 gau8MulticastMacAddrList[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
f61c5aff 52void wilc1000_wlan_deinit(struct wilc *nic);
da711eb6 53extern struct timer_list hDuringIpTimer;
c5c77ba1
JK
54
55static int linux_wlan_device_power(int on_off)
56{
57 PRINT_D(INIT_DBG, "linux_wlan_device_power.. (%d)\n", on_off);
58
59 if (on_off) {
60 _linux_wlan_device_power_on();
61 } else {
62 _linux_wlan_device_power_off();
63 }
64
65 return 0;
66}
67
68static int linux_wlan_device_detection(int on_off)
69{
70 PRINT_D(INIT_DBG, "linux_wlan_device_detection.. (%d)\n", on_off);
71
72#ifdef WILC_SDIO
73 if (on_off) {
74 _linux_wlan_device_detection();
75 } else {
76 _linux_wlan_device_removal();
77 }
78#endif
79
80 return 0;
81}
82
c5c77ba1
JK
83static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr);
84
85static struct notifier_block g_dev_notifier = {
86 .notifier_call = dev_state_ev_handler
87};
c5c77ba1 88
c5c77ba1
JK
89#define IRQ_WAIT 1
90#define IRQ_NO_WAIT 0
91/*
92 * to sync between mac_close and module exit.
93 * don't initialize or de-initialize from init/deinitlocks
94 * to be initialized from module wilc_netdev_init and
95 * deinitialized from mdoule_exit
96 */
97static struct semaphore close_exit_sync;
c5c77ba1 98
f61c5aff
TC
99static int wlan_deinit_locks(struct wilc *nic);
100static void wlan_deinitialize_threads(struct wilc *nic);
fbc2fe16
CL
101extern void WILC_WFI_monitor_rx(u8 *buff, u32 size);
102extern void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size);
c5c77ba1 103
c5c77ba1 104static void linux_wlan_tx_complete(void *priv, int status);
c5c77ba1
JK
105static int mac_init_fn(struct net_device *ndev);
106int mac_xmit(struct sk_buff *skb, struct net_device *dev);
107int mac_open(struct net_device *ndev);
108int mac_close(struct net_device *ndev);
109static struct net_device_stats *mac_stats(struct net_device *dev);
110static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd);
111static void wilc_set_multicast_list(struct net_device *dev);
112
c5c77ba1
JK
113/*
114 * for now - in frmw_to_linux there should be private data to be passed to it
115 * and this data should be pointer to net device
116 */
f61c5aff 117struct wilc *g_linux_wlan;
72ed4dc7 118bool bEnablePS = true;
c5c77ba1 119
c5c77ba1
JK
120static const struct net_device_ops wilc_netdev_ops = {
121 .ndo_init = mac_init_fn,
122 .ndo_open = mac_open,
123 .ndo_stop = mac_close,
124 .ndo_start_xmit = mac_xmit,
125 .ndo_do_ioctl = mac_ioctl,
126 .ndo_get_stats = mac_stats,
127 .ndo_set_rx_mode = wilc_set_multicast_list,
128
129};
c5c77ba1 130
c5c77ba1
JK
131static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr)
132{
133 struct in_ifaddr *dev_iface = (struct in_ifaddr *)ptr;
2726887c 134 struct wilc_priv *priv;
441dc609 135 struct host_if_drv *pstrWFIDrv;
c5c77ba1 136 struct net_device *dev;
63d03e47 137 u8 *pIP_Add_buff;
c5c77ba1 138 perInterface_wlan_t *nic;
63d03e47 139 u8 null_ip[4] = {0};
c5c77ba1
JK
140 char wlan_dev_name[5] = "wlan0";
141
142 if (dev_iface == NULL || dev_iface->ifa_dev == NULL || dev_iface->ifa_dev->dev == NULL) {
143 PRINT_D(GENERIC_DBG, "dev_iface = NULL\n");
144 return NOTIFY_DONE;
145 }
146
147 if ((memcmp(dev_iface->ifa_label, "wlan0", 5)) && (memcmp(dev_iface->ifa_label, "p2p0", 4))) {
148 PRINT_D(GENERIC_DBG, "Interface is neither WLAN0 nor P2P0\n");
149 return NOTIFY_DONE;
150 }
151
152 dev = (struct net_device *)dev_iface->ifa_dev->dev;
153 if (dev->ieee80211_ptr == NULL || dev->ieee80211_ptr->wiphy == NULL) {
154 PRINT_D(GENERIC_DBG, "No Wireless registerd\n");
155 return NOTIFY_DONE;
156 }
157 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
158 if (priv == NULL) {
159 PRINT_D(GENERIC_DBG, "No Wireless Priv\n");
160 return NOTIFY_DONE;
161 }
441dc609 162 pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
c5c77ba1
JK
163 nic = netdev_priv(dev);
164 if (nic == NULL || pstrWFIDrv == NULL) {
165 PRINT_D(GENERIC_DBG, "No Wireless Priv\n");
166 return NOTIFY_DONE;
167 }
168
169 PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler +++\n"); /* tony */
170
171 switch (event) {
172 case NETDEV_UP:
173 PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_UP %p\n", dev); /* tony */
174
175 PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n");
176
c5c77ba1
JK
177 /*If we are in station mode or client mode*/
178 if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) {
179 pstrWFIDrv->IFC_UP = 1;
72ed4dc7 180 g_obtainingIP = false;
8972d0fe 181 del_timer(&hDuringIpTimer);
c5c77ba1
JK
182 PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n");
183 }
184
5a66bf20 185 if (bEnablePS)
218dc407 186 host_int_set_power_mgmt(pstrWFIDrv, 1, 0);
c5c77ba1
JK
187
188 PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label);
189
190 pIP_Add_buff = (char *) (&(dev_iface->ifa_address));
17aacd43 191 PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
218dc407 192 host_int_setup_ipaddress(pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
c5c77ba1
JK
193
194 break;
195
196 case NETDEV_DOWN:
197 PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_DOWN %p\n", dev); /* tony */
198
199 PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Released ===============\n\n");
200 if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) {
201 pstrWFIDrv->IFC_UP = 0;
72ed4dc7 202 g_obtainingIP = false;
c5c77ba1
JK
203 }
204
205 if (memcmp(dev_iface->ifa_label, wlan_dev_name, 5) == 0)
218dc407 206 host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
c5c77ba1
JK
207
208 resolve_disconnect_aberration(pstrWFIDrv);
209
c5c77ba1
JK
210 PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label);
211
212 pIP_Add_buff = null_ip;
17aacd43 213 PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
c5c77ba1 214
218dc407 215 host_int_setup_ipaddress(pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
c5c77ba1
JK
216
217 break;
218
219 default:
220 PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler event=default\n"); /* tony */
221 PRINT_INFO(GENERIC_DBG, "[%s] unknown dev event: %lu\n", dev_iface->ifa_label, event);
222
223 break;
224 }
225
226 return NOTIFY_DONE;
227
228}
c5c77ba1 229
c5c77ba1
JK
230#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
231static irqreturn_t isr_uh_routine(int irq, void *user_data)
232{
c5c77ba1
JK
233 PRINT_D(INT_DBG, "Interrupt received UH\n");
234
235 /*While mac is closing cacncel the handling of any interrupts received*/
236 if (g_linux_wlan->close) {
237 PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n");
c5c77ba1 238 return IRQ_HANDLED;
c5c77ba1 239 }
c5c77ba1 240 return IRQ_WAKE_THREAD;
c5c77ba1
JK
241}
242#endif
243
c5c77ba1
JK
244irqreturn_t isr_bh_routine(int irq, void *userdata)
245{
f61c5aff 246 struct wilc *nic;
8dfaafd6 247
f61c5aff 248 nic = (struct wilc *)userdata;
c5c77ba1
JK
249
250 /*While mac is closing cacncel the handling of any interrupts received*/
251 if (g_linux_wlan->close) {
252 PRINT_ER("Driver is CLOSING: Can't handle BH interrupt\n");
c5c77ba1 253 return IRQ_HANDLED;
c5c77ba1
JK
254 }
255
c5c77ba1 256 PRINT_D(INT_DBG, "Interrupt received BH\n");
46ca80cd 257 wilc_handle_isr();
c5c77ba1 258
c5c77ba1 259 return IRQ_HANDLED;
c5c77ba1 260}
c5c77ba1 261
c5c77ba1 262#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
f61c5aff 263static int init_irq(struct wilc *p_nic)
c5c77ba1
JK
264{
265 int ret = 0;
f61c5aff 266 struct wilc *nic = p_nic;
c5c77ba1
JK
267
268 /*initialize GPIO and register IRQ num*/
269 /*GPIO request*/
270 if ((gpio_request(GPIO_NUM, "WILC_INTR") == 0) &&
271 (gpio_direction_input(GPIO_NUM) == 0)) {
272#if defined(CUSTOMER_PLATFORM)
273/*
274 TODO : save the registerd irq number to the private wilc context in kernel.
275 *
276 * ex) nic->dev_irq_num = gpio_to_irq(GPIO_NUM);
277 */
c5c77ba1
JK
278#else
279 nic->dev_irq_num = gpio_to_irq(GPIO_NUM);
280#endif
281 } else {
282 ret = -1;
283 PRINT_ER("could not obtain gpio for WILC_INTR\n");
284 }
285
c5c77ba1
JK
286 if ((ret != -1) && (request_threaded_irq(nic->dev_irq_num, isr_uh_routine, isr_bh_routine,
287 IRQF_TRIGGER_LOW | IRQF_ONESHOT, /*Without IRQF_ONESHOT the uh will remain kicked in and dont gave a chance to bh*/
288 "WILC_IRQ", nic)) < 0) {
289
c5c77ba1
JK
290 PRINT_ER("Failed to request IRQ for GPIO: %d\n", GPIO_NUM);
291 ret = -1;
292 } else {
293
294 PRINT_D(INIT_DBG, "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n",
295 nic->dev_irq_num, GPIO_NUM);
296 }
297
298 return ret;
299}
300#endif
301
f61c5aff 302static void deinit_irq(struct wilc *nic)
c5c77ba1
JK
303{
304#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
305 /* Deintialize IRQ */
306 if (&nic->dev_irq_num != 0) {
307 free_irq(nic->dev_irq_num, g_linux_wlan);
308
309 gpio_free(GPIO_NUM);
310 }
311#endif
312}
313
c5c77ba1
JK
314/*
315 * OS functions
316 */
ef2b784c 317void linux_wlan_dbg(u8 *buff)
c5c77ba1
JK
318{
319 PRINT_D(INIT_DBG, "%d\n", *buff);
320}
321
b002e20d 322int linux_wlan_lock_timeout(void *vp, u32 timeout)
c5c77ba1
JK
323{
324 int error = -1;
8dfaafd6 325
c5c77ba1 326 PRINT_D(LOCK_DBG, "Locking %p\n", vp);
78174ada 327 if (vp != NULL)
c5c77ba1 328 error = down_timeout((struct semaphore *)vp, msecs_to_jiffies(timeout));
78174ada 329 else
c5c77ba1 330 PRINT_ER("Failed, mutex is NULL\n");
c5c77ba1
JK
331 return error;
332}
333
4417d3da 334void linux_wlan_mac_indicate(int flag)
c5c77ba1
JK
335{
336 /*I have to do it that way becuase there is no mean to encapsulate device pointer
337 * as a parameter
338 */
f61c5aff 339 struct wilc *pd = g_linux_wlan;
c5c77ba1
JK
340 int status;
341
342 if (flag == WILC_MAC_INDICATE_STATUS) {
894de36b 343 wilc_wlan_cfg_get_val(WID_STATUS, (unsigned char *)&status, 4);
c5c77ba1
JK
344 if (pd->mac_status == WILC_MAC_STATUS_INIT) {
345 pd->mac_status = status;
8990d856 346 up(&pd->sync_event);
c5c77ba1
JK
347 } else {
348 pd->mac_status = status;
349 }
350
351 if (pd->mac_status == WILC_MAC_STATUS_CONNECT) { /* Connect */
c5c77ba1
JK
352 }
353
354 } else if (flag == WILC_MAC_INDICATE_SCAN) {
355 PRINT_D(GENERIC_DBG, "Scanning ...\n");
356
357 }
358
359}
360
51e825f7 361struct net_device *GetIfHandler(u8 *pMacHeader)
c5c77ba1 362{
51e825f7 363 u8 *Bssid, *Bssid1;
c5c77ba1
JK
364 int i = 0;
365
366 Bssid = pMacHeader + 10;
367 Bssid1 = pMacHeader + 4;
368
369 for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
370 if (!memcmp(Bssid1, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN) ||
371 !memcmp(Bssid, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN)) {
372 return g_linux_wlan->strInterfaceInfo[i].wilc_netdev;
373 }
374 }
375 PRINT_INFO(INIT_DBG, "Invalide handle\n");
fc4b95d6 376 for (i = 0; i < 25; i++)
c5c77ba1 377 PRINT_D(INIT_DBG, "%02x ", pMacHeader[i]);
c5c77ba1
JK
378 Bssid = pMacHeader + 18;
379 Bssid1 = pMacHeader + 12;
380 for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
381 if (!memcmp(Bssid1, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN) ||
382 !memcmp(Bssid, g_linux_wlan->strInterfaceInfo[i].aBSSID, ETH_ALEN)) {
383 PRINT_D(INIT_DBG, "Ctx [%p]\n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
384 return g_linux_wlan->strInterfaceInfo[i].wilc_netdev;
385 }
386 }
387 PRINT_INFO(INIT_DBG, "\n");
388 return NULL;
389}
390
51e825f7 391int linux_wlan_set_bssid(struct net_device *wilc_netdev, u8 *pBSSID)
c5c77ba1
JK
392{
393 int i = 0;
394 int ret = -1;
395
396 PRINT_D(INIT_DBG, "set bssid on[%p]\n", wilc_netdev);
397 for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
398 if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev == wilc_netdev) {
399 PRINT_D(INIT_DBG, "set bssid [%x][%x][%x]\n", pBSSID[0], pBSSID[1], pBSSID[2]);
400 memcpy(g_linux_wlan->strInterfaceInfo[i].aBSSID, pBSSID, 6);
401 ret = 0;
402 break;
403 }
404 }
405 return ret;
406}
407
c5c77ba1
JK
408/*Function to get number of connected interfaces*/
409int linux_wlan_get_num_conn_ifcs(void)
410{
51e825f7
CL
411 u8 i = 0;
412 u8 null_bssid[6] = {0};
413 u8 ret_val = 0;
c5c77ba1
JK
414
415 for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
fc4b95d6 416 if (memcmp(g_linux_wlan->strInterfaceInfo[i].aBSSID, null_bssid, 6))
c5c77ba1 417 ret_val++;
c5c77ba1
JK
418 }
419 return ret_val;
420}
421
c5c77ba1
JK
422#define USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
423
424static int linux_wlan_txq_task(void *vp)
425{
426 int ret, txq_count;
427
428#if defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
429#define TX_BACKOFF_WEIGHT_INCR_STEP (1)
430#define TX_BACKOFF_WEIGHT_DECR_STEP (1)
431#define TX_BACKOFF_WEIGHT_MAX (7)
432#define TX_BACKOFF_WEIGHT_MIN (0)
433#define TX_BACKOFF_WEIGHT_UNIT_MS (10)
434 int backoff_weight = TX_BACKOFF_WEIGHT_MIN;
c5c77ba1
JK
435#endif
436
437 /* inform wilc1000_wlan_init that TXQ task is started. */
8990d856 438 up(&g_linux_wlan->txq_thread_started);
c5c77ba1
JK
439 while (1) {
440
441 PRINT_D(TX_DBG, "txq_task Taking a nap :)\n");
8990d856 442 down(&g_linux_wlan->txq_event);
c5c77ba1
JK
443 /* wait_for_completion(&pd->txq_event); */
444 PRINT_D(TX_DBG, "txq_task Who waked me up :$\n");
445
446 if (g_linux_wlan->close) {
447 /*Unlock the mutex in the mac_close function to indicate the exiting of the TX thread */
8990d856 448 up(&g_linux_wlan->txq_thread_started);
c5c77ba1
JK
449
450 while (!kthread_should_stop())
451 schedule();
452
453 PRINT_D(TX_DBG, "TX thread stopped\n");
454 break;
455 }
456 PRINT_D(TX_DBG, "txq_task handle the sending packet and let me go to sleep.\n");
457#if !defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
f590c4ce 458 ret = wilc_wlan_handle_txq(&txq_count);
c5c77ba1
JK
459#else
460 do {
f590c4ce 461 ret = wilc_wlan_handle_txq(&txq_count);
c5c77ba1
JK
462 if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD /* && netif_queue_stopped(pd->wilc_netdev)*/) {
463 PRINT_D(TX_DBG, "Waking up queue\n");
464 /* netif_wake_queue(pd->wilc_netdev); */
465 if (netif_queue_stopped(g_linux_wlan->strInterfaceInfo[0].wilc_netdev))
466 netif_wake_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev);
467 if (netif_queue_stopped(g_linux_wlan->strInterfaceInfo[1].wilc_netdev))
468 netif_wake_queue(g_linux_wlan->strInterfaceInfo[1].wilc_netdev);
469 }
470
471 if (ret == WILC_TX_ERR_NO_BUF) { /* failed to allocate buffers in chip. */
c5c77ba1
JK
472 do {
473 /* Back off from sending packets for some time. */
474 /* schedule_timeout will allow RX task to run and free buffers.*/
475 /* set_current_state(TASK_UNINTERRUPTIBLE); */
476 /* timeout = schedule_timeout(timeout); */
477 msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
478 } while (/*timeout*/ 0);
479 backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP;
fc4b95d6 480 if (backoff_weight > TX_BACKOFF_WEIGHT_MAX)
c5c77ba1 481 backoff_weight = TX_BACKOFF_WEIGHT_MAX;
c5c77ba1
JK
482 } else {
483 if (backoff_weight > TX_BACKOFF_WEIGHT_MIN) {
484 backoff_weight -= TX_BACKOFF_WEIGHT_DECR_STEP;
fc4b95d6 485 if (backoff_weight < TX_BACKOFF_WEIGHT_MIN)
c5c77ba1 486 backoff_weight = TX_BACKOFF_WEIGHT_MIN;
c5c77ba1
JK
487 }
488 }
489 /*TODO: drop packets after a certain time/number of retry count. */
490 } while (ret == WILC_TX_ERR_NO_BUF && !g_linux_wlan->close); /* retry sending packets if no more buffers in chip. */
491#endif
492 }
493 return 0;
494}
495
c0cadaa4 496void linux_wlan_rx_complete(void)
c5c77ba1
JK
497{
498 PRINT_D(RX_DBG, "RX completed\n");
499}
500
501int linux_wlan_get_firmware(perInterface_wlan_t *p_nic)
502{
503
504 perInterface_wlan_t *nic = p_nic;
505 int ret = 0;
506 const struct firmware *wilc_firmware;
507 char *firmware;
508
c5c77ba1
JK
509 if (nic->iftype == AP_MODE)
510 firmware = AP_FIRMWARE;
511 else if (nic->iftype == STATION_MODE)
512 firmware = STA_FIRMWARE;
513
c5c77ba1
JK
514 else {
515 PRINT_D(INIT_DBG, "Get P2P_CONCURRENCY_FIRMWARE\n");
516 firmware = P2P_CONCURRENCY_FIRMWARE;
517 }
518
c5c77ba1
JK
519 if (nic == NULL) {
520 PRINT_ER("NIC is NULL\n");
521 goto _fail_;
522 }
523
524 if (&nic->wilc_netdev->dev == NULL) {
525 PRINT_ER("&nic->wilc_netdev->dev is NULL\n");
526 goto _fail_;
527 }
528
c5c77ba1
JK
529 /* the firmare should be located in /lib/firmware in
530 * root file system with the name specified above */
531
532#ifdef WILC_SDIO
533 if (request_firmware(&wilc_firmware, firmware, &g_linux_wlan->wilc_sdio_func->dev) != 0) {
534 PRINT_ER("%s - firmare not available\n", firmware);
535 ret = -1;
536 goto _fail_;
537 }
538#else
539 if (request_firmware(&wilc_firmware, firmware, &g_linux_wlan->wilc_spidev->dev) != 0) {
540 PRINT_ER("%s - firmare not available\n", firmware);
541 ret = -1;
542 goto _fail_;
543 }
544#endif
c3ca6372 545 g_linux_wlan->wilc_firmware = wilc_firmware;
c5c77ba1
JK
546
547_fail_:
548
549 return ret;
550
551}
552
553#ifdef COMPLEMENT_BOOT
554int repeat_power_cycle(perInterface_wlan_t *nic);
555#endif
556
557static int linux_wlan_start_firmware(perInterface_wlan_t *nic)
558{
559
c5c77ba1
JK
560 int ret = 0;
561 /* start firmware */
562 PRINT_D(INIT_DBG, "Starting Firmware ...\n");
e42563bb 563 ret = wilc_wlan_start();
c5c77ba1
JK
564 if (ret < 0) {
565 PRINT_ER("Failed to start Firmware\n");
566 goto _fail_;
567 }
568
569 /* wait for mac ready */
570 PRINT_D(INIT_DBG, "Waiting for Firmware to get ready ...\n");
571 ret = linux_wlan_lock_timeout(&g_linux_wlan->sync_event, 5000);
572 if (ret) {
573#ifdef COMPLEMENT_BOOT
7a8fd841 574 static int timeout = 5;
c5c77ba1
JK
575
576 if (timeout--) {
577 PRINT_D(INIT_DBG, "repeat power cycle[%d]", timeout);
578 ret = repeat_power_cycle(nic);
579 } else {
580 timeout = 5;
581 ret = -1;
582 goto _fail_;
583 }
584#endif
585 PRINT_D(INIT_DBG, "Firmware start timed out");
586 goto _fail_;
587 }
588 /*
589 * TODO: Driver shouoldn't wait forever for firmware to get started -
590 * in case of timeout this should be handled properly
591 */
592 PRINT_D(INIT_DBG, "Firmware successfully started\n");
593
594_fail_:
595 return ret;
596}
f61c5aff 597static int linux_wlan_firmware_download(struct wilc *p_nic)
c5c77ba1
JK
598{
599
600 int ret = 0;
601
602 if (g_linux_wlan->wilc_firmware == NULL) {
603 PRINT_ER("Firmware buffer is NULL\n");
604 ret = -ENOBUFS;
605 goto _FAIL_;
606 }
607 /**
608 * do the firmware download
609 **/
610 PRINT_D(INIT_DBG, "Downloading Firmware ...\n");
63d7ab8e
GL
611 ret = wilc_wlan_firmware_download(g_linux_wlan->wilc_firmware->data,
612 g_linux_wlan->wilc_firmware->size);
fc4b95d6 613 if (ret < 0)
c5c77ba1 614 goto _FAIL_;
c5c77ba1
JK
615
616 /* Freeing FW buffer */
617 PRINT_D(INIT_DBG, "Freeing FW buffer ...\n");
618 PRINT_D(INIT_DBG, "Releasing firmware\n");
619 release_firmware(g_linux_wlan->wilc_firmware);
620 g_linux_wlan->wilc_firmware = NULL;
621
17aacd43 622 PRINT_D(INIT_DBG, "Download Succeeded\n");
c5c77ba1
JK
623
624_FAIL_:
625 return ret;
626}
627
c5c77ba1 628/* startup configuration - could be changed later using iconfig*/
f61c5aff 629static int linux_wlan_init_test_config(struct net_device *dev, struct wilc *p_nic)
c5c77ba1
JK
630{
631
632 unsigned char c_val[64];
c5c77ba1 633 unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xff};
c5c77ba1 634
2726887c 635 struct wilc_priv *priv;
441dc609 636 struct host_if_drv *pstrWFIDrv;
c5c77ba1
JK
637
638 PRINT_D(TX_DBG, "Start configuring Firmware\n");
c5c77ba1
JK
639 get_random_bytes(&mac_add[5], 1);
640 get_random_bytes(&mac_add[4], 1);
c5c77ba1 641 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
441dc609 642 pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
8a14330f 643 PRINT_D(INIT_DBG, "Host = %p\n", pstrWFIDrv);
c5c77ba1
JK
644
645 PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", mac_add[0], mac_add[1], mac_add[2], mac_add[3], mac_add[4], mac_add[5]);
21175ef7 646 wilc_get_chipid(0);
c5c77ba1 647
e5d57e91 648 *(int *)c_val = 1;
c5c77ba1 649
1028e5a4 650 if (!wilc_wlan_cfg_set(1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0))
c5c77ba1
JK
651 goto _fail_;
652
653 /*to tell fw that we are going to use PC test - WILC specific*/
654 c_val[0] = 0;
1028e5a4 655 if (!wilc_wlan_cfg_set(0, WID_PC_TEST_MODE, c_val, 1, 0, 0))
c5c77ba1
JK
656 goto _fail_;
657
658 c_val[0] = INFRASTRUCTURE;
1028e5a4 659 if (!wilc_wlan_cfg_set(0, WID_BSS_TYPE, c_val, 1, 0, 0))
c5c77ba1
JK
660 goto _fail_;
661
c3ca6372 662 /* c_val[0] = RATE_AUTO; */
c5c77ba1 663 c_val[0] = RATE_AUTO;
1028e5a4 664 if (!wilc_wlan_cfg_set(0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0))
c5c77ba1
JK
665 goto _fail_;
666
667 c_val[0] = G_MIXED_11B_2_MODE;
1028e5a4 668 if (!wilc_wlan_cfg_set(0, WID_11G_OPERATING_MODE, c_val, 1, 0, 0))
c5c77ba1
JK
669 goto _fail_;
670
671 c_val[0] = 1;
1028e5a4 672 if (!wilc_wlan_cfg_set(0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0))
c5c77ba1
JK
673 goto _fail_;
674
675 c_val[0] = G_SHORT_PREAMBLE;
1028e5a4 676 if (!wilc_wlan_cfg_set(0, WID_PREAMBLE, c_val, 1, 0, 0))
c5c77ba1
JK
677 goto _fail_;
678
679 c_val[0] = AUTO_PROT;
1028e5a4 680 if (!wilc_wlan_cfg_set(0, WID_11N_PROT_MECH, c_val, 1, 0, 0))
c5c77ba1
JK
681 goto _fail_;
682
c5c77ba1 683 c_val[0] = ACTIVE_SCAN;
1028e5a4 684 if (!wilc_wlan_cfg_set(0, WID_SCAN_TYPE, c_val, 1, 0, 0))
c5c77ba1
JK
685 goto _fail_;
686
687 c_val[0] = SITE_SURVEY_OFF;
1028e5a4 688 if (!wilc_wlan_cfg_set(0, WID_SITE_SURVEY, c_val, 1, 0, 0))
c5c77ba1
JK
689 goto _fail_;
690
691 *((int *)c_val) = 0xffff; /* Never use RTS-CTS */
1028e5a4 692 if (!wilc_wlan_cfg_set(0, WID_RTS_THRESHOLD, c_val, 2, 0, 0))
c5c77ba1
JK
693 goto _fail_;
694
695 *((int *)c_val) = 2346;
1028e5a4 696 if (!wilc_wlan_cfg_set(0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0))
c5c77ba1
JK
697 goto _fail_;
698
699 /* SSID */
700 /* -------------------------------------------------------------- */
701 /* Configuration : String with length less than 32 bytes */
702 /* Values to set : Any string with length less than 32 bytes */
703 /* ( In BSS Station Set SSID to "" (null string) */
704 /* to enable Broadcast SSID suppport ) */
705 /* -------------------------------------------------------------- */
c5c77ba1 706 c_val[0] = 0;
1028e5a4 707 if (!wilc_wlan_cfg_set(0, WID_BCAST_SSID, c_val, 1, 0, 0))
c5c77ba1
JK
708 goto _fail_;
709
710 c_val[0] = 1;
1028e5a4 711 if (!wilc_wlan_cfg_set(0, WID_QOS_ENABLE, c_val, 1, 0, 0))
c5c77ba1
JK
712 goto _fail_;
713
714 c_val[0] = NO_POWERSAVE;
1028e5a4 715 if (!wilc_wlan_cfg_set(0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0))
c5c77ba1
JK
716 goto _fail_;
717
718 c_val[0] = NO_ENCRYPT; /* NO_ENCRYPT, 0x79 */
1028e5a4 719 if (!wilc_wlan_cfg_set(0, WID_11I_MODE, c_val, 1, 0, 0))
c5c77ba1
JK
720 goto _fail_;
721
722 c_val[0] = OPEN_SYSTEM;
1028e5a4 723 if (!wilc_wlan_cfg_set(0, WID_AUTH_TYPE, c_val, 1, 0, 0))
c5c77ba1
JK
724 goto _fail_;
725
726 /* WEP/802 11I Configuration */
727 /* ------------------------------------------------------------------ */
728 /* Configuration : WEP Key */
729 /* Values (0x) : 5 byte for WEP40 and 13 bytes for WEP104 */
730 /* In case more than 5 bytes are passed on for WEP 40 */
731 /* only first 5 bytes will be used as the key */
732 /* ------------------------------------------------------------------ */
733
734 strcpy(c_val, "123456790abcdef1234567890");
1028e5a4 735 if (!wilc_wlan_cfg_set(0, WID_WEP_KEY_VALUE, c_val, (strlen(c_val) + 1), 0, 0))
c5c77ba1
JK
736 goto _fail_;
737
738 /* WEP/802 11I Configuration */
739 /* ------------------------------------------------------------------ */
740 /* Configuration : AES/TKIP WPA/RSNA Pre-Shared Key */
741 /* Values to set : Any string with length greater than equal to 8 bytes */
742 /* and less than 64 bytes */
743 /* ------------------------------------------------------------------ */
744 strcpy(c_val, "12345678");
1028e5a4 745 if (!wilc_wlan_cfg_set(0, WID_11I_PSK, c_val, (strlen(c_val)), 0, 0))
c5c77ba1
JK
746 goto _fail_;
747
748 /* IEEE802.1X Key Configuration */
749 /* ------------------------------------------------------------------ */
750 /* Configuration : Radius Server Access Secret Key */
751 /* Values to set : Any string with length greater than equal to 8 bytes */
752 /* and less than 65 bytes */
753 /* ------------------------------------------------------------------ */
754 strcpy(c_val, "password");
1028e5a4 755 if (!wilc_wlan_cfg_set(0, WID_1X_KEY, c_val, (strlen(c_val) + 1), 0, 0))
c5c77ba1
JK
756 goto _fail_;
757
758 /* IEEE802.1X Server Address Configuration */
759 /* ------------------------------------------------------------------ */
760 /* Configuration : Radius Server IP Address */
761 /* Values to set : Any valid IP Address */
762 /* ------------------------------------------------------------------ */
763 c_val[0] = 192;
764 c_val[1] = 168;
765 c_val[2] = 1;
766 c_val[3] = 112;
1028e5a4 767 if (!wilc_wlan_cfg_set(0, WID_1X_SERV_ADDR, c_val, 4, 0, 0))
c5c77ba1
JK
768 goto _fail_;
769
770 c_val[0] = 3;
1028e5a4 771 if (!wilc_wlan_cfg_set(0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0))
c5c77ba1
JK
772 goto _fail_;
773
774 c_val[0] = 3;
1028e5a4 775 if (!wilc_wlan_cfg_set(0, WID_DTIM_PERIOD, c_val, 1, 0, 0))
c5c77ba1
JK
776 goto _fail_;
777
778 c_val[0] = NORMAL_ACK;
1028e5a4 779 if (!wilc_wlan_cfg_set(0, WID_ACK_POLICY, c_val, 1, 0, 0))
c5c77ba1
JK
780 goto _fail_;
781
782 c_val[0] = 0;
1028e5a4 783 if (!wilc_wlan_cfg_set(0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1, 0, 0))
c5c77ba1
JK
784 goto _fail_;
785
786 c_val[0] = 48;
1028e5a4 787 if (!wilc_wlan_cfg_set(0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0, 0))
c5c77ba1
JK
788 goto _fail_;
789
790 c_val[0] = 28;
1028e5a4 791 if (!wilc_wlan_cfg_set(0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0, 0))
c5c77ba1
JK
792 goto _fail_;
793
794 /* Beacon Interval */
795 /* -------------------------------------------------------------------- */
796 /* Configuration : Sets the beacon interval value */
797 /* Values to set : Any 16-bit value */
798 /* -------------------------------------------------------------------- */
799
800 *((int *)c_val) = 100;
1028e5a4 801 if (!wilc_wlan_cfg_set(0, WID_BEACON_INTERVAL, c_val, 2, 0, 0))
c5c77ba1
JK
802 goto _fail_;
803
804 c_val[0] = REKEY_DISABLE;
1028e5a4 805 if (!wilc_wlan_cfg_set(0, WID_REKEY_POLICY, c_val, 1, 0, 0))
c5c77ba1
JK
806 goto _fail_;
807
808 /* Rekey Time (s) (Used only when the Rekey policy is 2 or 4) */
809 /* -------------------------------------------------------------------- */
810 /* Configuration : Sets the Rekey Time (s) */
811 /* Values to set : 32-bit value */
812 /* -------------------------------------------------------------------- */
813 *((int *)c_val) = 84600;
1028e5a4 814 if (!wilc_wlan_cfg_set(0, WID_REKEY_PERIOD, c_val, 4, 0, 0))
c5c77ba1
JK
815 goto _fail_;
816
817 /* Rekey Packet Count (in 1000s; used when Rekey Policy is 3) */
818 /* -------------------------------------------------------------------- */
819 /* Configuration : Sets Rekey Group Packet count */
820 /* Values to set : 32-bit Value */
821 /* -------------------------------------------------------------------- */
822 *((int *)c_val) = 500;
1028e5a4 823 if (!wilc_wlan_cfg_set(0, WID_REKEY_PACKET_COUNT, c_val, 4, 0, 0))
c5c77ba1
JK
824 goto _fail_;
825
826 c_val[0] = 1;
1028e5a4 827 if (!wilc_wlan_cfg_set(0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0, 0))
c5c77ba1
JK
828 goto _fail_;
829
830 c_val[0] = G_SELF_CTS_PROT;
1028e5a4 831 if (!wilc_wlan_cfg_set(0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0))
c5c77ba1
JK
832 goto _fail_;
833
834 c_val[0] = 1; /* Enable N */
1028e5a4 835 if (!wilc_wlan_cfg_set(0, WID_11N_ENABLE, c_val, 1, 0, 0))
c5c77ba1
JK
836 goto _fail_;
837
838 c_val[0] = HT_MIXED_MODE;
1028e5a4 839 if (!wilc_wlan_cfg_set(0, WID_11N_OPERATING_MODE, c_val, 1, 0, 0))
c5c77ba1
JK
840 goto _fail_;
841
842 c_val[0] = 1; /* TXOP Prot disable in N mode: No RTS-CTS on TX A-MPDUs to save air-time. */
1028e5a4 843 if (!wilc_wlan_cfg_set(0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0, 0))
c5c77ba1
JK
844 goto _fail_;
845
846 memcpy(c_val, mac_add, 6);
847
1028e5a4 848 if (!wilc_wlan_cfg_set(0, WID_MAC_ADDR, c_val, 6, 0, 0))
c5c77ba1
JK
849 goto _fail_;
850
851 /**
852 * AP only
853 **/
854 c_val[0] = DETECT_PROTECT_REPORT;
1028e5a4 855 if (!wilc_wlan_cfg_set(0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, 0, 0))
c5c77ba1
JK
856 goto _fail_;
857
858 c_val[0] = RTS_CTS_NONHT_PROT;
1028e5a4 859 if (!wilc_wlan_cfg_set(0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0))
c5c77ba1
JK
860 goto _fail_;
861
862 c_val[0] = 0;
1028e5a4 863 if (!wilc_wlan_cfg_set(0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0, 0))
c5c77ba1
JK
864 goto _fail_;
865
866 c_val[0] = MIMO_MODE;
1028e5a4 867 if (!wilc_wlan_cfg_set(0, WID_11N_SMPS_MODE, c_val, 1, 0, 0))
c5c77ba1
JK
868 goto _fail_;
869
870 c_val[0] = 7;
1028e5a4 871 if (!wilc_wlan_cfg_set(0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0, 0))
c5c77ba1
JK
872 goto _fail_;
873
874 c_val[0] = 1; /* Enable N with immediate block ack. */
1028e5a4 875 if (!wilc_wlan_cfg_set(0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, 1, 1))
c5c77ba1
JK
876 goto _fail_;
877
878 return 0;
879
880_fail_:
881 return -1;
882}
883
c5c77ba1 884/**************************/
f61c5aff 885void wilc1000_wlan_deinit(struct wilc *nic)
c5c77ba1 886{
080f11bb 887 if (g_linux_wlan->initialized) {
c5c77ba1
JK
888 printk("Deinitializing wilc1000 ...\n");
889
890 if (nic == NULL) {
891 PRINT_ER("nic is NULL\n");
892 return;
893 }
894
895#if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31)
896 /* johnny : remove */
897 PRINT_D(INIT_DBG, "skip wilc_bus_set_default_speed\n");
898#else
899 wilc_bus_set_default_speed();
900#endif
901
902 PRINT_D(INIT_DBG, "Disabling IRQ\n");
d59177cb 903#ifdef WILC_SDIO
5e150b52 904 mutex_lock(&g_linux_wlan->hif_cs);
c5c77ba1 905 disable_sdio_interrupt();
5e150b52 906 mutex_unlock(&g_linux_wlan->hif_cs);
d59177cb 907#endif
fc4b95d6 908 if (&g_linux_wlan->txq_event != NULL)
8990d856 909 up(&g_linux_wlan->txq_event);
c5c77ba1 910
c5c77ba1
JK
911 PRINT_D(INIT_DBG, "Deinitializing Threads\n");
912 wlan_deinitialize_threads(nic);
913
914 PRINT_D(INIT_DBG, "Deinitializing IRQ\n");
915 deinit_irq(g_linux_wlan);
916
8cec741e 917 wilc_wlan_stop();
c5c77ba1
JK
918
919 PRINT_D(INIT_DBG, "Deinitializing WILC Wlan\n");
a17e2ec1 920 wilc_wlan_cleanup();
c5c77ba1
JK
921#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
922 #if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31)
923 PRINT_D(INIT_DBG, "Disabling IRQ 2\n");
924
5e150b52 925 mutex_lock(&g_linux_wlan->hif_cs);
c5c77ba1 926 disable_sdio_interrupt();
5e150b52 927 mutex_unlock(&g_linux_wlan->hif_cs);
c5c77ba1
JK
928 #endif
929#endif
930
931 /*De-Initialize locks*/
932 PRINT_D(INIT_DBG, "Deinitializing Locks\n");
933 wlan_deinit_locks(g_linux_wlan);
934
935 /* announce that wilc1000 is not initialized */
080f11bb 936 g_linux_wlan->initialized = false;
c5c77ba1
JK
937
938 PRINT_D(INIT_DBG, "wilc1000 deinitialization Done\n");
939
940 } else {
941 PRINT_D(INIT_DBG, "wilc1000 is not initialized\n");
942 }
c5c77ba1
JK
943}
944
f61c5aff 945int wlan_init_locks(struct wilc *p_nic)
c5c77ba1
JK
946{
947
948 PRINT_D(INIT_DBG, "Initializing Locks ...\n");
949
19a33489
GKH
950 mutex_init(&g_linux_wlan->hif_cs);
951 mutex_init(&g_linux_wlan->rxq_cs);
c5c77ba1 952
b25a37b9 953 spin_lock_init(&g_linux_wlan->txq_spinlock);
642768ee 954 sema_init(&g_linux_wlan->txq_add_to_head_cs, 1);
c5c77ba1 955
642768ee 956 sema_init(&g_linux_wlan->txq_event, 0);
c5c77ba1 957
642768ee
GKH
958 sema_init(&g_linux_wlan->cfg_event, 0);
959 sema_init(&g_linux_wlan->sync_event, 0);
c5c77ba1 960
642768ee 961 sema_init(&g_linux_wlan->txq_thread_started, 0);
c5c77ba1 962
c5c77ba1
JK
963 return 0;
964}
965
f61c5aff 966static int wlan_deinit_locks(struct wilc *nic)
c5c77ba1
JK
967{
968 PRINT_D(INIT_DBG, "De-Initializing Locks\n");
969
970 if (&g_linux_wlan->hif_cs != NULL)
19a33489 971 mutex_destroy(&g_linux_wlan->hif_cs);
c5c77ba1
JK
972
973 if (&g_linux_wlan->rxq_cs != NULL)
19a33489 974 mutex_destroy(&g_linux_wlan->rxq_cs);
c5c77ba1 975
c5c77ba1
JK
976 return 0;
977}
f61c5aff 978void linux_to_wlan(wilc_wlan_inp_t *nwi, struct wilc *nic)
c5c77ba1
JK
979{
980
981 PRINT_D(INIT_DBG, "Linux to Wlan services ...\n");
982
c5c77ba1 983 nwi->os_context.os_private = (void *)nic;
c5c77ba1 984
c5c77ba1
JK
985#ifdef WILC_SDIO
986 nwi->io_func.io_type = HIF_SDIO;
987 nwi->io_func.io_init = linux_sdio_init;
988 nwi->io_func.io_deinit = linux_sdio_deinit;
989 nwi->io_func.u.sdio.sdio_cmd52 = linux_sdio_cmd52;
990 nwi->io_func.u.sdio.sdio_cmd53 = linux_sdio_cmd53;
991 nwi->io_func.u.sdio.sdio_set_max_speed = linux_sdio_set_max_speed;
992 nwi->io_func.u.sdio.sdio_set_default_speed = linux_sdio_set_default_speed;
993#else
994 nwi->io_func.io_type = HIF_SPI;
995 nwi->io_func.io_init = linux_spi_init;
996 nwi->io_func.io_deinit = linux_spi_deinit;
997 nwi->io_func.u.spi.spi_tx = linux_spi_write;
998 nwi->io_func.u.spi.spi_rx = linux_spi_read;
999 nwi->io_func.u.spi.spi_trx = linux_spi_write_read;
1000 nwi->io_func.u.spi.spi_max_speed = linux_spi_set_max_speed;
1001#endif
c5c77ba1
JK
1002}
1003
1004int wlan_initialize_threads(perInterface_wlan_t *nic)
1005{
1006
1007 int ret = 0;
8dfaafd6 1008
c5c77ba1
JK
1009 PRINT_D(INIT_DBG, "Initializing Threads ...\n");
1010
c5c77ba1
JK
1011 /* create tx task */
1012 PRINT_D(INIT_DBG, "Creating kthread for transmission\n");
1013 g_linux_wlan->txq_thread = kthread_run(linux_wlan_txq_task, (void *)g_linux_wlan, "K_TXQ_TASK");
0e04f3f3 1014 if (g_linux_wlan->txq_thread == NULL) {
c5c77ba1
JK
1015 PRINT_ER("couldn't create TXQ thread\n");
1016 ret = -ENOBUFS;
1017 goto _fail_2;
1018 }
c5c77ba1 1019 /* wait for TXQ task to start. */
8990d856 1020 down(&g_linux_wlan->txq_thread_started);
c5c77ba1
JK
1021
1022 return 0;
1023
1024_fail_2:
1025 /*De-Initialize 2nd thread*/
1026 g_linux_wlan->close = 1;
c5c77ba1 1027
c5c77ba1
JK
1028 g_linux_wlan->close = 0;
1029 return ret;
1030}
1031
f61c5aff 1032static void wlan_deinitialize_threads(struct wilc *nic)
c5c77ba1
JK
1033{
1034
1035 g_linux_wlan->close = 1;
1036 PRINT_D(INIT_DBG, "Deinitializing Threads\n");
c5c77ba1 1037
c5c77ba1 1038 if (&g_linux_wlan->txq_event != NULL)
8990d856 1039 up(&g_linux_wlan->txq_event);
c5c77ba1 1040
c5c77ba1
JK
1041 if (g_linux_wlan->txq_thread != NULL) {
1042 kthread_stop(g_linux_wlan->txq_thread);
1043 g_linux_wlan->txq_thread = NULL;
1044 }
c5c77ba1
JK
1045}
1046
c5c77ba1
JK
1047#ifdef COMPLEMENT_BOOT
1048
1049extern volatile int probe;
51e825f7 1050extern u8 core_11b_ready(void);
c5c77ba1
JK
1051
1052#define READY_CHECK_THRESHOLD 30
1053extern void wilc_wlan_global_reset(void);
f61c5aff 1054u8 wilc1000_prepare_11b_core(wilc_wlan_inp_t *nwi, struct wilc *nic)
c5c77ba1 1055{
51e825f7 1056 u8 trials = 0;
8dfaafd6 1057
c5c77ba1
JK
1058 while ((core_11b_ready() && (READY_CHECK_THRESHOLD > (trials++)))) {
1059 PRINT_D(INIT_DBG, "11b core not ready yet: %u\n", trials);
a17e2ec1 1060 wilc_wlan_cleanup();
c5c77ba1
JK
1061 wilc_wlan_global_reset();
1062 sdio_unregister_driver(&wilc_bus);
1063
1064 linux_wlan_device_detection(0);
1065
1066 mdelay(100);
1067
1068 linux_wlan_device_detection(1);
1069
1070 sdio_register_driver(&wilc_bus);
1071
fc4b95d6 1072 while (!probe)
c5c77ba1 1073 msleep(100);
c5c77ba1
JK
1074 probe = 0;
1075 g_linux_wlan->wilc_sdio_func = local_sdio_func;
1076 linux_to_wlan(nwi, nic);
c9d4834d 1077 wilc_wlan_init(nwi);
c5c77ba1
JK
1078 }
1079
1080 if (READY_CHECK_THRESHOLD <= trials)
1081 return 1;
1082 else
1083 return 0;
1084
1085}
1086
1087int repeat_power_cycle(perInterface_wlan_t *nic)
1088{
1089 int ret = 0;
1090 wilc_wlan_inp_t nwi;
8dfaafd6 1091
c5c77ba1
JK
1092 sdio_unregister_driver(&wilc_bus);
1093
1094 linux_wlan_device_detection(0);
1095 linux_wlan_device_power(0);
1096 msleep(100);
1097 linux_wlan_device_power(1);
1098 msleep(80);
1099 linux_wlan_device_detection(1);
1100 msleep(20);
1101
1102 sdio_register_driver(&wilc_bus);
1103
1104 /* msleep(1000); */
fc4b95d6 1105 while (!probe)
c5c77ba1 1106 msleep(100);
c5c77ba1
JK
1107 probe = 0;
1108 g_linux_wlan->wilc_sdio_func = local_sdio_func;
1109 linux_to_wlan(&nwi, g_linux_wlan);
c9d4834d 1110 ret = wilc_wlan_init(&nwi);
c5c77ba1
JK
1111
1112 g_linux_wlan->mac_status = WILC_MAC_STATUS_INIT;
1113 #if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
1114 enable_sdio_interrupt();
1115 #endif
1116
1117 if (linux_wlan_get_firmware(nic)) {
17aacd43 1118 PRINT_ER("Can't get firmware\n");
c5c77ba1
JK
1119 ret = -1;
1120 goto __fail__;
1121 }
1122
1123 /*Download firmware*/
1124 ret = linux_wlan_firmware_download(g_linux_wlan);
1125 if (ret < 0) {
1126 PRINT_ER("Failed to download firmware\n");
1127 goto __fail__;
1128 }
1129 /* Start firmware*/
1130 ret = linux_wlan_start_firmware(nic);
fc4b95d6 1131 if (ret < 0)
c5c77ba1 1132 PRINT_ER("Failed to start firmware\n");
c5c77ba1
JK
1133__fail__:
1134 return ret;
1135}
1136#endif
1137
1138int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
1139{
1140 wilc_wlan_inp_t nwi;
c5c77ba1
JK
1141 perInterface_wlan_t *nic = p_nic;
1142 int ret = 0;
1143
080f11bb 1144 if (!g_linux_wlan->initialized) {
c5c77ba1
JK
1145 g_linux_wlan->mac_status = WILC_MAC_STATUS_INIT;
1146 g_linux_wlan->close = 0;
c5c77ba1
JK
1147
1148 wlan_init_locks(g_linux_wlan);
1149
c5c77ba1
JK
1150 linux_to_wlan(&nwi, g_linux_wlan);
1151
c9d4834d 1152 ret = wilc_wlan_init(&nwi);
c5c77ba1
JK
1153 if (ret < 0) {
1154 PRINT_ER("Initializing WILC_Wlan FAILED\n");
1155 ret = -EIO;
1156 goto _fail_locks_;
1157 }
c5c77ba1 1158
c5c77ba1
JK
1159 ret = wlan_initialize_threads(nic);
1160 if (ret < 0) {
1161 PRINT_ER("Initializing Threads FAILED\n");
1162 ret = -EIO;
1163 goto _fail_wilc_wlan_;
1164 }
1165
1166#if (defined WILC_SDIO) && (defined COMPLEMENT_BOOT)
c9d4834d 1167 if (wilc1000_prepare_11b_core(&nwi, g_linux_wlan)) {
c5c77ba1
JK
1168 PRINT_ER("11b Core is not ready\n");
1169 ret = -EIO;
1170 goto _fail_threads_;
1171 }
1172#endif
1173
1174#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO)
1175 if (init_irq(g_linux_wlan)) {
1176 PRINT_ER("couldn't initialize IRQ\n");
1177 ret = -EIO;
1178 goto _fail_threads_;
1179 }
1180#endif
1181
1182#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
1183 if (enable_sdio_interrupt()) {
1184 PRINT_ER("couldn't initialize IRQ\n");
1185 ret = -EIO;
1186 goto _fail_irq_init_;
1187 }
1188#endif
1189
1190 if (linux_wlan_get_firmware(nic)) {
17aacd43 1191 PRINT_ER("Can't get firmware\n");
c5c77ba1
JK
1192 ret = -EIO;
1193 goto _fail_irq_enable_;
1194 }
1195
c5c77ba1
JK
1196 /*Download firmware*/
1197 ret = linux_wlan_firmware_download(g_linux_wlan);
1198 if (ret < 0) {
1199 PRINT_ER("Failed to download firmware\n");
1200 ret = -EIO;
1201 goto _fail_irq_enable_;
1202 }
1203
1204 /* Start firmware*/
1205 ret = linux_wlan_start_firmware(nic);
1206 if (ret < 0) {
1207 PRINT_ER("Failed to start firmware\n");
1208 ret = -EIO;
1209 goto _fail_irq_enable_;
1210 }
1211
1212 wilc_bus_set_max_speed();
1213
07056a85 1214 if (wilc_wlan_cfg_get(1, WID_FIRMWARE_VERSION, 1, 0)) {
c5c77ba1
JK
1215 int size;
1216 char Firmware_ver[20];
8dfaafd6 1217
894de36b 1218 size = wilc_wlan_cfg_get_val(
c5c77ba1
JK
1219 WID_FIRMWARE_VERSION,
1220 Firmware_ver, sizeof(Firmware_ver));
1221 Firmware_ver[size] = '\0';
1222 PRINT_D(INIT_DBG, "***** Firmware Ver = %s *******\n", Firmware_ver);
1223 }
1224 /* Initialize firmware with default configuration */
1225 ret = linux_wlan_init_test_config(dev, g_linux_wlan);
1226
1227 if (ret < 0) {
1228 PRINT_ER("Failed to configure firmware\n");
1229 ret = -EIO;
1230 goto _fail_fw_start_;
1231 }
1232
080f11bb 1233 g_linux_wlan->initialized = true;
c5c77ba1
JK
1234 return 0; /*success*/
1235
c5c77ba1 1236_fail_fw_start_:
8cec741e 1237 wilc_wlan_stop();
c5c77ba1
JK
1238
1239_fail_irq_enable_:
1240#if (defined WILC_SDIO) && (!defined WILC_SDIO_IRQ_GPIO)
1241 disable_sdio_interrupt();
c5c77ba1 1242_fail_irq_init_:
7a8fd841 1243#endif
c5c77ba1
JK
1244#if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO)
1245 deinit_irq(g_linux_wlan);
1246
1247#endif
1248_fail_threads_:
1249 wlan_deinitialize_threads(g_linux_wlan);
1250_fail_wilc_wlan_:
a17e2ec1 1251 wilc_wlan_cleanup();
c5c77ba1
JK
1252_fail_locks_:
1253 wlan_deinit_locks(g_linux_wlan);
1254 PRINT_ER("WLAN Iinitialization FAILED\n");
1255 } else {
1256 PRINT_D(INIT_DBG, "wilc1000 already initialized\n");
1257 }
1258 return ret;
1259}
1260
c5c77ba1
JK
1261/*
1262 * - this function will be called automatically by OS when module inserted.
1263 */
1264
c5c77ba1
JK
1265int mac_init_fn(struct net_device *ndev)
1266{
1267
1268 /*Why we do this !!!*/
1269 netif_start_queue(ndev); /* ma */
1270 netif_stop_queue(ndev); /* ma */
1271
1272 return 0;
1273}
c5c77ba1 1274
c5c77ba1 1275/* This fn is called, when this device is setup using ifconfig */
c5c77ba1
JK
1276int mac_open(struct net_device *ndev)
1277{
1278 perInterface_wlan_t *nic;
1279
c5c77ba1
JK
1280 /*No need for setting mac address here anymore,*/
1281 /*Just set it in init_test_config()*/
1282 unsigned char mac_add[ETH_ALEN] = {0};
c5c77ba1
JK
1283 int ret = 0;
1284 int i = 0;
2726887c 1285 struct wilc_priv *priv;
c5c77ba1 1286
7d05652c
CG
1287#ifdef WILC_SPI
1288 if (!g_linux_wlan || !g_linux_wlan->wilc_spidev) {
1289 netdev_err(ndev, "wilc1000: SPI device not ready\n");
1290 return -ENODEV;
1291 }
1292#endif
c5c77ba1
JK
1293 nic = netdev_priv(ndev);
1294 priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy);
1295 PRINT_D(INIT_DBG, "MAC OPEN[%p]\n", ndev);
1296
dd4b6a83 1297 ret = wilc_init_host_int(ndev);
c5c77ba1
JK
1298 if (ret < 0) {
1299 PRINT_ER("Failed to initialize host interface\n");
1300
1301 return ret;
1302 }
c5c77ba1
JK
1303
1304 /*initialize platform*/
1305 PRINT_D(INIT_DBG, "*** re-init ***\n");
1306 ret = wilc1000_wlan_init(ndev, nic);
1307 if (ret < 0) {
1308 PRINT_ER("Failed to initialize wilc1000\n");
a9a16823 1309 wilc_deinit_host_int(ndev);
c5c77ba1
JK
1310 return ret;
1311 }
1312
72ed4dc7 1313 Set_machw_change_vir_if(false);
c5c77ba1 1314
21175ef7 1315 host_int_get_MacAddress(priv->hWILCWFIDrv, mac_add);
310a28fd 1316 PRINT_D(INIT_DBG, "Mac address: %pM\n", mac_add);
c5c77ba1
JK
1317
1318 /* loop through the NUM of supported devices and set the MAC address */
1319 for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
1320 if (ndev == g_linux_wlan->strInterfaceInfo[i].wilc_netdev) {
1321 memcpy(g_linux_wlan->strInterfaceInfo[i].aSrcAddress, mac_add, ETH_ALEN);
218dc407 1322 g_linux_wlan->strInterfaceInfo[i].drvHandler = priv->hWILCWFIDrv;
c5c77ba1
JK
1323 break;
1324 }
1325 }
1326
1327 /* TODO: get MAC address whenever the source is EPROM - hardcoded and copy it to ndev*/
1328 memcpy(ndev->dev_addr, g_linux_wlan->strInterfaceInfo[i].aSrcAddress, ETH_ALEN);
1329
1330 if (!is_valid_ether_addr(ndev->dev_addr)) {
1331 PRINT_ER("Error: Wrong MAC address\n");
1332 ret = -EINVAL;
1333 goto _err_;
1334 }
1335
8e0735c5
CL
1336 wilc_mgmt_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev->ieee80211_ptr,
1337 nic->g_struct_frame_reg[0].frame_type, nic->g_struct_frame_reg[0].reg);
1338 wilc_mgmt_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev->ieee80211_ptr,
1339 nic->g_struct_frame_reg[1].frame_type, nic->g_struct_frame_reg[1].reg);
c5c77ba1
JK
1340 netif_wake_queue(ndev);
1341 g_linux_wlan->open_ifcs++;
1342 nic->mac_opened = 1;
1343 return 0;
1344
1345_err_:
a9a16823 1346 wilc_deinit_host_int(ndev);
c5c77ba1
JK
1347 wilc1000_wlan_deinit(g_linux_wlan);
1348 return ret;
1349}
c5c77ba1
JK
1350
1351struct net_device_stats *mac_stats(struct net_device *dev)
1352{
1353 perInterface_wlan_t *nic = netdev_priv(dev);
1354
c5c77ba1
JK
1355 return &nic->netstats;
1356}
1357
1358/* Setup the multicast filter */
c5c77ba1
JK
1359static void wilc_set_multicast_list(struct net_device *dev)
1360{
1361
1362 struct netdev_hw_addr *ha;
2726887c 1363 struct wilc_priv *priv;
441dc609 1364 struct host_if_drv *pstrWFIDrv;
c5c77ba1 1365 int i = 0;
8dfaafd6 1366
c5c77ba1 1367 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
441dc609 1368 pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
c5c77ba1 1369
c5c77ba1
JK
1370 if (!dev)
1371 return;
1372
17aacd43 1373 PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n", dev->mc.count);
c5c77ba1
JK
1374
1375 if (dev->flags & IFF_PROMISC) {
1376 /* Normally, we should configure the chip to retrive all packets
1377 * but we don't wanna support this right now */
1378 /* TODO: add promiscuous mode support */
17aacd43 1379 PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets\n");
c5c77ba1
JK
1380 return;
1381 }
1382
1383 /* If there's more addresses than we handle, get all multicast
1384 * packets and sort them out in software. */
1385 if ((dev->flags & IFF_ALLMULTI) || (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) {
1386 PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n");
1387 /* get all multicast packets */
218dc407 1388 host_int_setup_multicast_filter(pstrWFIDrv, false, 0);
c5c77ba1
JK
1389 return;
1390 }
1391
1392 /* No multicast? Just get our own stuff */
1393 if ((dev->mc.count) == 0) {
1394 PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n");
218dc407 1395 host_int_setup_multicast_filter(pstrWFIDrv, true, 0);
c5c77ba1
JK
1396 return;
1397 }
1398
1399 /* Store all of the multicast addresses in the hardware filter */
1400 netdev_for_each_mc_addr(ha, dev)
1401 {
d00d2ba3 1402 memcpy(gau8MulticastMacAddrList[i], ha->addr, ETH_ALEN);
c5c77ba1
JK
1403 PRINT_D(INIT_DBG, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i,
1404 gau8MulticastMacAddrList[i][0], gau8MulticastMacAddrList[i][1], gau8MulticastMacAddrList[i][2], gau8MulticastMacAddrList[i][3], gau8MulticastMacAddrList[i][4], gau8MulticastMacAddrList[i][5]);
1405 i++;
1406 }
1407
218dc407 1408 host_int_setup_multicast_filter(pstrWFIDrv, true, (dev->mc.count));
c5c77ba1
JK
1409
1410 return;
1411
1412}
1413
c5c77ba1
JK
1414static void linux_wlan_tx_complete(void *priv, int status)
1415{
1416
1417 struct tx_complete_data *pv_data = (struct tx_complete_data *)priv;
8dfaafd6 1418
78174ada 1419 if (status == 1)
c5c77ba1 1420 PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
78174ada 1421 else
c5c77ba1 1422 PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
c5c77ba1
JK
1423 /* Free the SK Buffer, its work is done */
1424 dev_kfree_skb(pv_data->skb);
a18dd630 1425 kfree(pv_data);
c5c77ba1
JK
1426}
1427
1428int mac_xmit(struct sk_buff *skb, struct net_device *ndev)
1429{
1430 perInterface_wlan_t *nic;
1431 struct tx_complete_data *tx_data = NULL;
1432 int QueueCount;
1433 char *pu8UdpBuffer;
1434 struct iphdr *ih;
1435 struct ethhdr *eth_h;
8dfaafd6 1436
c5c77ba1
JK
1437 nic = netdev_priv(ndev);
1438
c5c77ba1
JK
1439 PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n");
1440
1441 /* Stop the network interface queue */
1442 if (skb->dev != ndev) {
1443 PRINT_ER("Packet not destined to this device\n");
1444 return 0;
1445 }
1446
d5df3797 1447 tx_data = kmalloc(sizeof(struct tx_complete_data), GFP_ATOMIC);
c5c77ba1
JK
1448 if (tx_data == NULL) {
1449 PRINT_ER("Failed to allocate memory for tx_data structure\n");
1450 dev_kfree_skb(skb);
1451 netif_wake_queue(ndev);
1452 return 0;
1453 }
1454
1455 tx_data->buff = skb->data;
1456 tx_data->size = skb->len;
1457 tx_data->skb = skb;
1458
1459 eth_h = (struct ethhdr *)(skb->data);
fc4b95d6 1460 if (eth_h->h_proto == 0x8e88)
c5c77ba1 1461 PRINT_D(INIT_DBG, "EAPOL transmitted\n");
c5c77ba1
JK
1462
1463 /*get source and dest ip addresses*/
1464 ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
1465
1466 pu8UdpBuffer = (char *)ih + sizeof(struct iphdr);
fc4b95d6 1467 if ((pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67) || (pu8UdpBuffer[1] == 67 && pu8UdpBuffer[3] == 68))
c5c77ba1
JK
1468 PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", pu8UdpBuffer[248], pu8UdpBuffer[249], pu8UdpBuffer[250]);
1469
c5c77ba1
JK
1470 PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb);
1471
1472 /* Send packet to MAC HW - for now the tx_complete function will be just status
1473 * indicator. still not sure if I need to suspend host transmission till the tx_complete
1474 * function called or not?
1475 * allocated buffer will be freed in tx_complete function.
1476 */
1477 PRINT_D(TX_DBG, "Adding tx packet to TX Queue\n");
1478 nic->netstats.tx_packets++;
1479 nic->netstats.tx_bytes += tx_data->size;
1480 tx_data->pBssid = g_linux_wlan->strInterfaceInfo[nic->u8IfIdx].aBSSID;
8fc84a6f
GL
1481 QueueCount = wilc_wlan_txq_add_net_pkt((void *)tx_data, tx_data->buff,
1482 tx_data->size,
1483 linux_wlan_tx_complete);
c5c77ba1 1484
c5c77ba1
JK
1485 if (QueueCount > FLOW_CONTROL_UPPER_THRESHOLD) {
1486 netif_stop_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev);
1487 netif_stop_queue(g_linux_wlan->strInterfaceInfo[1].wilc_netdev);
1488 }
1489
1490 return 0;
1491}
1492
c5c77ba1
JK
1493int mac_close(struct net_device *ndev)
1494{
2726887c 1495 struct wilc_priv *priv;
c5c77ba1 1496 perInterface_wlan_t *nic;
441dc609 1497 struct host_if_drv *pstrWFIDrv;
c5c77ba1
JK
1498
1499 nic = netdev_priv(ndev);
1500
1501 if ((nic == NULL) || (nic->wilc_netdev == NULL) || (nic->wilc_netdev->ieee80211_ptr == NULL) || (nic->wilc_netdev->ieee80211_ptr->wiphy == NULL)) {
1502 PRINT_ER("nic = NULL\n");
1503 return 0;
1504 }
1505
1506 priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy);
1507
1508 if (priv == NULL) {
1509 PRINT_ER("priv = NULL\n");
1510 return 0;
1511 }
1512
441dc609 1513 pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
c5c77ba1 1514
c5c77ba1
JK
1515 PRINT_D(GENERIC_DBG, "Mac close\n");
1516
1517 if (g_linux_wlan == NULL) {
1518 PRINT_ER("g_linux_wlan = NULL\n");
1519 return 0;
1520 }
1521
1522 if (pstrWFIDrv == NULL) {
1523 PRINT_ER("pstrWFIDrv = NULL\n");
1524 return 0;
1525 }
1526
1527 if ((g_linux_wlan->open_ifcs) > 0) {
1528 g_linux_wlan->open_ifcs--;
1529 } else {
1530 PRINT_ER("ERROR: MAC close called while number of opened interfaces is zero\n");
1531 return 0;
1532 }
1533
1534 if (nic->wilc_netdev != NULL) {
1535 /* Stop the network interface queue */
1536 netif_stop_queue(nic->wilc_netdev);
1537
a9a16823 1538 wilc_deinit_host_int(nic->wilc_netdev);
c5c77ba1
JK
1539 }
1540
1541 if (g_linux_wlan->open_ifcs == 0) {
1542 PRINT_D(GENERIC_DBG, "Deinitializing wilc1000\n");
1543 g_linux_wlan->close = 1;
1544 wilc1000_wlan_deinit(g_linux_wlan);
c5c77ba1 1545 WILC_WFI_deinit_mon_interface();
c5c77ba1
JK
1546 }
1547
8990d856 1548 up(&close_exit_sync);
c5c77ba1
JK
1549 nic->mac_opened = 0;
1550
1551 return 0;
1552}
1553
c5c77ba1
JK
1554int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
1555{
1556
63d03e47 1557 u8 *buff = NULL;
ca356ada 1558 s8 rssi;
4e4467fd 1559 u32 size = 0, length = 0;
c5c77ba1 1560 perInterface_wlan_t *nic;
2726887c 1561 struct wilc_priv *priv;
e6e12661 1562 s32 s32Error = 0;
c5c77ba1 1563
c5c77ba1 1564 /* struct iwreq *wrq = (struct iwreq *) req; // tony moved to case SIOCSIWPRIV */
c5c77ba1
JK
1565 nic = netdev_priv(ndev);
1566
080f11bb 1567 if (!g_linux_wlan->initialized)
c5c77ba1
JK
1568 return 0;
1569
c5c77ba1 1570 switch (cmd) {
c5c77ba1
JK
1571
1572 /* ]] 2013-06-24 */
1573 case SIOCSIWPRIV:
1574 {
1575 struct iwreq *wrq = (struct iwreq *) req; /* added by tony */
1576
1577 size = wrq->u.data.length;
1578
1579 if (size && wrq->u.data.pointer) {
c5c77ba1 1580
4a01f1c3 1581 buff = memdup_user(wrq->u.data.pointer, wrq->u.data.length);
360e27a9
SM
1582 if (IS_ERR(buff))
1583 return PTR_ERR(buff);
c5c77ba1
JK
1584
1585 if (strncasecmp(buff, "RSSI", length) == 0) {
c5c77ba1
JK
1586 priv = wiphy_priv(nic->wilc_netdev->ieee80211_ptr->wiphy);
1587 s32Error = host_int_get_rssi(priv->hWILCWFIDrv, &(rssi));
1588 if (s32Error)
1589 PRINT_ER("Failed to send get rssi param's message queue ");
c5c77ba1
JK
1590 PRINT_INFO(GENERIC_DBG, "RSSI :%d\n", rssi);
1591
1592 /*Rounding up the rssi negative value*/
1593 rssi += 5;
1594
1595 snprintf(buff, size, "rssi %d", rssi);
1596
1597 if (copy_to_user(wrq->u.data.pointer, buff, size)) {
60cb1e20 1598 PRINT_ER("%s: failed to copy data to user buffer\n", __func__);
c5c77ba1
JK
1599 s32Error = -EFAULT;
1600 goto done;
1601 }
1602 }
1603 }
1604 }
1605 break;
1606
1607 default:
1608 {
1609 PRINT_INFO(GENERIC_DBG, "Command - %d - has been received\n", cmd);
1610 s32Error = -EOPNOTSUPP;
1611 goto done;
1612 }
1613 }
1614
1615done:
1616
642ac6c0 1617 kfree(buff);
c5c77ba1
JK
1618
1619 return s32Error;
1620}
1621
fbc2fe16 1622void frmw_to_linux(u8 *buff, u32 size, u32 pkt_offset)
c5c77ba1
JK
1623{
1624
1625 unsigned int frame_len = 0;
1626 int stats;
1627 unsigned char *buff_to_send = NULL;
1628 struct sk_buff *skb;
c5c77ba1
JK
1629 struct net_device *wilc_netdev;
1630 perInterface_wlan_t *nic;
1631
1632 wilc_netdev = GetIfHandler(buff);
1633 if (wilc_netdev == NULL)
1634 return;
1635
1636 buff += pkt_offset;
1637 nic = netdev_priv(wilc_netdev);
1638
1639 if (size > 0) {
1640
1641 frame_len = size;
1642 buff_to_send = buff;
1643
c5c77ba1
JK
1644 /* Need to send the packet up to the host, allocate a skb buffer */
1645 skb = dev_alloc_skb(frame_len);
1646 if (skb == NULL) {
1647 PRINT_ER("Low memory - packet droped\n");
1648 return;
1649 }
1650
fc4b95d6 1651 if (g_linux_wlan == NULL || wilc_netdev == NULL)
c5c77ba1 1652 PRINT_ER("wilc_netdev in g_linux_wlan is NULL");
c5c77ba1
JK
1653 skb->dev = wilc_netdev;
1654
fc4b95d6 1655 if (skb->dev == NULL)
c5c77ba1 1656 PRINT_ER("skb->dev is NULL\n");
c5c77ba1
JK
1657
1658 /*
1659 * for(i=0;i<40;i++)
1660 * {
1661 * if(i<frame_len)
1662 * WILC_PRINTF("buff_to_send[%d]=%2x\n",i,buff_to_send[i]);
1663 *
1664 * }*/
1665
1666 /* skb_put(skb, frame_len); */
1667 memcpy(skb_put(skb, frame_len), buff_to_send, frame_len);
1668
1669 /* WILC_PRINTF("After MEM_CPY\n"); */
1670
1671 /* nic = netdev_priv(wilc_netdev); */
1672
c5c77ba1 1673 skb->protocol = eth_type_trans(skb, wilc_netdev);
c5c77ba1
JK
1674 /* Send the packet to the stack by giving it to the bridge */
1675 nic->netstats.rx_packets++;
1676 nic->netstats.rx_bytes += frame_len;
1677 skb->ip_summed = CHECKSUM_UNNECESSARY;
1678 stats = netif_rx(skb);
1679 PRINT_D(RX_DBG, "netif_rx ret value is: %d\n", stats);
1680 }
c5c77ba1
JK
1681}
1682
fbc2fe16 1683void WILC_WFI_mgmt_rx(u8 *buff, u32 size)
c5c77ba1
JK
1684{
1685 int i = 0;
1686 perInterface_wlan_t *nic;
1687
c5c77ba1
JK
1688 /*Pass the frame on the monitor interface, if any.*/
1689 /*Otherwise, pass it on p2p0 netdev, if registered on it*/
1690 for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
1691 nic = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
1692 if (nic->monitor_flag) {
1693 WILC_WFI_monitor_rx(buff, size);
1694 return;
1695 }
1696 }
1697
c5c77ba1
JK
1698 nic = netdev_priv(g_linux_wlan->strInterfaceInfo[1].wilc_netdev); /* p2p0 */
1699 if ((buff[0] == nic->g_struct_frame_reg[0].frame_type && nic->g_struct_frame_reg[0].reg) ||
fc4b95d6 1700 (buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg))
c5c77ba1 1701 WILC_WFI_p2p_rx(g_linux_wlan->strInterfaceInfo[1].wilc_netdev, buff, size);
c5c77ba1
JK
1702}
1703
1704int wilc_netdev_init(void)
1705{
1706
1707 int i;
1708 perInterface_wlan_t *nic;
1709 struct net_device *ndev;
1710
642768ee 1711 sema_init(&close_exit_sync, 0);
c5c77ba1
JK
1712
1713 /*create the common structure*/
f61c5aff 1714 g_linux_wlan = kzalloc(sizeof(*g_linux_wlan), GFP_KERNEL);
ac61ef86
CL
1715 if (!g_linux_wlan)
1716 return -ENOMEM;
c5c77ba1 1717
c5c77ba1 1718 register_inetaddr_notifier(&g_dev_notifier);
c5c77ba1
JK
1719
1720 for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
1721 /*allocate first ethernet device with perinterface_wlan_t as its private data*/
1722 ndev = alloc_etherdev(sizeof(perInterface_wlan_t));
1723 if (!ndev) {
1724 PRINT_ER("Failed to allocate ethernet dev\n");
1725 return -1;
1726 }
1727
1728 nic = netdev_priv(ndev);
1729 memset(nic, 0, sizeof(perInterface_wlan_t));
1730
1731 /*Name the Devices*/
1732 if (i == 0) {
1733 #if defined(NM73131) /* tony, 2012-09-20 */
1734 strcpy(ndev->name, "wilc_eth%d");
1735 #elif defined(PLAT_CLM9722) /* rachel */
1736 strcpy(ndev->name, "eth%d");
1737 #else /* PANDA_BOARD, PLAT_ALLWINNER_A10, PLAT_ALLWINNER_A20, PLAT_ALLWINNER_A31, PLAT_AML8726_M3 or PLAT_WMS8304 */
1738 strcpy(ndev->name, "wlan%d");
1739 #endif
1740 } else
1741 strcpy(ndev->name, "p2p%d");
1742
1743 nic->u8IfIdx = g_linux_wlan->u8NoIfcs;
1744 nic->wilc_netdev = ndev;
1745 g_linux_wlan->strInterfaceInfo[g_linux_wlan->u8NoIfcs].wilc_netdev = ndev;
1746 g_linux_wlan->u8NoIfcs++;
e5af0561 1747 ndev->netdev_ops = &wilc_netdev_ops;
c5c77ba1 1748
c5c77ba1
JK
1749 {
1750 struct wireless_dev *wdev;
1751 /*Register WiFi*/
8459fd54 1752 wdev = wilc_create_wiphy(ndev);
c5c77ba1
JK
1753
1754 #ifdef WILC_SDIO
1755 /* set netdev, tony */
1756 SET_NETDEV_DEV(ndev, &local_sdio_func->dev);
1757 #endif
1758
1759 if (wdev == NULL) {
1760 PRINT_ER("Can't register WILC Wiphy\n");
1761 return -1;
1762 }
1763
1764 /*linking the wireless_dev structure with the netdevice*/
1765 nic->wilc_netdev->ieee80211_ptr = wdev;
1766 nic->wilc_netdev->ml_priv = nic;
1767 wdev->netdev = nic->wilc_netdev;
1768 nic->netstats.rx_packets = 0;
1769 nic->netstats.tx_packets = 0;
1770 nic->netstats.rx_bytes = 0;
1771 nic->netstats.tx_bytes = 0;
1772
1773 }
c5c77ba1 1774
c5c77ba1
JK
1775 if (register_netdev(ndev)) {
1776 PRINT_ER("Device couldn't be registered - %s\n", ndev->name);
1777 return -1; /* ERROR */
1778 }
1779
1780 nic->iftype = STATION_MODE;
1781 nic->mac_opened = 0;
1782
1783 }
1784
1785 #ifndef WILC_SDIO
1786 if (!linux_spi_init(&g_linux_wlan->wilc_spidev)) {
17aacd43 1787 PRINT_ER("Can't initialize SPI\n");
c5c77ba1
JK
1788 return -1; /* ERROR */
1789 }
1790 g_linux_wlan->wilc_spidev = wilc_spi_dev;
1791 #else
1792 g_linux_wlan->wilc_sdio_func = local_sdio_func;
1793 #endif
1794
1795 return 0;
1796}
1797
c5c77ba1
JK
1798/*The 1st function called after module inserted*/
1799static int __init init_wilc_driver(void)
1800{
33694632 1801#if defined(WILC_DEBUGFS)
c5c77ba1
JK
1802 if (wilc_debugfs_init() < 0) {
1803 PRINT_D(GENERIC_DBG, "fail to create debugfs for wilc driver\n");
1804 return -1;
1805 }
1806#endif
1807
1808 printk("IN INIT FUNCTION\n");
691f1a2f 1809 printk("*** WILC1000 driver VERSION=[10.2] FW_VER=[10.2] ***\n");
c5c77ba1
JK
1810
1811 linux_wlan_device_power(1);
1812 msleep(100);
1813 linux_wlan_device_detection(1);
1814
1815#ifdef WILC_SDIO
1816 {
1817 int ret;
1818
1819 ret = sdio_register_driver(&wilc_bus);
fc4b95d6 1820 if (ret < 0)
c5c77ba1 1821 PRINT_D(INIT_DBG, "init_wilc_driver: Failed register sdio driver\n");
c5c77ba1
JK
1822
1823 return ret;
1824 }
1825#else
1826 PRINT_D(INIT_DBG, "Initializing netdev\n");
fc4b95d6 1827 if (wilc_netdev_init())
c5c77ba1 1828 PRINT_ER("Couldn't initialize netdev\n");
c5c77ba1
JK
1829 return 0;
1830#endif
1831}
1832late_initcall(init_wilc_driver);
1833
1834static void __exit exit_wilc_driver(void)
1835{
1836 int i = 0;
842f1d71 1837 perInterface_wlan_t *nic[NUM_CONCURRENT_IFC] = {NULL,};
c5c77ba1
JK
1838 #define CLOSE_TIMEOUT (12 * 1000)
1839
1840 if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL)
1841 || ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) {
c5c77ba1 1842 unregister_inetaddr_notifier(&g_dev_notifier);
c5c77ba1 1843
fc4b95d6 1844 for (i = 0; i < NUM_CONCURRENT_IFC; i++)
c5c77ba1 1845 nic[i] = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
c5c77ba1
JK
1846 }
1847
c5c77ba1
JK
1848 if ((g_linux_wlan != NULL) && g_linux_wlan->wilc_firmware != NULL) {
1849 release_firmware(g_linux_wlan->wilc_firmware);
1850 g_linux_wlan->wilc_firmware = NULL;
1851 }
1852
c5c77ba1
JK
1853 if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL)
1854 || ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) {
1855 PRINT_D(INIT_DBG, "Waiting for mac_close ....\n");
1856
1857 if (linux_wlan_lock_timeout(&close_exit_sync, CLOSE_TIMEOUT) < 0)
1858 PRINT_D(INIT_DBG, "Closed TimedOUT\n");
1859 else
1860 PRINT_D(INIT_DBG, "mac_closed\n");
1861
c5c77ba1
JK
1862 for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
1863 /* close all opened interfaces */
1864 if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev != NULL) {
fc4b95d6 1865 if (nic[i]->mac_opened)
c5c77ba1 1866 mac_close(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
c5c77ba1
JK
1867 }
1868 }
1869 for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
17aacd43 1870 PRINT_D(INIT_DBG, "Unregistering netdev %p\n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
c5c77ba1 1871 unregister_netdev(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
c5c77ba1 1872 PRINT_D(INIT_DBG, "Freeing Wiphy...\n");
96da20a9 1873 wilc_free_wiphy(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
c5c77ba1
JK
1874 PRINT_D(INIT_DBG, "Freeing netdev...\n");
1875 free_netdev(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
1876 }
1877 }
1878
c2eda352
CL
1879#ifndef WILC_SDIO
1880 PRINT_D(INIT_DBG, "SPI unregsiter...\n");
1881 spi_unregister_driver(&wilc_bus);
1882#else
1883 PRINT_D(INIT_DBG, "SDIO unregsiter...\n");
1884 sdio_unregister_driver(&wilc_bus);
1885#endif
c5c77ba1 1886
fbeb0dab
SB
1887 kfree(g_linux_wlan);
1888 g_linux_wlan = NULL;
c2eda352 1889 printk("Module_exit Done.\n");
c5c77ba1 1890
33694632 1891#if defined(WILC_DEBUGFS)
c2eda352 1892 wilc_debugfs_remove();
c5c77ba1
JK
1893#endif
1894
c2eda352
CL
1895 linux_wlan_device_detection(0);
1896 linux_wlan_device_power(0);
c5c77ba1
JK
1897}
1898module_exit(exit_wilc_driver);
1899
1900MODULE_LICENSE("GPL");
This page took 0.24161 seconds and 5 git commands to generate.