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