intel_pstate: fix PCT_TO_HWP macro
[linux-2.6-block.git] / drivers / staging / wilc1000 / wilc_wfi_netdevice.c
CommitLineData
c5c77ba1
JK
1/*!
2 * @file wilc_wfi_netdevice.c
3 * @brief File Operations OS wrapper functionality
4 * @author mdaftedar
5 * @sa wilc_wfi_netdevice.h
6 * @date 01 MAR 2012
7 * @version 1.0
8 */
9
10#ifdef SIMULATION
11
12#include "wilc_wfi_cfgoperations.h"
13#include "host_interface.h"
14
15
16MODULE_AUTHOR("Mai Daftedar");
17MODULE_LICENSE("Dual BSD/GPL");
18
19
20struct net_device *WILC_WFI_devs[2];
21
22/*
23 * Transmitter lockup simulation, normally disabled.
24 */
25static int lockup;
26module_param(lockup, int, 0);
27
28static int timeout = WILC_WFI_TIMEOUT;
29module_param(timeout, int, 0);
30
31/*
32 * Do we run in NAPI mode?
33 */
34static int use_napi ;
35module_param(use_napi, int, 0);
36
37
38/*
39 * A structure representing an in-flight packet.
40 */
41struct WILC_WFI_packet {
42 struct WILC_WFI_packet *next;
43 struct net_device *dev;
44 int datalen;
45 u8 data[ETH_DATA_LEN];
46};
47
48
49
50int pool_size = 8;
51module_param(pool_size, int, 0);
52
53
54static void WILC_WFI_TxTimeout(struct net_device *dev);
55static void (*WILC_WFI_Interrupt)(int, void *, struct pt_regs *);
56
57/**
58 * @brief WILC_WFI_SetupPool
59 * @details Set up a device's packet pool.
60 * @param[in] struct net_device *dev : Network Device Pointer
61 * @return NONE
62 * @author mdaftedar
63 * @date 01 MAR 2012
64 * @version 1.0
65 */
66void WILC_WFI_SetupPool(struct net_device *dev)
67{
68 struct WILC_WFI_priv *priv = netdev_priv(dev);
69 int i;
70 struct WILC_WFI_packet *pkt;
71
72 priv->ppool = NULL;
73 for (i = 0; i < pool_size; i++) {
74 pkt = kmalloc (sizeof (struct WILC_WFI_packet), GFP_KERNEL);
75 if (pkt == NULL) {
76 PRINT_D(RX_DBG, "Ran out of memory allocating packet pool\n");
77 return;
78 }
79 pkt->dev = dev;
80 pkt->next = priv->ppool;
81 priv->ppool = pkt;
82 }
83}
84
85/**
86 * @brief WILC_WFI_TearDownPool
87 * @details Internal cleanup function that's called after the network device
88 * driver is unregistered
89 * @param[in] struct net_device *dev : Network Device Driver
90 * @return NONE
91 * @author mdaftedar
92 * @date 01 MAR 2012
93 * @version 1.0
94 */
95void WILC_WFI_TearDownPool(struct net_device *dev)
96{
97 struct WILC_WFI_priv *priv = netdev_priv(dev);
98 struct WILC_WFI_packet *pkt;
99
100 while ((pkt = priv->ppool)) {
101 priv->ppool = pkt->next;
102 kfree (pkt);
103 /* FIXME - in-flight packets ? */
104 }
105}
106
107/**
108 * @brief WILC_WFI_GetTxBuffer
109 * @details Buffer/pool management
110 * @param[in] net_device *dev : Network Device Driver Structure
111 * @return struct WILC_WFI_packet
112 * @author mdaftedar
113 * @date 01 MAR 2012
114 * @version 1.0
115 */
116struct WILC_WFI_packet *WILC_WFI_GetTxBuffer(struct net_device *dev)
117{
118 struct WILC_WFI_priv *priv = netdev_priv(dev);
119 unsigned long flags;
120 struct WILC_WFI_packet *pkt;
121
122 spin_lock_irqsave(&priv->lock, flags);
123 pkt = priv->ppool;
124 priv->ppool = pkt->next;
125 if (priv->ppool == NULL) {
126 PRINT_INFO(RX_DBG, "Pool empty\n");
127 netif_stop_queue(dev);
128 }
129 spin_unlock_irqrestore(&priv->lock, flags);
130 return pkt;
131}
132/**
133 * @brief WILC_WFI_ReleaseBuffer
134 * @details Buffer/pool management
135 * @param[in] WILC_WFI_packet *pkt : Structure holding in-flight packet
136 * @return NONE
137 * @author mdaftedar
138 * @date 01 MAR 2012
139 * @version 1.0
140 */
141void WILC_WFI_ReleaseBuffer(struct WILC_WFI_packet *pkt)
142{
143 unsigned long flags;
144 struct WILC_WFI_priv *priv = netdev_priv(pkt->dev);
145
146 spin_lock_irqsave(&priv->lock, flags);
147 pkt->next = priv->ppool;
148 priv->ppool = pkt;
149 spin_unlock_irqrestore(&priv->lock, flags);
150 if (netif_queue_stopped(pkt->dev) && pkt->next == NULL)
151 netif_wake_queue(pkt->dev);
152}
153
154/**
155 * @brief WILC_WFI_EnqueueBuf
156 * @details Enqueuing packets in an RX buffer queue
157 * @param[in] WILC_WFI_packet *pkt : Structure holding in-flight packet
158 * @param[in] net_device *dev : Network Device Driver Structure
159 * @return NONE
160 * @author mdaftedar
161 * @date 01 MAR 2012
162 * @version 1.0
163 */
164void WILC_WFI_EnqueueBuf(struct net_device *dev, struct WILC_WFI_packet *pkt)
165{
166 unsigned long flags;
167 struct WILC_WFI_priv *priv = netdev_priv(dev);
168
169 spin_lock_irqsave(&priv->lock, flags);
170 pkt->next = priv->rx_queue; /* FIXME - misorders packets */
171 priv->rx_queue = pkt;
172 spin_unlock_irqrestore(&priv->lock, flags);
173}
174
175/**
176 * @brief WILC_WFI_DequeueBuf
177 * @details Dequeuing packets from the RX buffer queue
178 * @param[in] net_device *dev : Network Device Driver Structure
179 * @return WILC_WFI_packet *pkt : Structure holding in-flight pac
180 * @author mdaftedar
181 * @date 01 MAR 2012
182 * @version 1.0
183 */
184struct WILC_WFI_packet *WILC_WFI_DequeueBuf(struct net_device *dev)
185{
186 struct WILC_WFI_priv *priv = netdev_priv(dev);
187 struct WILC_WFI_packet *pkt;
188 unsigned long flags;
189
190 spin_lock_irqsave(&priv->lock, flags);
191 pkt = priv->rx_queue;
192 if (pkt != NULL)
193 priv->rx_queue = pkt->next;
194 spin_unlock_irqrestore(&priv->lock, flags);
195 return pkt;
196}
197/**
198 * @brief WILC_WFI_RxInts
199 * @details Enable and disable receive interrupts.
200 * @param[in] net_device *dev : Network Device Driver Structure
201 * @param[in] enable : Enable/Disable flag
202 * @return NONE
203 * @author mdaftedar
204 * @date 01 MAR 2012
205 * @version 1.0
206 */
207static void WILC_WFI_RxInts(struct net_device *dev, int enable)
208{
209 struct WILC_WFI_priv *priv = netdev_priv(dev);
210 priv->rx_int_enabled = enable;
211}
212
213/**
214 * @brief WILC_WFI_Open
215 * @details Open Network Device Driver, called when the network
216 * interface is opened. It starts the interface's transmit queue.
217 * @param[in] net_device *dev : Network Device Driver Structure
218 * @param[in] enable : Enable/Disable flag
219 * @return int : Returns 0 upon success.
220 * @author mdaftedar
221 * @date 01 MAR 2012
222 * @version 1.0
223 */
224int WILC_WFI_Open(struct net_device *dev)
225{
226 /* request_region(), request_irq(), .... (like fops->open) */
227 /*
228 * Assign the hardware address of the board: use "\0SNULx", where
229 * x is 0 or 1. The first byte is '\0' to avoid being a multicast
230 * address (the first byte of multicast addrs is odd).
231 */
232 memcpy(dev->dev_addr, "\0WLAN0", ETH_ALEN);
233 if (dev == WILC_WFI_devs[1])
234 dev->dev_addr[ETH_ALEN - 1]++; /* \0SNUL1 */
235
236 WILC_WFI_InitHostInt(dev);
237 netif_start_queue(dev);
238 return 0;
239}
240/**
241 * @brief WILC_WFI_Release
242 * @details Release Network Device Driver, called when the network
243 * interface is stopped or brought down. This function marks
244 * the network driver as not being able to transmit
245 * @param[in] net_device *dev : Network Device Driver Structure
246 * @return int : Return 0 on Success.
247 * @author mdaftedar
248 * @date 01 MAR 2012
249 * @version 1.0
250 */
251int WILC_WFI_Release(struct net_device *dev)
252{
253 /* release ports, irq and such -- like fops->close */
254
255 netif_stop_queue(dev); /* can't transmit any more */
256
257 return 0;
258}
259/**
260 * @brief WILC_WFI_Config
261 * @details Configuration changes (passed on by ifconfig)
262 * @param[in] net_device *dev : Network Device Driver Structure
263 * @param[in] struct ifmap *map : Contains the ioctl implementation for the
264 * network driver.
265 * @return int : Return 0 on Success.
266 * @author mdaftedar
267 * @date 01 MAR 2012
268 * @version 1.0
269 */
270int WILC_WFI_Config(struct net_device *dev, struct ifmap *map)
271{
272 if (dev->flags & IFF_UP) /* can't act on a running interface */
273 return -EBUSY;
274
275 /* Don't allow changing the I/O address */
276 if (map->base_addr != dev->base_addr) {
277 PRINT_D(RX_DBG, KERN_WARNING "WILC_WFI: Can't change I/O address\n");
278 return -EOPNOTSUPP;
279 }
280
281 /* Allow changing the IRQ */
282 if (map->irq != dev->irq) {
283 dev->irq = map->irq;
284 /* request_irq() is delayed to open-time */
285 }
286
287 /* ignore other fields */
288 return 0;
289}
290/**
291 * @brief WILC_WFI_Rx
292 * @details Receive a packet: retrieve, encapsulate and pass over to upper
293 * levels
294 * @param[in] net_device *dev : Network Device Driver Structure
295 * @param[in] WILC_WFI_packet :
296 * @return NONE
297 * @author mdaftedar
298 * @date 01 MAR 2012
299 * @version 1.0
300 */
301void WILC_WFI_Rx(struct net_device *dev, struct WILC_WFI_packet *pkt)
302{
303 int i;
304 struct sk_buff *skb;
305 struct WILC_WFI_priv *priv = netdev_priv(dev);
306 s8 rssi;
307 /*
308 * The packet has been retrieved from the transmission
309 * medium. Build an skb around it, so upper layers can handle it
310 */
311
312
313 skb = dev_alloc_skb(pkt->datalen + 2);
314 if (!skb) {
315 if (printk_ratelimit())
316 PRINT_D(RX_DBG, "WILC_WFI rx: low on mem - packet dropped\n");
317 priv->stats.rx_dropped++;
318 goto out;
319 }
320 skb_reserve(skb, 2); /* align IP on 16B boundary */
321 memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
322
323 if (priv->monitor_flag) {
324 PRINT_INFO(RX_DBG, "In monitor device name %s\n", dev->name);
325 priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy);
326 PRINT_D(RX_DBG, "VALUE PASSED IN OF HRWD %p\n", priv->hWILCWFIDrv);
327 /* host_int_get_rssi(priv->hWILCWFIDrv, &(rssi)); */
328 if (INFO) {
329 for (i = 14; i < skb->len; i++)
330 PRINT_INFO(RX_DBG, "RXdata[%d] %02x\n", i, skb->data[i]);
331 }
332 WILC_WFI_monitor_rx(dev, skb);
333 return;
334 }
c5c77ba1
JK
335out:
336 return;
337}
338
339/**
340 * @brief WILC_WFI_Poll
341 * @details The poll implementation
342 * @param[in] struct napi_struct *napi :
343 * @param[in] int budget :
344 * @return int : Return 0 on Success.
345 * @author mdaftedar
346 * @date 01 MAR 2012
347 * @version 1.0
348 */
349static int WILC_WFI_Poll(struct napi_struct *napi, int budget)
350{
351 int npackets = 0;
352 struct sk_buff *skb;
353 struct WILC_WFI_priv *priv = container_of(napi, struct WILC_WFI_priv, napi);
354 struct net_device *dev = priv->dev;
355 struct WILC_WFI_packet *pkt;
356
357 while (npackets < budget && priv->rx_queue) {
358 pkt = WILC_WFI_DequeueBuf(dev);
359 skb = dev_alloc_skb(pkt->datalen + 2);
360 if (!skb) {
361 if (printk_ratelimit())
362 PRINT_D(RX_DBG, "WILC_WFI: packet dropped\n");
363 priv->stats.rx_dropped++;
364 WILC_WFI_ReleaseBuffer(pkt);
365 continue;
366 }
367 skb_reserve(skb, 2); /* align IP on 16B boundary */
368 memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
369 skb->dev = dev;
370 skb->protocol = eth_type_trans(skb, dev);
371 skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
372 netif_receive_skb(skb);
373 /* Maintain stats */
374 npackets++;
375 WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, pkt->datalen, WILC_WFI_RX_PKT);
376 WILC_WFI_ReleaseBuffer(pkt);
377 }
378 /* If we processed all packets, we're done; tell the kernel and re-enable ints */
379 if (npackets < budget) {
380 napi_complete(napi);
381 WILC_WFI_RxInts(dev, 1);
382 }
383 return npackets;
384}
385
386/**
387 * @brief WILC_WFI_Poll
388 * @details The typical interrupt entry point
389 * @param[in] struct napi_struct *napi :
390 * @param[in] int budget :
391 * @return int : Return 0 on Success.
392 * @author mdaftedar
393 * @date 01 MAR 2012
394 * @version 1.0
395 */
396static void WILC_WFI_RegularInterrupt(int irq, void *dev_id, struct pt_regs *regs)
397{
398 int statusword;
399 struct WILC_WFI_priv *priv;
400 struct WILC_WFI_packet *pkt = NULL;
401 /*
402 * As usual, check the "device" pointer to be sure it is
403 * really interrupting.
404 * Then assign "struct device *dev"
405 */
406 struct net_device *dev = (struct net_device *)dev_id;
407 /* ... and check with hw if it's really ours */
408
409 /* paranoid */
410 if (!dev)
411 return;
412
413 /* Lock the device */
414 priv = netdev_priv(dev);
415 spin_lock(&priv->lock);
416
417 /* retrieve statusword: real netdevices use I/O instructions */
418 statusword = priv->status;
419 priv->status = 0;
420 if (statusword & WILC_WFI_RX_INTR) {
421 /* send it to WILC_WFI_rx for handling */
422 pkt = priv->rx_queue;
423 if (pkt) {
424 priv->rx_queue = pkt->next;
425 WILC_WFI_Rx(dev, pkt);
426 }
427 }
428 if (statusword & WILC_WFI_TX_INTR) {
429 /* a transmission is over: free the skb */
430 WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT);
431 dev_kfree_skb(priv->skb);
432 }
433
434 /* Unlock the device and we are done */
435 spin_unlock(&priv->lock);
436 if (pkt)
437 WILC_WFI_ReleaseBuffer(pkt); /* Do this outside the lock! */
438 return;
439}
440/**
441 * @brief WILC_WFI_NapiInterrupt
442 * @details A NAPI interrupt handler
443 * @param[in] irq:
444 * @param[in] dev_id:
445 * @param[in] pt_regs:
446 * @return NONE
447 * @author mdaftedar
448 * @date 01 MAR 2012
449 * @version 1.0
450 */
451static void WILC_WFI_NapiInterrupt(int irq, void *dev_id, struct pt_regs *regs)
452{
453 int statusword;
454 struct WILC_WFI_priv *priv;
455
456 /*
457 * As usual, check the "device" pointer for shared handlers.
458 * Then assign "struct device *dev"
459 */
460 struct net_device *dev = (struct net_device *)dev_id;
461 /* ... and check with hw if it's really ours */
462
463 /* paranoid */
464 if (!dev)
465 return;
466
467 /* Lock the device */
468 priv = netdev_priv(dev);
469 spin_lock(&priv->lock);
470
471 /* retrieve statusword: real netdevices use I/O instructions */
472 statusword = priv->status;
473 priv->status = 0;
474 if (statusword & WILC_WFI_RX_INTR) {
475 WILC_WFI_RxInts(dev, 0); /* Disable further interrupts */
476 napi_schedule(&priv->napi);
477 }
478 if (statusword & WILC_WFI_TX_INTR) {
479 /* a transmission is over: free the skb */
480
481 WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT);
482 dev_kfree_skb(priv->skb);
483 }
484
485 /* Unlock the device and we are done */
486 spin_unlock(&priv->lock);
487 return;
488}
489
490/**
491 * @brief MI_WFI_HwTx
492 * @details Transmit a packet (low level interface)
493 * @param[in] buf:
494 * @param[in] len:
495 * @param[in] net_device *dev:
496 * @return NONE
497 * @author mdaftedar
498 * @date 01 MAR 2012
499 * @version 1.0
500 */
501void WILC_WFI_HwTx(char *buf, int len, struct net_device *dev)
502{
503 /*
504 * This function deals with hw details. This interface loops
505 * back the packet to the other WILC_WFI interface (if any).
506 * In other words, this function implements the WILC_WFI behaviour,
507 * while all other procedures are rather device-independent
508 */
509 struct iphdr *ih;
510 struct net_device *dest;
511 struct WILC_WFI_priv *priv;
512 u32 *saddr, *daddr;
513 struct WILC_WFI_packet *tx_buffer;
514
515
516 /* I am paranoid. Ain't I? */
517 if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {
518 PRINT_D(RX_DBG, "WILC_WFI: Hmm... packet too short (%i octets)\n",
519 len);
520 return;
521 }
522
523 if (0) { /* enable this conditional to look at the data */
524 int i;
525 PRINT_D(RX_DBG, "len is %i", len);
526 for (i = 14; i < len; i++)
527 PRINT_D(RX_DBG, "TXdata[%d] %02x\n", i, buf[i] & 0xff);
528 /* PRINT_D(RX_DBG, "\n"); */
529 }
530 /*
531 * Ethhdr is 14 bytes, but the kernel arranges for iphdr
532 * to be aligned (i.e., ethhdr is unaligned)
533 */
534 ih = (struct iphdr *)(buf + sizeof(struct ethhdr));
535 saddr = &ih->saddr;
536 daddr = &ih->daddr;
537
538 ((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
539 ((u8 *)daddr)[2] ^= 1;
540
541 ih->check = 0; /* and rebuild the checksum (ip needs it) */
542 ih->check = ip_fast_csum((unsigned char *)ih, ih->ihl);
543
544
545 if (dev == WILC_WFI_devs[0])
546 PRINT_D(RX_DBG, "%08x:%05i --> %08x:%05i\n",
547 ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source),
548 ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest));
549 else
550 PRINT_D(RX_DBG, "%08x:%05i <-- %08x:%05i\n",
551 ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest),
552 ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source));
553
554 /*
555 * Ok, now the packet is ready for transmission: first simulate a
556 * receive interrupt on the twin device, then a
557 * transmission-done on the transmitting device
558 */
559 dest = WILC_WFI_devs[dev == WILC_WFI_devs[0] ? 1 : 0];
560 priv = netdev_priv(dest);
561
562 tx_buffer = WILC_WFI_GetTxBuffer(dev);
563 tx_buffer->datalen = len;
564 memcpy(tx_buffer->data, buf, len);
565 WILC_WFI_EnqueueBuf(dest, tx_buffer);
566 if (priv->rx_int_enabled) {
567 priv->status |= WILC_WFI_RX_INTR;
568 WILC_WFI_Interrupt(0, dest, NULL);
569 }
570
571 priv = netdev_priv(dev);
572 priv->tx_packetlen = len;
573 priv->tx_packetdata = buf;
574 priv->status |= WILC_WFI_TX_INTR;
575 if (lockup && ((priv->stats.tx_packets + 1) % lockup) == 0) {
576 /* Simulate a dropped transmit interrupt */
577 netif_stop_queue(dev);
578 PRINT_D(RX_DBG, "Simulate lockup at %ld, txp %ld\n", jiffies,
579 (unsigned long) priv->stats.tx_packets);
580 } else
581 WILC_WFI_Interrupt(0, dev, NULL);
582
583}
584
585/**
586 * @brief WILC_WFI_Tx
587 * @details Transmit a packet (called by the kernel)
588 * @param[in] sk_buff *skb:
589 * @param[in] net_device *dev:
590 * @return NONE
591 * @author mdaftedar
592 * @date 01 MAR 2012
593 * @version 1.0
594 */
595int WILC_WFI_Tx(struct sk_buff *skb, struct net_device *dev)
596{
597 int len;
598 char *data, shortpkt[ETH_ZLEN];
599 struct WILC_WFI_priv *priv = netdev_priv(dev);
600
601 /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
602
603 /* if(priv->monitor_flag) */
604 /* mac80211_hwsim_monitor_rx(skb); */
605
606
607 data = skb->data;
608 len = skb->len;
609
610 if (len < ETH_ZLEN) {
611 memset(shortpkt, 0, ETH_ZLEN);
612 memcpy(shortpkt, skb->data, skb->len);
613 len = ETH_ZLEN;
614 data = shortpkt;
615 }
616 dev->trans_start = jiffies; /* save the timestamp */
617
618 /* Remember the skb, so we can free it at interrupt time */
619 priv->skb = skb;
620
621 /* actual deliver of data is device-specific, and not shown here */
622 WILC_WFI_HwTx(data, len, dev);
623
624 return 0; /* Our simple device can not fail */
625}
626
627/**
628 * @brief WILC_WFI_TxTimeout
629 * @details Deal with a transmit timeout.
630 * @param[in] net_device *dev:
631 * @return NONE
632 * @author mdaftedar
633 * @date 01 MAR 2012
634 * @version 1.0
635 */
636void WILC_WFI_TxTimeout(struct net_device *dev)
637{
638 struct WILC_WFI_priv *priv = netdev_priv(dev);
639
640 PRINT_D(RX_DBG, "Transmit timeout at %ld, latency %ld\n", jiffies,
641 jiffies - dev->trans_start);
642 /* Simulate a transmission interrupt to get things moving */
643 priv->status = WILC_WFI_TX_INTR;
644 WILC_WFI_Interrupt(0, dev, NULL);
645 priv->stats.tx_errors++;
646 netif_wake_queue(dev);
647 return;
648}
649
650/**
651 * @brief WILC_WFI_Ioctl
652 * @details Ioctl commands
653 * @param[in] net_device *dev:
654 * @param[in] ifreq *rq
655 * @param[in] cmd:
656 * @return int : Return 0 on Success
657 * @author mdaftedar
658 * @date 01 MAR 2012
659 * @version 1.0
660 */
661int WILC_WFI_Ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
662{
663 PRINT_D(RX_DBG, "ioctl\n");
664 return 0;
665}
666
667/**
668 * @brief WILC_WFI_Stat
669 * @details Return statistics to the caller
670 * @param[in] net_device *dev:
671 * @return WILC_WFI_Stats : Return net_device_stats stucture with the
672 * network device driver private data contents.
673 * @author mdaftedar
674 * @date 01 MAR 2012
675 * @version 1.0
676 */
677struct net_device_stats *WILC_WFI_Stats(struct net_device *dev)
678{
679 struct WILC_WFI_priv *priv = netdev_priv(dev);
680 return &priv->stats;
681}
682
683/**
684 * @brief WILC_WFI_RebuildHeader
685 * @details This function is called to fill up an eth header, since arp is not
686 * available on the interface
687 * @param[in] sk_buff *skb:
688 * @return int : Return 0 on Success
689 * @author mdaftedar
690 * @date 01 MAR 2012
691 * @version 1.0
692 */
693int WILC_WFI_RebuildHeader(struct sk_buff *skb)
694{
695 struct ethhdr *eth = (struct ethhdr *) skb->data;
696 struct net_device *dev = skb->dev;
697
698 memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
699 memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
700 eth->h_dest[ETH_ALEN - 1] ^= 0x01; /* dest is us xor 1 */
701 return 0;
702}
703/**
704 * @brief WILC_WFI_RebuildHeader
705 * @details This function is called to fill up an eth header, since arp is not
706 * available on the interface
707 * @param[in] sk_buff *skb:
708 * @param[in] struct net_device *dev:
709 * @param[in] unsigned short type:
710 * @param[in] const void *saddr,
711 * @param[in] const void *daddr:
712 * @param[in] unsigned int len
713 * @return int : Return 0 on Success
714 * @author mdaftedar
715 * @date 01 MAR 2012
716 * @version 1.0
717 */
718int WILC_WFI_Header(struct sk_buff *skb, struct net_device *dev,
719 unsigned short type, const void *daddr, const void *saddr,
720 unsigned int len)
721{
722 struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN);
723
724 eth->h_proto = htons(type);
725 memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);
726 memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len);
727 eth->h_dest[ETH_ALEN - 1] ^= 0x01; /* dest is us xor 1 */
728 return dev->hard_header_len;
729}
730
731/**
732 * @brief WILC_WFI_ChangeMtu
733 * @details The "change_mtu" method is usually not needed.
734 * If you need it, it must be like this.
735 * @param[in] net_device *dev : Network Device Driver Structure
736 * @param[in] new_mtu :
737 * @return int : Returns 0 on Success.
738 * @author mdaftedar
739 * @date 01 MAR 2012
740 * @version 1.0
741 */
742int WILC_WFI_ChangeMtu(struct net_device *dev, int new_mtu)
743{
744 unsigned long flags;
745 struct WILC_WFI_priv *priv = netdev_priv(dev);
746 spinlock_t *lock = &priv->lock;
747
748 /* check ranges */
749 if ((new_mtu < 68) || (new_mtu > 1500))
750 return -EINVAL;
751 /*
752 * Do anything you need, and the accept the value
753 */
754 spin_lock_irqsave(lock, flags);
755 dev->mtu = new_mtu;
756 spin_unlock_irqrestore(lock, flags);
757 return 0; /* success */
758}
759
760static const struct header_ops WILC_WFI_header_ops = {
761 .create = WILC_WFI_Header,
762 .rebuild = WILC_WFI_RebuildHeader,
763 .cache = NULL, /* disable caching */
764};
765
766
767static const struct net_device_ops WILC_WFI_netdev_ops = {
768 .ndo_open = WILC_WFI_Open,
769 .ndo_stop = WILC_WFI_Release,
770 .ndo_set_config = WILC_WFI_Config,
771 .ndo_start_xmit = WILC_WFI_Tx,
772 .ndo_do_ioctl = WILC_WFI_Ioctl,
773 .ndo_get_stats = WILC_WFI_Stats,
774 .ndo_change_mtu = WILC_WFI_ChangeMtu,
775 .ndo_tx_timeout = WILC_WFI_TxTimeout,
776};
777
778/**
779 * @brief WILC_WFI_Init
780 * @details The init function (sometimes called probe).
781 * It is invoked by register_netdev()
782 * @param[in] net_device *dev:
783 * @return NONE
784 * @author mdaftedar
785 * @date 01 MAR 2012
786 * @version 1.0
787 */
788void WILC_WFI_Init(struct net_device *dev)
789{
790 struct WILC_WFI_priv *priv;
791
792
793 /*
794 * Then, assign other fields in dev, using ether_setup() and some
795 * hand assignments
796 */
797 ether_setup(dev); /* assign some of the fields */
798 /* 1- Allocate space */
799
800 dev->netdev_ops = &WILC_WFI_netdev_ops;
801 dev->header_ops = &WILC_WFI_header_ops;
802 dev->watchdog_timeo = timeout;
803 /* keep the default flags, just add NOARP */
804 dev->flags |= IFF_NOARP;
805 dev->features |= NETIF_F_NO_CSUM;
806 /*
807 * Then, initialize the priv field. This encloses the statistics
808 * and a few private fields.
809 */
810 priv = netdev_priv(dev);
811 memset(priv, 0, sizeof(struct WILC_WFI_priv));
812 priv->dev = dev;
813 netif_napi_add(dev, &priv->napi, WILC_WFI_Poll, 2);
814 /* The last parameter above is the NAPI "weight". */
815 spin_lock_init(&priv->lock);
816 WILC_WFI_RxInts(dev, 1); /* enable receive interrupts */
817 WILC_WFI_SetupPool(dev);
818}
819
820/**
821 * @brief WILC_WFI_Stat
822 * @details Return statistics to the caller
823 * @param[in] net_device *dev:
824 * @return WILC_WFI_Stats : Return net_device_stats stucture with the
825 * network device driver private data contents.
826 * @author mdaftedar
827 * @date 01 MAR 2012
828 * @version 1.0
829 */
830
831void WILC_WFI_Cleanup(void)
832{
833 int i;
834 struct WILC_WFI_priv *priv[2];
835
836 /*if(hwsim_mon!=NULL)
837 * {
838 * PRINT_D(RX_DBG, "Freeing monitor interface\n");
839 * unregister_netdev(hwsim_mon);
840 * free_netdev(hwsim_mon);
841 * }*/
842 for (i = 0; i < 2; i++) {
843 priv[i] = netdev_priv(WILC_WFI_devs[i]);
844
845 if (WILC_WFI_devs[i]) {
846 PRINT_D(RX_DBG, "Unregistering\n");
847 unregister_netdev(WILC_WFI_devs[i]);
848 WILC_WFI_TearDownPool(WILC_WFI_devs[i]);
849 free_netdev(WILC_WFI_devs[i]);
850 PRINT_D(RX_DBG, "[NETDEV]Stopping interface\n");
851 WILC_WFI_DeInitHostInt(WILC_WFI_devs[i]);
852 WILC_WFI_WiphyFree(WILC_WFI_devs[i]);
853 }
854
855 }
856 /* unregister_netdev(hwsim_mon); */
857 WILC_WFI_deinit_mon_interface();
858 return;
859}
860
861
862void StartConfigSim(void);
863
864
865
866
867
868
869
870/**
871 * @brief WILC_WFI_Stat
872 * @details Return statistics to the caller
873 * @param[in] net_device *dev:
874 * @return WILC_WFI_Stats : Return net_device_stats stucture with the
875 * network device driver private data contents.
876 * @author mdaftedar
877 * @date 01 MAR 2012
878 * @version 1.0
879 */
880int WILC_WFI_InitModule(void)
881{
882
883 int result, i, ret = -ENOMEM;
884 struct WILC_WFI_priv *priv[2], *netpriv;
885 struct wireless_dev *wdev;
886 WILC_WFI_Interrupt = use_napi ? WILC_WFI_NapiInterrupt : WILC_WFI_RegularInterrupt;
887 char buf[IFNAMSIZ];
888
889 for (i = 0; i < 2; i++) {
890
891 /* Allocate the net devices */
892 WILC_WFI_devs[i] = alloc_netdev(sizeof(struct WILC_WFI_priv), "wlan%d",
893 WILC_WFI_Init);
894 if (WILC_WFI_devs[i] == NULL)
895 goto out;
896 /* priv[i] = netdev_priv(WILC_WFI_devs[i]); */
897
898 wdev = WILC_WFI_WiphyRegister(WILC_WFI_devs[i]);
899 WILC_WFI_devs[i]->ieee80211_ptr = wdev;
900 netpriv = netdev_priv(WILC_WFI_devs[i]);
901 netpriv->dev->ieee80211_ptr = wdev;
902 netpriv->dev->ml_priv = netpriv;
903 wdev->netdev = netpriv->dev;
904
905 /*Registering the net device*/
906 result = register_netdev(WILC_WFI_devs[i]);
907 if (result)
908 PRINT_D(RX_DBG, "WILC_WFI: error %i registering device \"%s\"\n",
909 result, WILC_WFI_devs[i]->name);
910 else
911 ret = 0;
912 }
913
914
915 /*init atmel driver */
916 priv[0] = netdev_priv(WILC_WFI_devs[0]);
917 priv[1] = netdev_priv(WILC_WFI_devs[1]);
918
919 if (priv[1]->dev->ieee80211_ptr->wiphy->interface_modes && BIT(NL80211_IFTYPE_MONITOR)) {
920 /* snprintf(buf, IFNAMSIZ, "mon.%s", priv[1]->dev->name); */
921 /* WILC_WFI_init_mon_interface(); */
922 /* priv[1]->monitor_flag = 1; */
923
924 }
72ed4dc7 925 priv[0]->bCfgScanning = false;
c5c77ba1
JK
926 priv[0]->u32RcvdChCount = 0;
927
928 WILC_memset(priv[0]->au8AssociatedBss, 0xFF, ETH_ALEN);
929
930
931 /* ret = host_int_init(&priv[0]->hWILCWFIDrv); */
932 /*copy handle to the other driver*/
933 /* priv[1]->hWILCWFIDrv = priv[0]->hWILCWFIDrv; */
934 if (ret) {
935 PRINT_ER("Error Init Driver\n");
936 }
937
938
939out:
940 if (ret)
941 WILC_WFI_Cleanup();
942 return ret;
943
944
945}
946
947
948module_init(WILC_WFI_InitModule);
949module_exit(WILC_WFI_Cleanup);
950
951#endif