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