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