Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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