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