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