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