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