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