Staging: wlan-ng: Remove dead code from p80211netdev.c
[safe/jmp/linux-2.6] / drivers / staging / wlan-ng / p80211netdev.c
1 /* src/p80211/p80211knetdev.c
2 *
3 * Linux Kernel net device interface
4 *
5 * Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
6 * --------------------------------------------------------------------
7 *
8 * linux-wlan
9 *
10 *   The contents of this file are subject to the Mozilla Public
11 *   License Version 1.1 (the "License"); you may not use this file
12 *   except in compliance with the License. You may obtain a copy of
13 *   the License at http://www.mozilla.org/MPL/
14 *
15 *   Software distributed under the License is distributed on an "AS
16 *   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 *   implied. See the License for the specific language governing
18 *   rights and limitations under the License.
19 *
20 *   Alternatively, the contents of this file may be used under the
21 *   terms of the GNU Public License version 2 (the "GPL"), in which
22 *   case the provisions of the GPL are applicable instead of the
23 *   above.  If you wish to allow the use of your version of this file
24 *   only under the terms of the GPL and not to allow others to use
25 *   your version of this file under the MPL, indicate your decision
26 *   by deleting the provisions above and replace them with the notice
27 *   and other provisions required by the GPL.  If you do not delete
28 *   the provisions above, a recipient may use your version of this
29 *   file under either the MPL or the GPL.
30 *
31 * --------------------------------------------------------------------
32 *
33 * Inquiries regarding the linux-wlan Open Source project can be
34 * made directly to:
35 *
36 * AbsoluteValue Systems Inc.
37 * info@linux-wlan.com
38 * http://www.linux-wlan.com
39 *
40 * --------------------------------------------------------------------
41 *
42 * Portions of the development of this software were funded by
43 * Intersil Corporation as part of PRISM(R) chipset product development.
44 *
45 * --------------------------------------------------------------------
46 *
47 * The functions required for a Linux network device are defined here.
48 *
49 * --------------------------------------------------------------------
50 */
51
52 #include <linux/version.h>
53 #include <linux/module.h>
54 #include <linux/kernel.h>
55 #include <linux/sched.h>
56 #include <linux/types.h>
57 #include <linux/skbuff.h>
58 #include <linux/slab.h>
59 #include <linux/proc_fs.h>
60 #include <linux/interrupt.h>
61 #include <linux/netdevice.h>
62 #include <linux/kmod.h>
63 #include <linux/if_arp.h>
64 #include <linux/wireless.h>
65 #include <linux/sockios.h>
66 #include <linux/etherdevice.h>
67 #include <linux/if_ether.h>
68 #include <linux/byteorder/generic.h>
69 #include <linux/bitops.h>
70 #include <linux/uaccess.h>
71 #include <asm/byteorder.h>
72
73 #ifdef SIOCETHTOOL
74 #include <linux/ethtool.h>
75 #endif
76
77 #include <net/iw_handler.h>
78 #include <net/net_namespace.h>
79
80 /*================================================================*/
81 /* Project Includes */
82
83 #include "wlan_compat.h"
84 #include "p80211types.h"
85 #include "p80211hdr.h"
86 #include "p80211conv.h"
87 #include "p80211mgmt.h"
88 #include "p80211msg.h"
89 #include "p80211netdev.h"
90 #include "p80211ioctl.h"
91 #include "p80211req.h"
92 #include "p80211metastruct.h"
93 #include "p80211metadef.h"
94
95 /* Support functions */
96 static void p80211netdev_rx_bh(unsigned long arg);
97
98 /* netdevice method functions */
99 static int p80211knetdev_init(netdevice_t *netdev);
100 static struct net_device_stats *p80211knetdev_get_stats(netdevice_t *netdev);
101 static int p80211knetdev_open(netdevice_t *netdev);
102 static int p80211knetdev_stop(netdevice_t *netdev);
103 static int p80211knetdev_hard_start_xmit(struct sk_buff *skb,
104                                          netdevice_t *netdev);
105 static void p80211knetdev_set_multicast_list(netdevice_t *dev);
106 static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr,
107                                   int cmd);
108 static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr);
109 static void p80211knetdev_tx_timeout(netdevice_t *netdev);
110 static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc);
111
112 int wlan_watchdog = 5000;
113 module_param(wlan_watchdog, int, 0644);
114 MODULE_PARM_DESC(wlan_watchdog, "transmit timeout in milliseconds");
115
116 int wlan_wext_write = 1;
117 module_param(wlan_wext_write, int, 0644);
118 MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions");
119
120 /*----------------------------------------------------------------
121 * p80211knetdev_init
122 *
123 * Init method for a Linux netdevice.  Called in response to
124 * register_netdev.
125 *
126 * Arguments:
127 *       none
128 *
129 * Returns:
130 *       nothing
131 ----------------------------------------------------------------*/
132 static int p80211knetdev_init(netdevice_t *netdev)
133 {
134         /* Called in response to register_netdev */
135         /* This is usually the probe function, but the probe has */
136         /* already been done by the MSD and the create_kdev */
137         /* function.  All we do here is return success */
138         return 0;
139 }
140
141 /*----------------------------------------------------------------
142 * p80211knetdev_get_stats
143 *
144 * Statistics retrieval for linux netdevices.  Here we're reporting
145 * the Linux i/f level statistics.  Hence, for the primary numbers,
146 * we don't want to report the numbers from the MIB.  Eventually,
147 * it might be useful to collect some of the error counters though.
148 *
149 * Arguments:
150 *       netdev          Linux netdevice
151 *
152 * Returns:
153 *       the address of the statistics structure
154 ----------------------------------------------------------------*/
155 static struct net_device_stats *p80211knetdev_get_stats(netdevice_t *netdev)
156 {
157         wlandevice_t *wlandev = netdev->ml_priv;
158
159         /* TODO: review the MIB stats for items that correspond to
160            linux stats */
161
162         return &(wlandev->linux_stats);
163 }
164
165 /*----------------------------------------------------------------
166 * p80211knetdev_open
167 *
168 * Linux netdevice open method.  Following a successful call here,
169 * the device is supposed to be ready for tx and rx.  In our
170 * situation that may not be entirely true due to the state of the
171 * MAC below.
172 *
173 * Arguments:
174 *       netdev          Linux network device structure
175 *
176 * Returns:
177 *       zero on success, non-zero otherwise
178 ----------------------------------------------------------------*/
179 static int p80211knetdev_open(netdevice_t *netdev)
180 {
181         int result = 0;         /* success */
182         wlandevice_t *wlandev = netdev->ml_priv;
183
184         /* Check to make sure the MSD is running */
185         if (wlandev->msdstate != WLAN_MSD_RUNNING)
186                 return -ENODEV;
187
188         /* Tell the MSD to open */
189         if (wlandev->open != NULL) {
190                 result = wlandev->open(wlandev);
191                 if (result == 0) {
192                         netif_start_queue(wlandev->netdev);
193                         wlandev->state = WLAN_DEVICE_OPEN;
194                 }
195         } else {
196                 result = -EAGAIN;
197         }
198
199         return result;
200 }
201
202 /*----------------------------------------------------------------
203 * p80211knetdev_stop
204 *
205 * Linux netdevice stop (close) method.  Following this call,
206 * no frames should go up or down through this interface.
207 *
208 * Arguments:
209 *       netdev          Linux network device structure
210 *
211 * Returns:
212 *       zero on success, non-zero otherwise
213 ----------------------------------------------------------------*/
214 static int p80211knetdev_stop(netdevice_t *netdev)
215 {
216         int result = 0;
217         wlandevice_t *wlandev = netdev->ml_priv;
218
219         if (wlandev->close != NULL)
220                 result = wlandev->close(wlandev);
221
222         netif_stop_queue(wlandev->netdev);
223         wlandev->state = WLAN_DEVICE_CLOSED;
224
225         return result;
226 }
227
228 /*----------------------------------------------------------------
229 * p80211netdev_rx
230 *
231 * Frame receive function called by the mac specific driver.
232 *
233 * Arguments:
234 *       wlandev         WLAN network device structure
235 *       skb             skbuff containing a full 802.11 frame.
236 * Returns:
237 *       nothing
238 * Side effects:
239 *
240 ----------------------------------------------------------------*/
241 void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb)
242 {
243         /* Enqueue for post-irq processing */
244         skb_queue_tail(&wlandev->nsd_rxq, skb);
245
246         tasklet_schedule(&wlandev->rx_bh);
247
248         return;
249 }
250
251 /*----------------------------------------------------------------
252 * p80211netdev_rx_bh
253 *
254 * Deferred processing of all received frames.
255 *
256 * Arguments:
257 *       wlandev         WLAN network device structure
258 *       skb             skbuff containing a full 802.11 frame.
259 * Returns:
260 *       nothing
261 * Side effects:
262 *
263 ----------------------------------------------------------------*/
264 static void p80211netdev_rx_bh(unsigned long arg)
265 {
266         wlandevice_t *wlandev = (wlandevice_t *) arg;
267         struct sk_buff *skb = NULL;
268         netdevice_t *dev = wlandev->netdev;
269         p80211_hdr_a3_t *hdr;
270         u16 fc;
271
272         /* Let's empty our our queue */
273         while ((skb = skb_dequeue(&wlandev->nsd_rxq))) {
274                 if (wlandev->state == WLAN_DEVICE_OPEN) {
275
276                         if (dev->type != ARPHRD_ETHER) {
277                                 /* RAW frame; we shouldn't convert it */
278                                 /* XXX Append the Prism Header here instead. */
279
280                                 /* set up various data fields */
281                                 skb->dev = dev;
282                                 skb_reset_mac_header(skb);
283                                 skb->ip_summed = CHECKSUM_NONE;
284                                 skb->pkt_type = PACKET_OTHERHOST;
285                                 skb->protocol = htons(ETH_P_80211_RAW);
286                                 dev->last_rx = jiffies;
287
288                                 wlandev->linux_stats.rx_packets++;
289                                 wlandev->linux_stats.rx_bytes += skb->len;
290                                 netif_rx_ni(skb);
291                                 continue;
292                         } else {
293                                 hdr = (p80211_hdr_a3_t *) skb->data;
294                                 fc = le16_to_cpu(hdr->fc);
295                                 if (p80211_rx_typedrop(wlandev, fc)) {
296                                         dev_kfree_skb(skb);
297                                         continue;
298                                 }
299
300                                 /* perform mcast filtering */
301                                 if (wlandev->netdev->flags & IFF_ALLMULTI) {
302                                         /* allow my local address through */
303                                         if (memcmp
304                                             (hdr->a1, wlandev->netdev->dev_addr,
305                                              ETH_ALEN) != 0) {
306                                                 /* but reject anything else that isn't multicast */
307                                                 if (!(hdr->a1[0] & 0x01)) {
308                                                         dev_kfree_skb(skb);
309                                                         continue;
310                                                 }
311                                         }
312                                 }
313
314                                 if (skb_p80211_to_ether
315                                     (wlandev, wlandev->ethconv, skb) == 0) {
316                                         skb->dev->last_rx = jiffies;
317                                         wlandev->linux_stats.rx_packets++;
318                                         wlandev->linux_stats.rx_bytes +=
319                                             skb->len;
320                                         netif_rx_ni(skb);
321                                         continue;
322                                 }
323                                 pr_debug("p80211_to_ether failed.\n");
324                         }
325                 }
326                 dev_kfree_skb(skb);
327         }
328 }
329
330 /*----------------------------------------------------------------
331 * p80211knetdev_hard_start_xmit
332 *
333 * Linux netdevice method for transmitting a frame.
334 *
335 * Arguments:
336 *       skb     Linux sk_buff containing the frame.
337 *       netdev  Linux netdevice.
338 *
339 * Side effects:
340 *       If the lower layers report that buffers are full. netdev->tbusy
341 *       will be set to prevent higher layers from sending more traffic.
342 *
343 *       Note: If this function returns non-zero, higher layers retain
344 *             ownership of the skb.
345 *
346 * Returns:
347 *       zero on success, non-zero on failure.
348 ----------------------------------------------------------------*/
349 static int p80211knetdev_hard_start_xmit(struct sk_buff *skb,
350                                          netdevice_t *netdev)
351 {
352         int result = 0;
353         int txresult = -1;
354         wlandevice_t *wlandev = netdev->ml_priv;
355         p80211_hdr_t p80211_hdr;
356         p80211_metawep_t p80211_wep;
357
358         if (skb == NULL)
359                 return 0;
360
361         if (wlandev->state != WLAN_DEVICE_OPEN) {
362                 result = 1;
363                 goto failed;
364         }
365
366         memset(&p80211_hdr, 0, sizeof(p80211_hdr_t));
367         memset(&p80211_wep, 0, sizeof(p80211_metawep_t));
368
369         if (netif_queue_stopped(netdev)) {
370                 pr_debug("called when queue stopped.\n");
371                 result = 1;
372                 goto failed;
373         }
374
375         netif_stop_queue(netdev);
376
377         /* Check to see that a valid mode is set */
378         switch (wlandev->macmode) {
379         case WLAN_MACMODE_IBSS_STA:
380         case WLAN_MACMODE_ESS_STA:
381         case WLAN_MACMODE_ESS_AP:
382                 break;
383         default:
384                 /* Mode isn't set yet, just drop the frame
385                  * and return success .
386                  * TODO: we need a saner way to handle this
387                  */
388                 if (skb->protocol != ETH_P_80211_RAW) {
389                         netif_start_queue(wlandev->netdev);
390                         printk(KERN_NOTICE
391                                "Tx attempt prior to association, frame dropped.\n");
392                         wlandev->linux_stats.tx_dropped++;
393                         result = 0;
394                         goto failed;
395                 }
396                 break;
397         }
398
399         /* Check for raw transmits */
400         if (skb->protocol == ETH_P_80211_RAW) {
401                 if (!capable(CAP_NET_ADMIN)) {
402                         result = 1;
403                         goto failed;
404                 }
405                 /* move the header over */
406                 memcpy(&p80211_hdr, skb->data, sizeof(p80211_hdr_t));
407                 skb_pull(skb, sizeof(p80211_hdr_t));
408         } else {
409                 if (skb_ether_to_p80211
410                     (wlandev, wlandev->ethconv, skb, &p80211_hdr,
411                      &p80211_wep) != 0) {
412                         /* convert failed */
413                         pr_debug("ether_to_80211(%d) failed.\n",
414                                wlandev->ethconv);
415                         result = 1;
416                         goto failed;
417                 }
418         }
419         if (wlandev->txframe == NULL) {
420                 result = 1;
421                 goto failed;
422         }
423
424         netdev->trans_start = jiffies;
425
426         wlandev->linux_stats.tx_packets++;
427         /* count only the packet payload */
428         wlandev->linux_stats.tx_bytes += skb->len;
429
430         txresult = wlandev->txframe(wlandev, skb, &p80211_hdr, &p80211_wep);
431
432         if (txresult == 0) {
433                 /* success and more buf */
434                 /* avail, re: hw_txdata */
435                 netif_wake_queue(wlandev->netdev);
436                 result = 0;
437         } else if (txresult == 1) {
438                 /* success, no more avail */
439                 pr_debug("txframe success, no more bufs\n");
440                 /* netdev->tbusy = 1;  don't set here, irqhdlr */
441                 /*   may have already cleared it */
442                 result = 0;
443         } else if (txresult == 2) {
444                 /* alloc failure, drop frame */
445                 pr_debug("txframe returned alloc_fail\n");
446                 result = 1;
447         } else {
448                 /* buffer full or queue busy, drop frame. */
449                 pr_debug("txframe returned full or busy\n");
450                 result = 1;
451         }
452
453 failed:
454         /* Free up the WEP buffer if it's not the same as the skb */
455         if ((p80211_wep.data) && (p80211_wep.data != skb->data))
456                 kfree(p80211_wep.data);
457
458         /* we always free the skb here, never in a lower level. */
459         if (!result)
460                 dev_kfree_skb(skb);
461
462         return result;
463 }
464
465 /*----------------------------------------------------------------
466 * p80211knetdev_set_multicast_list
467 *
468 * Called from higher lavers whenever there's a need to set/clear
469 * promiscuous mode or rewrite the multicast list.
470 *
471 * Arguments:
472 *       none
473 *
474 * Returns:
475 *       nothing
476 ----------------------------------------------------------------*/
477 static void p80211knetdev_set_multicast_list(netdevice_t *dev)
478 {
479         wlandevice_t *wlandev = dev->ml_priv;
480
481         /* TODO:  real multicast support as well */
482
483         if (wlandev->set_multicast_list)
484                 wlandev->set_multicast_list(wlandev, dev);
485
486 }
487
488 #ifdef SIOCETHTOOL
489
490 static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr)
491 {
492         u32 ethcmd;
493         struct ethtool_drvinfo info;
494         struct ethtool_value edata;
495
496         memset(&info, 0, sizeof(info));
497         memset(&edata, 0, sizeof(edata));
498
499         if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
500                 return -EFAULT;
501
502         switch (ethcmd) {
503         case ETHTOOL_GDRVINFO:
504                 info.cmd = ethcmd;
505                 snprintf(info.driver, sizeof(info.driver), "p80211_%s",
506                          wlandev->nsdname);
507                 snprintf(info.version, sizeof(info.version), "%s",
508                          WLAN_RELEASE);
509
510                 if (copy_to_user(useraddr, &info, sizeof(info)))
511                         return -EFAULT;
512                 return 0;
513 #ifdef ETHTOOL_GLINK
514         case ETHTOOL_GLINK:
515                 edata.cmd = ethcmd;
516
517                 if (wlandev->linkstatus &&
518                     (wlandev->macmode != WLAN_MACMODE_NONE)) {
519                         edata.data = 1;
520                 } else {
521                         edata.data = 0;
522                 }
523
524                 if (copy_to_user(useraddr, &edata, sizeof(edata)))
525                         return -EFAULT;
526                 return 0;
527         }
528 #endif
529
530         return -EOPNOTSUPP;
531 }
532
533 #endif
534
535 /*----------------------------------------------------------------
536 * p80211knetdev_do_ioctl
537 *
538 * Handle an ioctl call on one of our devices.  Everything Linux
539 * ioctl specific is done here.  Then we pass the contents of the
540 * ifr->data to the request message handler.
541 *
542 * Arguments:
543 *       dev     Linux kernel netdevice
544 *       ifr     Our private ioctl request structure, typed for the
545 *               generic struct ifreq so we can use ptr to func
546 *               w/o cast.
547 *
548 * Returns:
549 *       zero on success, a negative errno on failure.  Possible values:
550 *               -ENETDOWN Device isn't up.
551 *               -EBUSY  cmd already in progress
552 *               -ETIME  p80211 cmd timed out (MSD may have its own timers)
553 *               -EFAULT memory fault copying msg from user buffer
554 *               -ENOMEM unable to allocate kernel msg buffer
555 *               -ENOSYS bad magic, it the cmd really for us?
556 *               -EintR  sleeping on cmd, awakened by signal, cmd cancelled.
557 *
558 * Call Context:
559 *       Process thread (ioctl caller).  TODO: SMP support may require
560 *       locks.
561 ----------------------------------------------------------------*/
562 static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd)
563 {
564         int result = 0;
565         p80211ioctl_req_t *req = (p80211ioctl_req_t *) ifr;
566         wlandevice_t *wlandev = dev->ml_priv;
567         u8 *msgbuf;
568
569         pr_debug("rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len);
570
571 #ifdef SIOCETHTOOL
572         if (cmd == SIOCETHTOOL) {
573                 result =
574                     p80211netdev_ethtool(wlandev, (void __user *)ifr->ifr_data);
575                 goto bail;
576         }
577 #endif
578
579         /* Test the magic, assume ifr is good if it's there */
580         if (req->magic != P80211_IOCTL_MAGIC) {
581                 result = -ENOSYS;
582                 goto bail;
583         }
584
585         if (cmd == P80211_IFTEST) {
586                 result = 0;
587                 goto bail;
588         } else if (cmd != P80211_IFREQ) {
589                 result = -ENOSYS;
590                 goto bail;
591         }
592
593         /* Allocate a buf of size req->len */
594         if ((msgbuf = kmalloc(req->len, GFP_KERNEL))) {
595                 if (copy_from_user(msgbuf, (void __user *)req->data, req->len))
596                         result = -EFAULT;
597                 else
598                         result = p80211req_dorequest(wlandev, msgbuf);
599
600                 if (result == 0) {
601                         if (copy_to_user
602                             ((void __user *)req->data, msgbuf, req->len)) {
603                                 result = -EFAULT;
604                         }
605                 }
606                 kfree(msgbuf);
607         } else {
608                 result = -ENOMEM;
609         }
610 bail:
611         return result;          /* If allocate,copyfrom or copyto fails, return errno */
612 }
613
614 /*----------------------------------------------------------------
615 * p80211knetdev_set_mac_address
616 *
617 * Handles the ioctl for changing the MACAddress of a netdevice
618 *
619 * references: linux/netdevice.h and drivers/net/net_init.c
620 *
621 * NOTE: [MSM] We only prevent address changes when the netdev is
622 * up.  We don't control anything based on dot11 state.  If the
623 * address is changed on a STA that's currently associated, you
624 * will probably lose the ability to send and receive data frames.
625 * Just be aware.  Therefore, this should usually only be done
626 * prior to scan/join/auth/assoc.
627 *
628 * Arguments:
629 *       dev     netdevice struct
630 *       addr    the new MACAddress (a struct)
631 *
632 * Returns:
633 *       zero on success, a negative errno on failure.  Possible values:
634 *               -EBUSY  device is bussy (cmd not possible)
635 *               -and errors returned by: p80211req_dorequest(..)
636 *
637 * by: Collin R. Mulliner <collin@mulliner.org>
638 ----------------------------------------------------------------*/
639 static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr)
640 {
641         struct sockaddr *new_addr = addr;
642         p80211msg_dot11req_mibset_t dot11req;
643         p80211item_unk392_t *mibattr;
644         p80211item_pstr6_t *macaddr;
645         p80211item_uint32_t *resultcode;
646         int result = 0;
647
648         /* If we're running, we don't allow MAC address changes */
649         if (netif_running(dev))
650                 return -EBUSY;
651
652         /* Set up some convenience pointers. */
653         mibattr = &dot11req.mibattribute;
654         macaddr = (p80211item_pstr6_t *)&mibattr->data;
655         resultcode = &dot11req.resultcode;
656
657         /* Set up a dot11req_mibset */
658         memset(&dot11req, 0, sizeof(p80211msg_dot11req_mibset_t));
659         dot11req.msgcode = DIDmsg_dot11req_mibset;
660         dot11req.msglen = sizeof(p80211msg_dot11req_mibset_t);
661         memcpy(dot11req.devname,
662                ((wlandevice_t *) dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1);
663
664         /* Set up the mibattribute argument */
665         mibattr->did = DIDmsg_dot11req_mibset_mibattribute;
666         mibattr->status = P80211ENUM_msgitem_status_data_ok;
667         mibattr->len = sizeof(mibattr->data);
668
669         macaddr->did = DIDmib_dot11mac_dot11OperationTable_dot11MACAddress;
670         macaddr->status = P80211ENUM_msgitem_status_data_ok;
671         macaddr->len = sizeof(macaddr->data);
672         macaddr->data.len = ETH_ALEN;
673         memcpy(&macaddr->data.data, new_addr->sa_data, ETH_ALEN);
674
675         /* Set up the resultcode argument */
676         resultcode->did = DIDmsg_dot11req_mibset_resultcode;
677         resultcode->status = P80211ENUM_msgitem_status_no_value;
678         resultcode->len = sizeof(resultcode->data);
679         resultcode->data = 0;
680
681         /* now fire the request */
682         result = p80211req_dorequest(dev->ml_priv, (u8 *)&dot11req);
683
684         /* If the request wasn't successful, report an error and don't
685          * change the netdev address
686          */
687         if (result != 0 || resultcode->data != P80211ENUM_resultcode_success) {
688                 printk(KERN_ERR
689                        "Low-level driver failed dot11req_mibset(dot11MACAddress).\n");
690                 result = -EADDRNOTAVAIL;
691         } else {
692                 /* everything's ok, change the addr in netdev */
693                 memcpy(dev->dev_addr, new_addr->sa_data, dev->addr_len);
694         }
695
696         return result;
697 }
698
699 static int wlan_change_mtu(netdevice_t *dev, int new_mtu)
700 {
701         /* 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap)
702            and another 8 for wep. */
703         if ((new_mtu < 68) || (new_mtu > (2312 - 20 - 8)))
704                 return -EINVAL;
705
706         dev->mtu = new_mtu;
707
708         return 0;
709 }
710
711 /*----------------------------------------------------------------
712 * wlan_setup
713 *
714 * Roughly matches the functionality of ether_setup.  Here
715 * we set up any members of the wlandevice structure that are common
716 * to all devices.  Additionally, we allocate a linux 'struct device'
717 * and perform the same setup as ether_setup.
718 *
719 * Note: It's important that the caller have setup the wlandev->name
720 *       ptr prior to calling this function.
721 *
722 * Arguments:
723 *       wlandev         ptr to the wlandev structure for the
724 *                       interface.
725 * Returns:
726 *       zero on success, non-zero otherwise.
727 * Call Context:
728 *       Should be process thread.  We'll assume it might be
729 *       interrupt though.  When we add support for statically
730 *       compiled drivers, this function will be called in the
731 *       context of the kernel startup code.
732 ----------------------------------------------------------------*/
733 int wlan_setup(wlandevice_t *wlandev)
734 {
735         int result = 0;
736         netdevice_t *dev;
737
738         /* Set up the wlandev */
739         wlandev->state = WLAN_DEVICE_CLOSED;
740         wlandev->ethconv = WLAN_ETHCONV_8021h;
741         wlandev->macmode = WLAN_MACMODE_NONE;
742
743         /* Set up the rx queue */
744         skb_queue_head_init(&wlandev->nsd_rxq);
745         tasklet_init(&wlandev->rx_bh,
746                      p80211netdev_rx_bh, (unsigned long)wlandev);
747
748         /* Allocate and initialize the struct device */
749         dev = alloc_netdev(0, "wlan%d", ether_setup);
750         if (dev == NULL) {
751                 printk(KERN_ERR "Failed to alloc netdev.\n");
752                 result = 1;
753         } else {
754                 wlandev->netdev = dev;
755                 dev->ml_priv = wlandev;
756                 dev->hard_start_xmit = p80211knetdev_hard_start_xmit;
757                 dev->get_stats = p80211knetdev_get_stats;
758                 dev->init = p80211knetdev_init;
759                 dev->open = p80211knetdev_open;
760                 dev->stop = p80211knetdev_stop;
761
762 #if (WIRELESS_EXT < 21)
763                 dev->get_wireless_stats = p80211wext_get_wireless_stats;
764 #endif
765                 dev->wireless_handlers = &p80211wext_handler_def;
766
767                 netif_stop_queue(dev);
768                 netif_carrier_off(dev);
769         }
770
771         return result;
772 }
773
774 /*----------------------------------------------------------------
775 * wlan_unsetup
776 *
777 * This function is paired with the wlan_setup routine.  It should
778 * be called after unregister_wlandev.  Basically, all it does is
779 * free the 'struct device' that's associated with the wlandev.
780 * We do it here because the 'struct device' isn't allocated
781 * explicitly in the driver code, it's done in wlan_setup.  To
782 * do the free in the driver might seem like 'magic'.
783 *
784 * Arguments:
785 *       wlandev         ptr to the wlandev structure for the
786 *                       interface.
787 * Returns:
788 *       zero on success, non-zero otherwise.
789 * Call Context:
790 *       Should be process thread.  We'll assume it might be
791 *       interrupt though.  When we add support for statically
792 *       compiled drivers, this function will be called in the
793 *       context of the kernel startup code.
794 ----------------------------------------------------------------*/
795 int wlan_unsetup(wlandevice_t *wlandev)
796 {
797         int result = 0;
798
799         tasklet_kill(&wlandev->rx_bh);
800
801         if (wlandev->netdev == NULL) {
802                 printk(KERN_ERR "called without wlandev->netdev set.\n");
803                 result = 1;
804         } else {
805                 free_netdev(wlandev->netdev);
806                 wlandev->netdev = NULL;
807         }
808
809         return 0;
810 }
811
812 /*----------------------------------------------------------------
813 * register_wlandev
814 *
815 * Roughly matches the functionality of register_netdev.  This function
816 * is called after the driver has successfully probed and set up the
817 * resources for the device.  It's now ready to become a named device
818 * in the Linux system.
819 *
820 * First we allocate a name for the device (if not already set), then
821 * we call the Linux function register_netdevice.
822 *
823 * Arguments:
824 *       wlandev         ptr to the wlandev structure for the
825 *                       interface.
826 * Returns:
827 *       zero on success, non-zero otherwise.
828 * Call Context:
829 *       Can be either interrupt or not.
830 ----------------------------------------------------------------*/
831 int register_wlandev(wlandevice_t *wlandev)
832 {
833         int i = 0;
834
835         i = register_netdev(wlandev->netdev);
836         if (i)
837                 return i;
838
839         return 0;
840 }
841
842 /*----------------------------------------------------------------
843 * unregister_wlandev
844 *
845 * Roughly matches the functionality of unregister_netdev.  This
846 * function is called to remove a named device from the system.
847 *
848 * First we tell linux that the device should no longer exist.
849 * Then we remove it from the list of known wlan devices.
850 *
851 * Arguments:
852 *       wlandev         ptr to the wlandev structure for the
853 *                       interface.
854 * Returns:
855 *       zero on success, non-zero otherwise.
856 * Call Context:
857 *       Can be either interrupt or not.
858 ----------------------------------------------------------------*/
859 int unregister_wlandev(wlandevice_t *wlandev)
860 {
861         struct sk_buff *skb;
862
863         unregister_netdev(wlandev->netdev);
864
865         /* Now to clean out the rx queue */
866         while ((skb = skb_dequeue(&wlandev->nsd_rxq)))
867                 dev_kfree_skb(skb);
868
869         return 0;
870 }
871
872 /*----------------------------------------------------------------
873 * p80211netdev_hwremoved
874 *
875 * Hardware removed notification. This function should be called
876 * immediately after an MSD has detected that the underlying hardware
877 * has been yanked out from under us.  The primary things we need
878 * to do are:
879 *   - Mark the wlandev
880 *   - Prevent any further traffic from the knetdev i/f
881 *   - Prevent any further requests from mgmt i/f
882 *   - If there are any waitq'd mgmt requests or mgmt-frame exchanges,
883 *     shut them down.
884 *   - Call the MSD hwremoved function.
885 *
886 * The remainder of the cleanup will be handled by unregister().
887 * Our primary goal here is to prevent as much tickling of the MSD
888 * as possible since the MSD is already in a 'wounded' state.
889 *
890 * TODO: As new features are added, this function should be
891 *       updated.
892 *
893 * Arguments:
894 *       wlandev         WLAN network device structure
895 * Returns:
896 *       nothing
897 * Side effects:
898 *
899 * Call context:
900 *       Usually interrupt.
901 ----------------------------------------------------------------*/
902 void p80211netdev_hwremoved(wlandevice_t *wlandev)
903 {
904         wlandev->hwremoved = 1;
905         if (wlandev->state == WLAN_DEVICE_OPEN)
906                 netif_stop_queue(wlandev->netdev);
907
908         netif_device_detach(wlandev->netdev);
909 }
910
911 /*----------------------------------------------------------------
912 * p80211_rx_typedrop
913 *
914 * Classifies the frame, increments the appropriate counter, and
915 * returns 0|1|2 indicating whether the driver should handle, ignore, or
916 * drop the frame
917 *
918 * Arguments:
919 *       wlandev         wlan device structure
920 *       fc              frame control field
921 *
922 * Returns:
923 *       zero if the frame should be handled by the driver,
924 *       one if the frame should be ignored
925 *       anything else means we drop it.
926 *
927 * Side effects:
928 *
929 * Call context:
930 *       interrupt
931 ----------------------------------------------------------------*/
932 static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc)
933 {
934         u16 ftype;
935         u16 fstype;
936         int drop = 0;
937         /* Classify frame, increment counter */
938         ftype = WLAN_GET_FC_FTYPE(fc);
939         fstype = WLAN_GET_FC_FSTYPE(fc);
940 #if 0
941         pr_debug("rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype);
942 #endif
943         switch (ftype) {
944         case WLAN_FTYPE_MGMT:
945                 if ((wlandev->netdev->flags & IFF_PROMISC) ||
946                     (wlandev->netdev->flags & IFF_ALLMULTI)) {
947                         drop = 1;
948                         break;
949                 }
950                 pr_debug("rx'd mgmt:\n");
951                 wlandev->rx.mgmt++;
952                 switch (fstype) {
953                 case WLAN_FSTYPE_ASSOCREQ:
954                         /* printk("assocreq"); */
955                         wlandev->rx.assocreq++;
956                         break;
957                 case WLAN_FSTYPE_ASSOCRESP:
958                         /* printk("assocresp"); */
959                         wlandev->rx.assocresp++;
960                         break;
961                 case WLAN_FSTYPE_REASSOCREQ:
962                         /* printk("reassocreq"); */
963                         wlandev->rx.reassocreq++;
964                         break;
965                 case WLAN_FSTYPE_REASSOCRESP:
966                         /* printk("reassocresp"); */
967                         wlandev->rx.reassocresp++;
968                         break;
969                 case WLAN_FSTYPE_PROBEREQ:
970                         /* printk("probereq"); */
971                         wlandev->rx.probereq++;
972                         break;
973                 case WLAN_FSTYPE_PROBERESP:
974                         /* printk("proberesp"); */
975                         wlandev->rx.proberesp++;
976                         break;
977                 case WLAN_FSTYPE_BEACON:
978                         /* printk("beacon"); */
979                         wlandev->rx.beacon++;
980                         break;
981                 case WLAN_FSTYPE_ATIM:
982                         /* printk("atim"); */
983                         wlandev->rx.atim++;
984                         break;
985                 case WLAN_FSTYPE_DISASSOC:
986                         /* printk("disassoc"); */
987                         wlandev->rx.disassoc++;
988                         break;
989                 case WLAN_FSTYPE_AUTHEN:
990                         /* printk("authen"); */
991                         wlandev->rx.authen++;
992                         break;
993                 case WLAN_FSTYPE_DEAUTHEN:
994                         /* printk("deauthen"); */
995                         wlandev->rx.deauthen++;
996                         break;
997                 default:
998                         /* printk("unknown"); */
999                         wlandev->rx.mgmt_unknown++;
1000                         break;
1001                 }
1002                 /* printk("\n"); */
1003                 drop = 2;
1004                 break;
1005
1006         case WLAN_FTYPE_CTL:
1007                 if ((wlandev->netdev->flags & IFF_PROMISC) ||
1008                     (wlandev->netdev->flags & IFF_ALLMULTI)) {
1009                         drop = 1;
1010                         break;
1011                 }
1012                 pr_debug("rx'd ctl:\n");
1013                 wlandev->rx.ctl++;
1014                 switch (fstype) {
1015                 case WLAN_FSTYPE_PSPOLL:
1016                         /* printk("pspoll"); */
1017                         wlandev->rx.pspoll++;
1018                         break;
1019                 case WLAN_FSTYPE_RTS:
1020                         /* printk("rts"); */
1021                         wlandev->rx.rts++;
1022                         break;
1023                 case WLAN_FSTYPE_CTS:
1024                         /* printk("cts"); */
1025                         wlandev->rx.cts++;
1026                         break;
1027                 case WLAN_FSTYPE_ACK:
1028                         /* printk("ack"); */
1029                         wlandev->rx.ack++;
1030                         break;
1031                 case WLAN_FSTYPE_CFEND:
1032                         /* printk("cfend"); */
1033                         wlandev->rx.cfend++;
1034                         break;
1035                 case WLAN_FSTYPE_CFENDCFACK:
1036                         /* printk("cfendcfack"); */
1037                         wlandev->rx.cfendcfack++;
1038                         break;
1039                 default:
1040                         /* printk("unknown"); */
1041                         wlandev->rx.ctl_unknown++;
1042                         break;
1043                 }
1044                 /* printk("\n"); */
1045                 drop = 2;
1046                 break;
1047
1048         case WLAN_FTYPE_DATA:
1049                 wlandev->rx.data++;
1050                 switch (fstype) {
1051                 case WLAN_FSTYPE_DATAONLY:
1052                         wlandev->rx.dataonly++;
1053                         break;
1054                 case WLAN_FSTYPE_DATA_CFACK:
1055                         wlandev->rx.data_cfack++;
1056                         break;
1057                 case WLAN_FSTYPE_DATA_CFPOLL:
1058                         wlandev->rx.data_cfpoll++;
1059                         break;
1060                 case WLAN_FSTYPE_DATA_CFACK_CFPOLL:
1061                         wlandev->rx.data__cfack_cfpoll++;
1062                         break;
1063                 case WLAN_FSTYPE_NULL:
1064                         pr_debug("rx'd data:null\n");
1065                         wlandev->rx.null++;
1066                         break;
1067                 case WLAN_FSTYPE_CFACK:
1068                         pr_debug("rx'd data:cfack\n");
1069                         wlandev->rx.cfack++;
1070                         break;
1071                 case WLAN_FSTYPE_CFPOLL:
1072                         pr_debug("rx'd data:cfpoll\n");
1073                         wlandev->rx.cfpoll++;
1074                         break;
1075                 case WLAN_FSTYPE_CFACK_CFPOLL:
1076                         pr_debug("rx'd data:cfack_cfpoll\n");
1077                         wlandev->rx.cfack_cfpoll++;
1078                         break;
1079                 default:
1080                         /* printk("unknown"); */
1081                         wlandev->rx.data_unknown++;
1082                         break;
1083                 }
1084
1085                 break;
1086         }
1087         return drop;
1088 }
1089
1090 static void p80211knetdev_tx_timeout(netdevice_t *netdev)
1091 {
1092         wlandevice_t *wlandev = netdev->ml_priv;
1093
1094         if (wlandev->tx_timeout) {
1095                 wlandev->tx_timeout(wlandev);
1096         } else {
1097                 printk(KERN_WARNING "Implement tx_timeout for %s\n",
1098                        wlandev->nsdname);
1099                 netif_wake_queue(wlandev->netdev);
1100         }
1101 }