linux/drivers/staging/wlan-ng/prism2sta.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
   2/* src/prism2/driver/prism2sta.c
   3 *
   4 * Implements the station functionality for prism2
   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 * This file implements the module and linux pcmcia routines for the
  49 * prism2 driver.
  50 *
  51 * --------------------------------------------------------------------
  52 */
  53
  54#include <linux/module.h>
  55#include <linux/kernel.h>
  56#include <linux/sched.h>
  57#include <linux/types.h>
  58#include <linux/slab.h>
  59#include <linux/wireless.h>
  60#include <linux/netdevice.h>
  61#include <linux/workqueue.h>
  62#include <linux/byteorder/generic.h>
  63#include <linux/etherdevice.h>
  64
  65#include <linux/io.h>
  66#include <linux/delay.h>
  67#include <asm/byteorder.h>
  68#include <linux/if_arp.h>
  69#include <linux/if_ether.h>
  70#include <linux/bitops.h>
  71
  72#include "p80211types.h"
  73#include "p80211hdr.h"
  74#include "p80211mgmt.h"
  75#include "p80211conv.h"
  76#include "p80211msg.h"
  77#include "p80211netdev.h"
  78#include "p80211req.h"
  79#include "p80211metadef.h"
  80#include "p80211metastruct.h"
  81#include "hfa384x.h"
  82#include "prism2mgmt.h"
  83
  84static char *dev_info = "prism2_usb";
  85static struct wlandevice *create_wlan(void);
  86
  87int prism2_reset_holdtime = 30; /* Reset hold time in ms */
  88int prism2_reset_settletime = 100;      /* Reset settle time in ms */
  89
  90static int prism2_doreset;      /* Do a reset at init? */
  91
  92module_param(prism2_doreset, int, 0644);
  93MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization");
  94
  95module_param(prism2_reset_holdtime, int, 0644);
  96MODULE_PARM_DESC(prism2_reset_holdtime, "reset hold time in ms");
  97module_param(prism2_reset_settletime, int, 0644);
  98MODULE_PARM_DESC(prism2_reset_settletime, "reset settle time in ms");
  99
 100MODULE_LICENSE("Dual MPL/GPL");
 101
 102static int prism2sta_open(struct wlandevice *wlandev);
 103static int prism2sta_close(struct wlandevice *wlandev);
 104static void prism2sta_reset(struct wlandevice *wlandev);
 105static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb,
 106                             union p80211_hdr *p80211_hdr,
 107                             struct p80211_metawep *p80211_wep);
 108static int prism2sta_mlmerequest(struct wlandevice *wlandev,
 109                                 struct p80211msg *msg);
 110static int prism2sta_getcardinfo(struct wlandevice *wlandev);
 111static int prism2sta_globalsetup(struct wlandevice *wlandev);
 112static int prism2sta_setmulticast(struct wlandevice *wlandev,
 113                                  struct net_device *dev);
 114
 115static void prism2sta_inf_handover(struct wlandevice *wlandev,
 116                                   struct hfa384x_inf_frame *inf);
 117static void prism2sta_inf_tallies(struct wlandevice *wlandev,
 118                                  struct hfa384x_inf_frame *inf);
 119static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev,
 120                                          struct hfa384x_inf_frame *inf);
 121static void prism2sta_inf_scanresults(struct wlandevice *wlandev,
 122                                      struct hfa384x_inf_frame *inf);
 123static void prism2sta_inf_chinforesults(struct wlandevice *wlandev,
 124                                        struct hfa384x_inf_frame *inf);
 125static void prism2sta_inf_linkstatus(struct wlandevice *wlandev,
 126                                     struct hfa384x_inf_frame *inf);
 127static void prism2sta_inf_assocstatus(struct wlandevice *wlandev,
 128                                      struct hfa384x_inf_frame *inf);
 129static void prism2sta_inf_authreq(struct wlandevice *wlandev,
 130                                  struct hfa384x_inf_frame *inf);
 131static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev,
 132                                        struct hfa384x_inf_frame *inf);
 133static void prism2sta_inf_psusercnt(struct wlandevice *wlandev,
 134                                    struct hfa384x_inf_frame *inf);
 135
 136/*
 137 * prism2sta_open
 138 *
 139 * WLAN device open method.  Called from p80211netdev when kernel
 140 * device open (start) method is called in response to the
 141 * SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
 142 * from clear to set.
 143 *
 144 * Arguments:
 145 *      wlandev         wlan device structure
 146 *
 147 * Returns:
 148 *      0       success
 149 *      >0      f/w reported error
 150 *      <0      driver reported error
 151 *
 152 * Side effects:
 153 *
 154 * Call context:
 155 *      process thread
 156 */
 157static int prism2sta_open(struct wlandevice *wlandev)
 158{
 159        /* We don't currently have to do anything else.
 160         * The setup of the MAC should be subsequently completed via
 161         * the mlme commands.
 162         * Higher layers know we're ready from dev->start==1 and
 163         * dev->tbusy==0.  Our rx path knows to pass up received/
 164         * frames because of dev->flags&IFF_UP is true.
 165         */
 166
 167        return 0;
 168}
 169
 170/*
 171 * prism2sta_close
 172 *
 173 * WLAN device close method.  Called from p80211netdev when kernel
 174 * device close method is called in response to the
 175 * SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
 176 * from set to clear.
 177 *
 178 * Arguments:
 179 *      wlandev         wlan device structure
 180 *
 181 * Returns:
 182 *      0       success
 183 *      >0      f/w reported error
 184 *      <0      driver reported error
 185 *
 186 * Side effects:
 187 *
 188 * Call context:
 189 *      process thread
 190 */
 191static int prism2sta_close(struct wlandevice *wlandev)
 192{
 193        /* We don't currently have to do anything else.
 194         * Higher layers know we're not ready from dev->start==0 and
 195         * dev->tbusy==1.  Our rx path knows to not pass up received
 196         * frames because of dev->flags&IFF_UP is false.
 197         */
 198
 199        return 0;
 200}
 201
 202/*
 203 * prism2sta_reset
 204 *
 205 * Currently not implemented.
 206 *
 207 * Arguments:
 208 *      wlandev         wlan device structure
 209 *      none
 210 *
 211 * Returns:
 212 *      nothing
 213 *
 214 * Side effects:
 215 *
 216 * Call context:
 217 *      process thread
 218 */
 219static void prism2sta_reset(struct wlandevice *wlandev)
 220{
 221}
 222
 223/*
 224 * prism2sta_txframe
 225 *
 226 * Takes a frame from p80211 and queues it for transmission.
 227 *
 228 * Arguments:
 229 *      wlandev         wlan device structure
 230 *      pb              packet buffer struct.  Contains an 802.11
 231 *                      data frame.
 232 *       p80211_hdr      points to the 802.11 header for the packet.
 233 * Returns:
 234 *      0               Success and more buffs available
 235 *      1               Success but no more buffs
 236 *      2               Allocation failure
 237 *      4               Buffer full or queue busy
 238 *
 239 * Side effects:
 240 *
 241 * Call context:
 242 *      process thread
 243 */
 244static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb,
 245                             union p80211_hdr *p80211_hdr,
 246                             struct p80211_metawep *p80211_wep)
 247{
 248        struct hfa384x *hw = wlandev->priv;
 249
 250        /* If necessary, set the 802.11 WEP bit */
 251        if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) ==
 252            HOSTWEP_PRIVACYINVOKED) {
 253                p80211_hdr->a3.fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1));
 254        }
 255
 256        return hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep);
 257}
 258
 259/*
 260 * prism2sta_mlmerequest
 261 *
 262 * wlan command message handler.  All we do here is pass the message
 263 * over to the prism2sta_mgmt_handler.
 264 *
 265 * Arguments:
 266 *      wlandev         wlan device structure
 267 *      msg             wlan command message
 268 * Returns:
 269 *      0               success
 270 *      <0              successful acceptance of message, but we're
 271 *                      waiting for an async process to finish before
 272 *                      we're done with the msg.  When the asynch
 273 *                      process is done, we'll call the p80211
 274 *                      function p80211req_confirm() .
 275 *      >0              An error occurred while we were handling
 276 *                      the message.
 277 *
 278 * Side effects:
 279 *
 280 * Call context:
 281 *      process thread
 282 */
 283static int prism2sta_mlmerequest(struct wlandevice *wlandev,
 284                                 struct p80211msg *msg)
 285{
 286        struct hfa384x *hw = wlandev->priv;
 287
 288        int result = 0;
 289
 290        switch (msg->msgcode) {
 291        case DIDMSG_DOT11REQ_MIBGET:
 292                pr_debug("Received mibget request\n");
 293                result = prism2mgmt_mibset_mibget(wlandev, msg);
 294                break;
 295        case DIDMSG_DOT11REQ_MIBSET:
 296                pr_debug("Received mibset request\n");
 297                result = prism2mgmt_mibset_mibget(wlandev, msg);
 298                break;
 299        case DIDMSG_DOT11REQ_SCAN:
 300                pr_debug("Received scan request\n");
 301                result = prism2mgmt_scan(wlandev, msg);
 302                break;
 303        case DIDMSG_DOT11REQ_SCAN_RESULTS:
 304                pr_debug("Received scan_results request\n");
 305                result = prism2mgmt_scan_results(wlandev, msg);
 306                break;
 307        case DIDMSG_DOT11REQ_START:
 308                pr_debug("Received mlme start request\n");
 309                result = prism2mgmt_start(wlandev, msg);
 310                break;
 311                /*
 312                 * Prism2 specific messages
 313                 */
 314        case DIDMSG_P2REQ_READPDA:
 315                pr_debug("Received mlme readpda request\n");
 316                result = prism2mgmt_readpda(wlandev, msg);
 317                break;
 318        case DIDMSG_P2REQ_RAMDL_STATE:
 319                pr_debug("Received mlme ramdl_state request\n");
 320                result = prism2mgmt_ramdl_state(wlandev, msg);
 321                break;
 322        case DIDMSG_P2REQ_RAMDL_WRITE:
 323                pr_debug("Received mlme ramdl_write request\n");
 324                result = prism2mgmt_ramdl_write(wlandev, msg);
 325                break;
 326        case DIDMSG_P2REQ_FLASHDL_STATE:
 327                pr_debug("Received mlme flashdl_state request\n");
 328                result = prism2mgmt_flashdl_state(wlandev, msg);
 329                break;
 330        case DIDMSG_P2REQ_FLASHDL_WRITE:
 331                pr_debug("Received mlme flashdl_write request\n");
 332                result = prism2mgmt_flashdl_write(wlandev, msg);
 333                break;
 334                /*
 335                 * Linux specific messages
 336                 */
 337        case DIDMSG_LNXREQ_HOSTWEP:
 338                break;          /* ignore me. */
 339        case DIDMSG_LNXREQ_IFSTATE: {
 340                struct p80211msg_lnxreq_ifstate *ifstatemsg;
 341
 342                pr_debug("Received mlme ifstate request\n");
 343                ifstatemsg = (struct p80211msg_lnxreq_ifstate *)msg;
 344                result = prism2sta_ifstate(wlandev,
 345                                           ifstatemsg->ifstate.data);
 346                ifstatemsg->resultcode.status =
 347                        P80211ENUM_msgitem_status_data_ok;
 348                ifstatemsg->resultcode.data = result;
 349                result = 0;
 350                break;
 351        }
 352        case DIDMSG_LNXREQ_WLANSNIFF:
 353                pr_debug("Received mlme wlansniff request\n");
 354                result = prism2mgmt_wlansniff(wlandev, msg);
 355                break;
 356        case DIDMSG_LNXREQ_AUTOJOIN:
 357                pr_debug("Received mlme autojoin request\n");
 358                result = prism2mgmt_autojoin(wlandev, msg);
 359                break;
 360        case DIDMSG_LNXREQ_COMMSQUALITY: {
 361                struct p80211msg_lnxreq_commsquality *qualmsg;
 362
 363                pr_debug("Received commsquality request\n");
 364
 365                qualmsg = (struct p80211msg_lnxreq_commsquality *)msg;
 366
 367                qualmsg->link.status = P80211ENUM_msgitem_status_data_ok;
 368                qualmsg->level.status = P80211ENUM_msgitem_status_data_ok;
 369                qualmsg->noise.status = P80211ENUM_msgitem_status_data_ok;
 370
 371                qualmsg->link.data = le16_to_cpu(hw->qual.cq_curr_bss);
 372                qualmsg->level.data = le16_to_cpu(hw->qual.asl_curr_bss);
 373                qualmsg->noise.data = le16_to_cpu(hw->qual.anl_curr_fc);
 374                qualmsg->txrate.data = hw->txrate;
 375
 376                break;
 377        }
 378        default:
 379                netdev_warn(wlandev->netdev,
 380                            "Unknown mgmt request message 0x%08x",
 381                            msg->msgcode);
 382                break;
 383        }
 384
 385        return result;
 386}
 387
 388/*
 389 * prism2sta_ifstate
 390 *
 391 * Interface state.  This is the primary WLAN interface enable/disable
 392 * handler.  Following the driver/load/deviceprobe sequence, this
 393 * function must be called with a state of "enable" before any other
 394 * commands will be accepted.
 395 *
 396 * Arguments:
 397 *      wlandev         wlan device structure
 398 *      msgp            ptr to msg buffer
 399 *
 400 * Returns:
 401 *      A p80211 message resultcode value.
 402 *
 403 * Side effects:
 404 *
 405 * Call context:
 406 *      process thread  (usually)
 407 *      interrupt
 408 */
 409u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate)
 410{
 411        struct hfa384x *hw = wlandev->priv;
 412        u32 result;
 413
 414        result = P80211ENUM_resultcode_implementation_failure;
 415
 416        pr_debug("Current MSD state(%d), requesting(%d)\n",
 417                 wlandev->msdstate, ifstate);
 418        switch (ifstate) {
 419        case P80211ENUM_ifstate_fwload:
 420                switch (wlandev->msdstate) {
 421                case WLAN_MSD_HWPRESENT:
 422                        wlandev->msdstate = WLAN_MSD_FWLOAD_PENDING;
 423                        /*
 424                         * Initialize the device+driver sufficiently
 425                         * for firmware loading.
 426                         */
 427                        result = hfa384x_drvr_start(hw);
 428                        if (result) {
 429                                netdev_err(wlandev->netdev,
 430                                           "hfa384x_drvr_start() failed,result=%d\n",
 431                                           (int)result);
 432                                result =
 433                                 P80211ENUM_resultcode_implementation_failure;
 434                                wlandev->msdstate = WLAN_MSD_HWPRESENT;
 435                                break;
 436                        }
 437                        wlandev->msdstate = WLAN_MSD_FWLOAD;
 438                        result = P80211ENUM_resultcode_success;
 439                        break;
 440                case WLAN_MSD_FWLOAD:
 441                        hfa384x_cmd_initialize(hw);
 442                        result = P80211ENUM_resultcode_success;
 443                        break;
 444                case WLAN_MSD_RUNNING:
 445                        netdev_warn(wlandev->netdev,
 446                                    "Cannot enter fwload state from enable state, you must disable first.\n");
 447                        result = P80211ENUM_resultcode_invalid_parameters;
 448                        break;
 449                case WLAN_MSD_HWFAIL:
 450                default:
 451                        /* probe() had a problem or the msdstate contains
 452                         * an unrecognized value, there's nothing we can do.
 453                         */
 454                        result = P80211ENUM_resultcode_implementation_failure;
 455                        break;
 456                }
 457                break;
 458        case P80211ENUM_ifstate_enable:
 459                switch (wlandev->msdstate) {
 460                case WLAN_MSD_HWPRESENT:
 461                case WLAN_MSD_FWLOAD:
 462                        wlandev->msdstate = WLAN_MSD_RUNNING_PENDING;
 463                        /* Initialize the device+driver for full
 464                         * operation. Note that this might me an FWLOAD
 465                         * to RUNNING transition so we must not do a chip
 466                         * or board level reset.  Note that on failure,
 467                         * the MSD state is set to HWPRESENT because we
 468                         * can't make any assumptions about the state
 469                         * of the hardware or a previous firmware load.
 470                         */
 471                        result = hfa384x_drvr_start(hw);
 472                        if (result) {
 473                                netdev_err(wlandev->netdev,
 474                                           "hfa384x_drvr_start() failed,result=%d\n",
 475                                           (int)result);
 476                                result =
 477                                  P80211ENUM_resultcode_implementation_failure;
 478                                wlandev->msdstate = WLAN_MSD_HWPRESENT;
 479                                break;
 480                        }
 481
 482                        result = prism2sta_getcardinfo(wlandev);
 483                        if (result) {
 484                                netdev_err(wlandev->netdev,
 485                                           "prism2sta_getcardinfo() failed,result=%d\n",
 486                                           (int)result);
 487                                result =
 488                                  P80211ENUM_resultcode_implementation_failure;
 489                                hfa384x_drvr_stop(hw);
 490                                wlandev->msdstate = WLAN_MSD_HWPRESENT;
 491                                break;
 492                        }
 493                        result = prism2sta_globalsetup(wlandev);
 494                        if (result) {
 495                                netdev_err(wlandev->netdev,
 496                                           "prism2sta_globalsetup() failed,result=%d\n",
 497                                           (int)result);
 498                                result =
 499                                  P80211ENUM_resultcode_implementation_failure;
 500                                hfa384x_drvr_stop(hw);
 501                                wlandev->msdstate = WLAN_MSD_HWPRESENT;
 502                                break;
 503                        }
 504                        wlandev->msdstate = WLAN_MSD_RUNNING;
 505                        hw->join_ap = 0;
 506                        hw->join_retries = 60;
 507                        result = P80211ENUM_resultcode_success;
 508                        break;
 509                case WLAN_MSD_RUNNING:
 510                        /* Do nothing, we're already in this state. */
 511                        result = P80211ENUM_resultcode_success;
 512                        break;
 513                case WLAN_MSD_HWFAIL:
 514                default:
 515                        /* probe() had a problem or the msdstate contains
 516                         * an unrecognized value, there's nothing we can do.
 517                         */
 518                        result = P80211ENUM_resultcode_implementation_failure;
 519                        break;
 520                }
 521                break;
 522        case P80211ENUM_ifstate_disable:
 523                switch (wlandev->msdstate) {
 524                case WLAN_MSD_HWPRESENT:
 525                        /* Do nothing, we're already in this state. */
 526                        result = P80211ENUM_resultcode_success;
 527                        break;
 528                case WLAN_MSD_FWLOAD:
 529                case WLAN_MSD_RUNNING:
 530                        wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
 531                        /*
 532                         * TODO: Shut down the MAC completely. Here a chip
 533                         * or board level reset is probably called for.
 534                         * After a "disable" _all_ results are lost, even
 535                         * those from a fwload.
 536                         */
 537                        if (!wlandev->hwremoved)
 538                                netif_carrier_off(wlandev->netdev);
 539
 540                        hfa384x_drvr_stop(hw);
 541
 542                        wlandev->macmode = WLAN_MACMODE_NONE;
 543                        wlandev->msdstate = WLAN_MSD_HWPRESENT;
 544                        result = P80211ENUM_resultcode_success;
 545                        break;
 546                case WLAN_MSD_HWFAIL:
 547                default:
 548                        /* probe() had a problem or the msdstate contains
 549                         * an unrecognized value, there's nothing we can do.
 550                         */
 551                        result = P80211ENUM_resultcode_implementation_failure;
 552                        break;
 553                }
 554                break;
 555        default:
 556                result = P80211ENUM_resultcode_invalid_parameters;
 557                break;
 558        }
 559
 560        return result;
 561}
 562
 563/*
 564 * prism2sta_getcardinfo
 565 *
 566 * Collect the NICID, firmware version and any other identifiers
 567 * we'd like to have in host-side data structures.
 568 *
 569 * Arguments:
 570 *      wlandev         wlan device structure
 571 *
 572 * Returns:
 573 *      0       success
 574 *      >0      f/w reported error
 575 *      <0      driver reported error
 576 *
 577 * Side effects:
 578 *
 579 * Call context:
 580 *      Either.
 581 */
 582static int prism2sta_getcardinfo(struct wlandevice *wlandev)
 583{
 584        int result = 0;
 585        struct hfa384x *hw = wlandev->priv;
 586        u16 temp;
 587        u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN];
 588
 589        /* Collect version and compatibility info */
 590        /*  Some are critical, some are not */
 591        /* NIC identity */
 592        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY,
 593                                        &hw->ident_nic,
 594                                        sizeof(struct hfa384x_compident));
 595        if (result) {
 596                netdev_err(wlandev->netdev, "Failed to retrieve NICIDENTITY\n");
 597                goto failed;
 598        }
 599
 600        /* get all the nic id fields in host byte order */
 601        le16_to_cpus(&hw->ident_nic.id);
 602        le16_to_cpus(&hw->ident_nic.variant);
 603        le16_to_cpus(&hw->ident_nic.major);
 604        le16_to_cpus(&hw->ident_nic.minor);
 605
 606        netdev_info(wlandev->netdev, "ident: nic h/w: id=0x%02x %d.%d.%d\n",
 607                    hw->ident_nic.id, hw->ident_nic.major,
 608                    hw->ident_nic.minor, hw->ident_nic.variant);
 609
 610        /* Primary f/w identity */
 611        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY,
 612                                        &hw->ident_pri_fw,
 613                                        sizeof(struct hfa384x_compident));
 614        if (result) {
 615                netdev_err(wlandev->netdev, "Failed to retrieve PRIIDENTITY\n");
 616                goto failed;
 617        }
 618
 619        /* get all the private fw id fields in host byte order */
 620        le16_to_cpus(&hw->ident_pri_fw.id);
 621        le16_to_cpus(&hw->ident_pri_fw.variant);
 622        le16_to_cpus(&hw->ident_pri_fw.major);
 623        le16_to_cpus(&hw->ident_pri_fw.minor);
 624
 625        netdev_info(wlandev->netdev, "ident: pri f/w: id=0x%02x %d.%d.%d\n",
 626                    hw->ident_pri_fw.id, hw->ident_pri_fw.major,
 627                    hw->ident_pri_fw.minor, hw->ident_pri_fw.variant);
 628
 629        /* Station (Secondary?) f/w identity */
 630        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY,
 631                                        &hw->ident_sta_fw,
 632                                        sizeof(struct hfa384x_compident));
 633        if (result) {
 634                netdev_err(wlandev->netdev, "Failed to retrieve STAIDENTITY\n");
 635                goto failed;
 636        }
 637
 638        if (hw->ident_nic.id < 0x8000) {
 639                netdev_err(wlandev->netdev,
 640                           "FATAL: Card is not an Intersil Prism2/2.5/3\n");
 641                result = -1;
 642                goto failed;
 643        }
 644
 645        /* get all the station fw id fields in host byte order */
 646        le16_to_cpus(&hw->ident_sta_fw.id);
 647        le16_to_cpus(&hw->ident_sta_fw.variant);
 648        le16_to_cpus(&hw->ident_sta_fw.major);
 649        le16_to_cpus(&hw->ident_sta_fw.minor);
 650
 651        /* strip out the 'special' variant bits */
 652        hw->mm_mods = hw->ident_sta_fw.variant & GENMASK(15, 14);
 653        hw->ident_sta_fw.variant &= ~((u16)GENMASK(15, 14));
 654
 655        if (hw->ident_sta_fw.id == 0x1f) {
 656                netdev_info(wlandev->netdev,
 657                            "ident: sta f/w: id=0x%02x %d.%d.%d\n",
 658                            hw->ident_sta_fw.id, hw->ident_sta_fw.major,
 659                            hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
 660        } else {
 661                netdev_info(wlandev->netdev,
 662                            "ident:  ap f/w: id=0x%02x %d.%d.%d\n",
 663                            hw->ident_sta_fw.id, hw->ident_sta_fw.major,
 664                            hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
 665                netdev_err(wlandev->netdev, "Unsupported Tertiary AP firmware loaded!\n");
 666                goto failed;
 667        }
 668
 669        /* Compatibility range, Modem supplier */
 670        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE,
 671                                        &hw->cap_sup_mfi,
 672                                        sizeof(struct hfa384x_caplevel));
 673        if (result) {
 674                netdev_err(wlandev->netdev, "Failed to retrieve MFISUPRANGE\n");
 675                goto failed;
 676        }
 677
 678        /* get all the Compatibility range, modem interface supplier
 679         * fields in byte order
 680         */
 681        le16_to_cpus(&hw->cap_sup_mfi.role);
 682        le16_to_cpus(&hw->cap_sup_mfi.id);
 683        le16_to_cpus(&hw->cap_sup_mfi.variant);
 684        le16_to_cpus(&hw->cap_sup_mfi.bottom);
 685        le16_to_cpus(&hw->cap_sup_mfi.top);
 686
 687        netdev_info(wlandev->netdev,
 688                    "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
 689                    hw->cap_sup_mfi.role, hw->cap_sup_mfi.id,
 690                    hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom,
 691                    hw->cap_sup_mfi.top);
 692
 693        /* Compatibility range, Controller supplier */
 694        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE,
 695                                        &hw->cap_sup_cfi,
 696                                        sizeof(struct hfa384x_caplevel));
 697        if (result) {
 698                netdev_err(wlandev->netdev, "Failed to retrieve CFISUPRANGE\n");
 699                goto failed;
 700        }
 701
 702        /* get all the Compatibility range, controller interface supplier
 703         * fields in byte order
 704         */
 705        le16_to_cpus(&hw->cap_sup_cfi.role);
 706        le16_to_cpus(&hw->cap_sup_cfi.id);
 707        le16_to_cpus(&hw->cap_sup_cfi.variant);
 708        le16_to_cpus(&hw->cap_sup_cfi.bottom);
 709        le16_to_cpus(&hw->cap_sup_cfi.top);
 710
 711        netdev_info(wlandev->netdev,
 712                    "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
 713                    hw->cap_sup_cfi.role, hw->cap_sup_cfi.id,
 714                    hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom,
 715                    hw->cap_sup_cfi.top);
 716
 717        /* Compatibility range, Primary f/w supplier */
 718        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE,
 719                                        &hw->cap_sup_pri,
 720                                        sizeof(struct hfa384x_caplevel));
 721        if (result) {
 722                netdev_err(wlandev->netdev, "Failed to retrieve PRISUPRANGE\n");
 723                goto failed;
 724        }
 725
 726        /* get all the Compatibility range, primary firmware supplier
 727         * fields in byte order
 728         */
 729        le16_to_cpus(&hw->cap_sup_pri.role);
 730        le16_to_cpus(&hw->cap_sup_pri.id);
 731        le16_to_cpus(&hw->cap_sup_pri.variant);
 732        le16_to_cpus(&hw->cap_sup_pri.bottom);
 733        le16_to_cpus(&hw->cap_sup_pri.top);
 734
 735        netdev_info(wlandev->netdev,
 736                    "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
 737                    hw->cap_sup_pri.role, hw->cap_sup_pri.id,
 738                    hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom,
 739                    hw->cap_sup_pri.top);
 740
 741        /* Compatibility range, Station f/w supplier */
 742        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE,
 743                                        &hw->cap_sup_sta,
 744                                        sizeof(struct hfa384x_caplevel));
 745        if (result) {
 746                netdev_err(wlandev->netdev, "Failed to retrieve STASUPRANGE\n");
 747                goto failed;
 748        }
 749
 750        /* get all the Compatibility range, station firmware supplier
 751         * fields in byte order
 752         */
 753        le16_to_cpus(&hw->cap_sup_sta.role);
 754        le16_to_cpus(&hw->cap_sup_sta.id);
 755        le16_to_cpus(&hw->cap_sup_sta.variant);
 756        le16_to_cpus(&hw->cap_sup_sta.bottom);
 757        le16_to_cpus(&hw->cap_sup_sta.top);
 758
 759        if (hw->cap_sup_sta.id == 0x04) {
 760                netdev_info(wlandev->netdev,
 761                            "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
 762                            hw->cap_sup_sta.role, hw->cap_sup_sta.id,
 763                            hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
 764                            hw->cap_sup_sta.top);
 765        } else {
 766                netdev_info(wlandev->netdev,
 767                            "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
 768                            hw->cap_sup_sta.role, hw->cap_sup_sta.id,
 769                            hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
 770                            hw->cap_sup_sta.top);
 771        }
 772
 773        /* Compatibility range, primary f/w actor, CFI supplier */
 774        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES,
 775                                        &hw->cap_act_pri_cfi,
 776                                        sizeof(struct hfa384x_caplevel));
 777        if (result) {
 778                netdev_err(wlandev->netdev, "Failed to retrieve PRI_CFIACTRANGES\n");
 779                goto failed;
 780        }
 781
 782        /* get all the Compatibility range, primary f/w actor, CFI supplier
 783         * fields in byte order
 784         */
 785        le16_to_cpus(&hw->cap_act_pri_cfi.role);
 786        le16_to_cpus(&hw->cap_act_pri_cfi.id);
 787        le16_to_cpus(&hw->cap_act_pri_cfi.variant);
 788        le16_to_cpus(&hw->cap_act_pri_cfi.bottom);
 789        le16_to_cpus(&hw->cap_act_pri_cfi.top);
 790
 791        netdev_info(wlandev->netdev,
 792                    "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
 793                    hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id,
 794                    hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom,
 795                    hw->cap_act_pri_cfi.top);
 796
 797        /* Compatibility range, sta f/w actor, CFI supplier */
 798        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES,
 799                                        &hw->cap_act_sta_cfi,
 800                                        sizeof(struct hfa384x_caplevel));
 801        if (result) {
 802                netdev_err(wlandev->netdev, "Failed to retrieve STA_CFIACTRANGES\n");
 803                goto failed;
 804        }
 805
 806        /* get all the Compatibility range, station f/w actor, CFI supplier
 807         * fields in byte order
 808         */
 809        le16_to_cpus(&hw->cap_act_sta_cfi.role);
 810        le16_to_cpus(&hw->cap_act_sta_cfi.id);
 811        le16_to_cpus(&hw->cap_act_sta_cfi.variant);
 812        le16_to_cpus(&hw->cap_act_sta_cfi.bottom);
 813        le16_to_cpus(&hw->cap_act_sta_cfi.top);
 814
 815        netdev_info(wlandev->netdev,
 816                    "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
 817                    hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id,
 818                    hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom,
 819                    hw->cap_act_sta_cfi.top);
 820
 821        /* Compatibility range, sta f/w actor, MFI supplier */
 822        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES,
 823                                        &hw->cap_act_sta_mfi,
 824                                        sizeof(struct hfa384x_caplevel));
 825        if (result) {
 826                netdev_err(wlandev->netdev, "Failed to retrieve STA_MFIACTRANGES\n");
 827                goto failed;
 828        }
 829
 830        /* get all the Compatibility range, station f/w actor, MFI supplier
 831         * fields in byte order
 832         */
 833        le16_to_cpus(&hw->cap_act_sta_mfi.role);
 834        le16_to_cpus(&hw->cap_act_sta_mfi.id);
 835        le16_to_cpus(&hw->cap_act_sta_mfi.variant);
 836        le16_to_cpus(&hw->cap_act_sta_mfi.bottom);
 837        le16_to_cpus(&hw->cap_act_sta_mfi.top);
 838
 839        netdev_info(wlandev->netdev,
 840                    "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
 841                    hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id,
 842                    hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom,
 843                    hw->cap_act_sta_mfi.top);
 844
 845        /* Serial Number */
 846        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER,
 847                                        snum, HFA384x_RID_NICSERIALNUMBER_LEN);
 848        if (!result) {
 849                netdev_info(wlandev->netdev, "Prism2 card SN: %*pE\n",
 850                            HFA384x_RID_NICSERIALNUMBER_LEN, snum);
 851        } else {
 852                netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n");
 853                goto failed;
 854        }
 855
 856        /* Collect the MAC address */
 857        result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNMACADDR,
 858                                        wlandev->netdev->dev_addr, ETH_ALEN);
 859        if (result != 0) {
 860                netdev_err(wlandev->netdev, "Failed to retrieve mac address\n");
 861                goto failed;
 862        }
 863
 864        /* short preamble is always implemented */
 865        wlandev->nsdcaps |= P80211_NSDCAP_SHORT_PREAMBLE;
 866
 867        /* find out if hardware wep is implemented */
 868        hfa384x_drvr_getconfig16(hw, HFA384x_RID_PRIVACYOPTIMP, &temp);
 869        if (temp)
 870                wlandev->nsdcaps |= P80211_NSDCAP_HARDWAREWEP;
 871
 872        /* get the dBm Scaling constant */
 873        hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFDBMADJUST, &temp);
 874        hw->dbmadjust = temp;
 875
 876        /* Only enable scan by default on newer firmware */
 877        if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
 878                                     hw->ident_sta_fw.minor,
 879                                     hw->ident_sta_fw.variant) <
 880            HFA384x_FIRMWARE_VERSION(1, 5, 5)) {
 881                wlandev->nsdcaps |= P80211_NSDCAP_NOSCAN;
 882        }
 883
 884        /* TODO: Set any internally managed config items */
 885
 886        goto done;
 887failed:
 888        netdev_err(wlandev->netdev, "Failed, result=%d\n", result);
 889done:
 890        return result;
 891}
 892
 893/*
 894 * prism2sta_globalsetup
 895 *
 896 * Set any global RIDs that we want to set at device activation.
 897 *
 898 * Arguments:
 899 *      wlandev         wlan device structure
 900 *
 901 * Returns:
 902 *      0       success
 903 *      >0      f/w reported error
 904 *      <0      driver reported error
 905 *
 906 * Side effects:
 907 *
 908 * Call context:
 909 *      process thread
 910 */
 911static int prism2sta_globalsetup(struct wlandevice *wlandev)
 912{
 913        struct hfa384x *hw = wlandev->priv;
 914
 915        /* Set the maximum frame size */
 916        return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN,
 917                                        WLAN_DATA_MAXLEN);
 918}
 919
 920static int prism2sta_setmulticast(struct wlandevice *wlandev,
 921                                  struct net_device *dev)
 922{
 923        int result = 0;
 924        struct hfa384x *hw = wlandev->priv;
 925
 926        u16 promisc;
 927
 928        /* If we're not ready, what's the point? */
 929        if (hw->state != HFA384x_STATE_RUNNING)
 930                goto exit;
 931
 932        if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
 933                promisc = P80211ENUM_truth_true;
 934        else
 935                promisc = P80211ENUM_truth_false;
 936
 937        result =
 938            hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE,
 939                                           promisc);
 940exit:
 941        return result;
 942}
 943
 944/*
 945 * prism2sta_inf_handover
 946 *
 947 * Handles the receipt of a Handover info frame. Should only be present
 948 * in APs only.
 949 *
 950 * Arguments:
 951 *      wlandev         wlan device structure
 952 *      inf             ptr to info frame (contents in hfa384x order)
 953 *
 954 * Returns:
 955 *      nothing
 956 *
 957 * Side effects:
 958 *
 959 * Call context:
 960 *      interrupt
 961 */
 962static void prism2sta_inf_handover(struct wlandevice *wlandev,
 963                                   struct hfa384x_inf_frame *inf)
 964{
 965        pr_debug("received infoframe:HANDOVER (unhandled)\n");
 966}
 967
 968/*
 969 * prism2sta_inf_tallies
 970 *
 971 * Handles the receipt of a CommTallies info frame.
 972 *
 973 * Arguments:
 974 *      wlandev         wlan device structure
 975 *      inf             ptr to info frame (contents in hfa384x order)
 976 *
 977 * Returns:
 978 *      nothing
 979 *
 980 * Side effects:
 981 *
 982 * Call context:
 983 *      interrupt
 984 */
 985static void prism2sta_inf_tallies(struct wlandevice *wlandev,
 986                                  struct hfa384x_inf_frame *inf)
 987{
 988        struct hfa384x *hw = wlandev->priv;
 989        __le16 *src16;
 990        u32 *dst;
 991        __le32 *src32;
 992        int i;
 993        int cnt;
 994
 995        /*
 996         * Determine if these are 16-bit or 32-bit tallies, based on the
 997         * record length of the info record.
 998         */
 999
1000        cnt = sizeof(struct hfa384x_comm_tallies_32) / sizeof(u32);
1001        if (inf->framelen > 22) {
1002                dst = (u32 *)&hw->tallies;
1003                src32 = (__le32 *)&inf->info.commtallies32;
1004                for (i = 0; i < cnt; i++, dst++, src32++)
1005                        *dst += le32_to_cpu(*src32);
1006        } else {
1007                dst = (u32 *)&hw->tallies;
1008                src16 = (__le16 *)&inf->info.commtallies16;
1009                for (i = 0; i < cnt; i++, dst++, src16++)
1010                        *dst += le16_to_cpu(*src16);
1011        }
1012}
1013
1014/*
1015 * prism2sta_inf_scanresults
1016 *
1017 * Handles the receipt of a Scan Results info frame.
1018 *
1019 * Arguments:
1020 *      wlandev         wlan device structure
1021 *      inf             ptr to info frame (contents in hfa384x order)
1022 *
1023 * Returns:
1024 *      nothing
1025 *
1026 * Side effects:
1027 *
1028 * Call context:
1029 *      interrupt
1030 */
1031static void prism2sta_inf_scanresults(struct wlandevice *wlandev,
1032                                      struct hfa384x_inf_frame *inf)
1033{
1034        struct hfa384x *hw = wlandev->priv;
1035        int nbss;
1036        struct hfa384x_scan_result *sr = &inf->info.scanresult;
1037        int i;
1038        struct hfa384x_join_request_data joinreq;
1039        int result;
1040
1041        /* Get the number of results, first in bytes, then in results */
1042        nbss = (inf->framelen * sizeof(u16)) -
1043            sizeof(inf->infotype) - sizeof(inf->info.scanresult.scanreason);
1044        nbss /= sizeof(struct hfa384x_scan_result_sub);
1045
1046        /* Print em */
1047        pr_debug("rx scanresults, reason=%d, nbss=%d:\n",
1048                 inf->info.scanresult.scanreason, nbss);
1049        for (i = 0; i < nbss; i++) {
1050                pr_debug("chid=%d anl=%d sl=%d bcnint=%d\n",
1051                         sr->result[i].chid,
1052                         sr->result[i].anl,
1053                         sr->result[i].sl, sr->result[i].bcnint);
1054                pr_debug("  capinfo=0x%04x proberesp_rate=%d\n",
1055                         sr->result[i].capinfo, sr->result[i].proberesp_rate);
1056        }
1057        /* issue a join request */
1058        joinreq.channel = sr->result[0].chid;
1059        memcpy(joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN);
1060        result = hfa384x_drvr_setconfig(hw,
1061                                        HFA384x_RID_JOINREQUEST,
1062                                        &joinreq, HFA384x_RID_JOINREQUEST_LEN);
1063        if (result) {
1064                netdev_err(wlandev->netdev, "setconfig(joinreq) failed, result=%d\n",
1065                           result);
1066        }
1067}
1068
1069/*
1070 * prism2sta_inf_hostscanresults
1071 *
1072 * Handles the receipt of a Scan Results info frame.
1073 *
1074 * Arguments:
1075 *      wlandev         wlan device structure
1076 *      inf             ptr to info frame (contents in hfa384x order)
1077 *
1078 * Returns:
1079 *      nothing
1080 *
1081 * Side effects:
1082 *
1083 * Call context:
1084 *      interrupt
1085 */
1086static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev,
1087                                          struct hfa384x_inf_frame *inf)
1088{
1089        struct hfa384x *hw = wlandev->priv;
1090        int nbss;
1091
1092        nbss = (inf->framelen - 3) / 32;
1093        pr_debug("Received %d hostscan results\n", nbss);
1094
1095        if (nbss > 32)
1096                nbss = 32;
1097
1098        kfree(hw->scanresults);
1099
1100        hw->scanresults = kmemdup(inf, sizeof(*inf), GFP_ATOMIC);
1101
1102        if (nbss == 0)
1103                nbss = -1;
1104
1105        /* Notify/wake the sleeping caller. */
1106        hw->scanflag = nbss;
1107        wake_up_interruptible(&hw->cmdq);
1108};
1109
1110/*
1111 * prism2sta_inf_chinforesults
1112 *
1113 * Handles the receipt of a Channel Info Results info frame.
1114 *
1115 * Arguments:
1116 *      wlandev         wlan device structure
1117 *      inf             ptr to info frame (contents in hfa384x order)
1118 *
1119 * Returns:
1120 *      nothing
1121 *
1122 * Side effects:
1123 *
1124 * Call context:
1125 *      interrupt
1126 */
1127static void prism2sta_inf_chinforesults(struct wlandevice *wlandev,
1128                                        struct hfa384x_inf_frame *inf)
1129{
1130        struct hfa384x *hw = wlandev->priv;
1131        unsigned int i, n;
1132
1133        hw->channel_info.results.scanchannels =
1134            inf->info.chinforesult.scanchannels;
1135
1136        for (i = 0, n = 0; i < HFA384x_CHINFORESULT_MAX; i++) {
1137                struct hfa384x_ch_info_result_sub *result;
1138                struct hfa384x_ch_info_result_sub *chinforesult;
1139                int chan;
1140
1141                if (!(hw->channel_info.results.scanchannels & (1 << i)))
1142                        continue;
1143
1144                result = &inf->info.chinforesult.result[n];
1145                chan = result->chid - 1;
1146
1147                if (chan < 0 || chan >= HFA384x_CHINFORESULT_MAX)
1148                        continue;
1149
1150                chinforesult = &hw->channel_info.results.result[chan];
1151                chinforesult->chid = chan;
1152                chinforesult->anl = result->anl;
1153                chinforesult->pnl = result->pnl;
1154                chinforesult->active = result->active;
1155
1156                pr_debug("chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n",
1157                         chan + 1,
1158                         (chinforesult->active & HFA384x_CHINFORESULT_BSSACTIVE)
1159                                ? "signal" : "noise",
1160                         chinforesult->anl, chinforesult->pnl,
1161                         (chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE)
1162                                ? 1 : 0);
1163                n++;
1164        }
1165        atomic_set(&hw->channel_info.done, 2);
1166
1167        hw->channel_info.count = n;
1168}
1169
1170void prism2sta_processing_defer(struct work_struct *data)
1171{
1172        struct hfa384x *hw = container_of(data, struct hfa384x, link_bh);
1173        struct wlandevice *wlandev = hw->wlandev;
1174        struct hfa384x_bytestr32 ssid;
1175        int result;
1176
1177        /* First let's process the auth frames */
1178        {
1179                struct sk_buff *skb;
1180                struct hfa384x_inf_frame *inf;
1181
1182                while ((skb = skb_dequeue(&hw->authq))) {
1183                        inf = (struct hfa384x_inf_frame *)skb->data;
1184                        prism2sta_inf_authreq_defer(wlandev, inf);
1185                }
1186        }
1187
1188        /* Now let's handle the linkstatus stuff */
1189        if (hw->link_status == hw->link_status_new)
1190                return;
1191
1192        hw->link_status = hw->link_status_new;
1193
1194        switch (hw->link_status) {
1195        case HFA384x_LINK_NOTCONNECTED:
1196                /* I'm currently assuming that this is the initial link
1197                 * state.  It should only be possible immediately
1198                 * following an Enable command.
1199                 * Response:
1200                 * Block Transmits, Ignore receives of data frames
1201                 */
1202                netif_carrier_off(wlandev->netdev);
1203
1204                netdev_info(wlandev->netdev, "linkstatus=NOTCONNECTED (unhandled)\n");
1205                break;
1206
1207        case HFA384x_LINK_CONNECTED:
1208                /* This one indicates a successful scan/join/auth/assoc.
1209                 * When we have the full MLME complement, this event will
1210                 * signify successful completion of both mlme_authenticate
1211                 * and mlme_associate.  State management will get a little
1212                 * ugly here.
1213                 * Response:
1214                 * Indicate authentication and/or association
1215                 * Enable Transmits, Receives and pass up data frames
1216                 */
1217
1218                netif_carrier_on(wlandev->netdev);
1219
1220                /* If we are joining a specific AP, set our
1221                 * state and reset retries
1222                 */
1223                if (hw->join_ap == 1)
1224                        hw->join_ap = 2;
1225                hw->join_retries = 60;
1226
1227                /* Don't call this in monitor mode */
1228                if (wlandev->netdev->type == ARPHRD_ETHER) {
1229                        u16 portstatus;
1230
1231                        netdev_info(wlandev->netdev, "linkstatus=CONNECTED\n");
1232
1233                        /* For non-usb devices, we can use the sync versions */
1234                        /* Collect the BSSID, and set state to allow tx */
1235
1236                        result = hfa384x_drvr_getconfig(hw,
1237                                                        HFA384x_RID_CURRENTBSSID,
1238                                                        wlandev->bssid,
1239                                                        WLAN_BSSID_LEN);
1240                        if (result) {
1241                                pr_debug
1242                                    ("getconfig(0x%02x) failed, result = %d\n",
1243                                     HFA384x_RID_CURRENTBSSID, result);
1244                                return;
1245                        }
1246
1247                        result = hfa384x_drvr_getconfig(hw,
1248                                                        HFA384x_RID_CURRENTSSID,
1249                                                        &ssid, sizeof(ssid));
1250                        if (result) {
1251                                pr_debug
1252                                    ("getconfig(0x%02x) failed, result = %d\n",
1253                                     HFA384x_RID_CURRENTSSID, result);
1254                                return;
1255                        }
1256                        prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid,
1257                                                (struct p80211pstrd *)&wlandev->ssid);
1258
1259                        /* Collect the port status */
1260                        result = hfa384x_drvr_getconfig16(hw,
1261                                                          HFA384x_RID_PORTSTATUS,
1262                                                          &portstatus);
1263                        if (result) {
1264                                pr_debug
1265                                    ("getconfig(0x%02x) failed, result = %d\n",
1266                                     HFA384x_RID_PORTSTATUS, result);
1267                                return;
1268                        }
1269                        wlandev->macmode =
1270                            (portstatus == HFA384x_PSTATUS_CONN_IBSS) ?
1271                            WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA;
1272
1273                        /* signal back up to cfg80211 layer */
1274                        prism2_connect_result(wlandev, P80211ENUM_truth_false);
1275
1276                        /* Get the ball rolling on the comms quality stuff */
1277                        prism2sta_commsqual_defer(&hw->commsqual_bh);
1278                }
1279                break;
1280
1281        case HFA384x_LINK_DISCONNECTED:
1282                /* This one indicates that our association is gone.  We've
1283                 * lost connection with the AP and/or been disassociated.
1284                 * This indicates that the MAC has completely cleared it's
1285                 * associated state.  We * should send a deauth indication
1286                 * (implying disassoc) up * to the MLME.
1287                 * Response:
1288                 * Indicate Deauthentication
1289                 * Block Transmits, Ignore receives of data frames
1290                 */
1291                if (wlandev->netdev->type == ARPHRD_ETHER)
1292                        netdev_info(wlandev->netdev,
1293                                    "linkstatus=DISCONNECTED (unhandled)\n");
1294                wlandev->macmode = WLAN_MACMODE_NONE;
1295
1296                netif_carrier_off(wlandev->netdev);
1297
1298                /* signal back up to cfg80211 layer */
1299                prism2_disconnected(wlandev);
1300
1301                break;
1302
1303        case HFA384x_LINK_AP_CHANGE:
1304                /* This one indicates that the MAC has decided to and
1305                 * successfully completed a change to another AP.  We
1306                 * should probably implement a reassociation indication
1307                 * in response to this one.  I'm thinking that the
1308                 * p80211 layer needs to be notified in case of
1309                 * buffering/queueing issues.  User mode also needs to be
1310                 * notified so that any BSS dependent elements can be
1311                 * updated.
1312                 * associated state.  We * should send a deauth indication
1313                 * (implying disassoc) up * to the MLME.
1314                 * Response:
1315                 * Indicate Reassociation
1316                 * Enable Transmits, Receives and pass up data frames
1317                 */
1318                netdev_info(wlandev->netdev, "linkstatus=AP_CHANGE\n");
1319
1320                result = hfa384x_drvr_getconfig(hw,
1321                                                HFA384x_RID_CURRENTBSSID,
1322                                                wlandev->bssid, WLAN_BSSID_LEN);
1323                if (result) {
1324                        pr_debug("getconfig(0x%02x) failed, result = %d\n",
1325                                 HFA384x_RID_CURRENTBSSID, result);
1326                        return;
1327                }
1328
1329                result = hfa384x_drvr_getconfig(hw,
1330                                                HFA384x_RID_CURRENTSSID,
1331                                                &ssid, sizeof(ssid));
1332                if (result) {
1333                        pr_debug("getconfig(0x%02x) failed, result = %d\n",
1334                                 HFA384x_RID_CURRENTSSID, result);
1335                        return;
1336                }
1337                prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid,
1338                                        (struct p80211pstrd *)&wlandev->ssid);
1339
1340                hw->link_status = HFA384x_LINK_CONNECTED;
1341                netif_carrier_on(wlandev->netdev);
1342
1343                /* signal back up to cfg80211 layer */
1344                prism2_roamed(wlandev);
1345
1346                break;
1347
1348        case HFA384x_LINK_AP_OUTOFRANGE:
1349                /* This one indicates that the MAC has decided that the
1350                 * AP is out of range, but hasn't found a better candidate
1351                 * so the MAC maintains its "associated" state in case
1352                 * we get back in range.  We should block transmits and
1353                 * receives in this state.  Do we need an indication here?
1354                 * Probably not since a polling user-mode element would
1355                 * get this status from p2PortStatus(FD40). What about
1356                 * p80211?
1357                 * Response:
1358                 * Block Transmits, Ignore receives of data frames
1359                 */
1360                netdev_info(wlandev->netdev, "linkstatus=AP_OUTOFRANGE (unhandled)\n");
1361
1362                netif_carrier_off(wlandev->netdev);
1363
1364                break;
1365
1366        case HFA384x_LINK_AP_INRANGE:
1367                /* This one indicates that the MAC has decided that the
1368                 * AP is back in range.  We continue working with our
1369                 * existing association.
1370                 * Response:
1371                 * Enable Transmits, Receives and pass up data frames
1372                 */
1373                netdev_info(wlandev->netdev, "linkstatus=AP_INRANGE\n");
1374
1375                hw->link_status = HFA384x_LINK_CONNECTED;
1376                netif_carrier_on(wlandev->netdev);
1377
1378                break;
1379
1380        case HFA384x_LINK_ASSOCFAIL:
1381                /* This one is actually a peer to CONNECTED.  We've
1382                 * requested a join for a given SSID and optionally BSSID.
1383                 * We can use this one to indicate authentication and
1384                 * association failures.  The trick is going to be
1385                 * 1) identifying the failure, and 2) state management.
1386                 * Response:
1387                 * Disable Transmits, Ignore receives of data frames
1388                 */
1389                if (hw->join_ap && --hw->join_retries > 0) {
1390                        struct hfa384x_join_request_data joinreq;
1391
1392                        joinreq = hw->joinreq;
1393                        /* Send the join request */
1394                        hfa384x_drvr_setconfig(hw,
1395                                               HFA384x_RID_JOINREQUEST,
1396                                               &joinreq,
1397                                               HFA384x_RID_JOINREQUEST_LEN);
1398                        netdev_info(wlandev->netdev,
1399                                    "linkstatus=ASSOCFAIL (re-submitting join)\n");
1400                } else {
1401                        netdev_info(wlandev->netdev, "linkstatus=ASSOCFAIL (unhandled)\n");
1402                }
1403
1404                netif_carrier_off(wlandev->netdev);
1405
1406                /* signal back up to cfg80211 layer */
1407                prism2_connect_result(wlandev, P80211ENUM_truth_true);
1408
1409                break;
1410
1411        default:
1412                /* This is bad, IO port problems? */
1413                netdev_warn(wlandev->netdev,
1414                            "unknown linkstatus=0x%02x\n", hw->link_status);
1415                return;
1416        }
1417
1418        wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED);
1419}
1420
1421/*
1422 * prism2sta_inf_linkstatus
1423 *
1424 * Handles the receipt of a Link Status info frame.
1425 *
1426 * Arguments:
1427 *      wlandev         wlan device structure
1428 *      inf             ptr to info frame (contents in hfa384x order)
1429 *
1430 * Returns:
1431 *      nothing
1432 *
1433 * Side effects:
1434 *
1435 * Call context:
1436 *      interrupt
1437 */
1438static void prism2sta_inf_linkstatus(struct wlandevice *wlandev,
1439                                     struct hfa384x_inf_frame *inf)
1440{
1441        struct hfa384x *hw = wlandev->priv;
1442
1443        hw->link_status_new = le16_to_cpu(inf->info.linkstatus.linkstatus);
1444
1445        schedule_work(&hw->link_bh);
1446}
1447
1448/*
1449 * prism2sta_inf_assocstatus
1450 *
1451 * Handles the receipt of an Association Status info frame. Should
1452 * be present in APs only.
1453 *
1454 * Arguments:
1455 *      wlandev         wlan device structure
1456 *      inf             ptr to info frame (contents in hfa384x order)
1457 *
1458 * Returns:
1459 *      nothing
1460 *
1461 * Side effects:
1462 *
1463 * Call context:
1464 *      interrupt
1465 */
1466static void prism2sta_inf_assocstatus(struct wlandevice *wlandev,
1467                                      struct hfa384x_inf_frame *inf)
1468{
1469        struct hfa384x *hw = wlandev->priv;
1470        struct hfa384x_assoc_status rec;
1471        int i;
1472
1473        memcpy(&rec, &inf->info.assocstatus, sizeof(rec));
1474        le16_to_cpus(&rec.assocstatus);
1475        le16_to_cpus(&rec.reason);
1476
1477        /*
1478         * Find the address in the list of authenticated stations.
1479         * If it wasn't found, then this address has not been previously
1480         * authenticated and something weird has happened if this is
1481         * anything other than an "authentication failed" message.
1482         * If the address was found, then set the "associated" flag for
1483         * that station, based on whether the station is associating or
1484         * losing its association.  Something weird has also happened
1485         * if we find the address in the list of authenticated stations
1486         * but we are getting an "authentication failed" message.
1487         */
1488
1489        for (i = 0; i < hw->authlist.cnt; i++)
1490                if (ether_addr_equal(rec.sta_addr, hw->authlist.addr[i]))
1491                        break;
1492
1493        if (i >= hw->authlist.cnt) {
1494                if (rec.assocstatus != HFA384x_ASSOCSTATUS_AUTHFAIL)
1495                        netdev_warn(wlandev->netdev,
1496                                    "assocstatus info frame received for non-authenticated station.\n");
1497        } else {
1498                hw->authlist.assoc[i] =
1499                    (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC ||
1500                     rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC);
1501
1502                if (rec.assocstatus == HFA384x_ASSOCSTATUS_AUTHFAIL)
1503                        netdev_warn(wlandev->netdev,
1504                                    "authfail assocstatus info frame received for authenticated station.\n");
1505        }
1506}
1507
1508/*
1509 * prism2sta_inf_authreq
1510 *
1511 * Handles the receipt of an Authentication Request info frame. Should
1512 * be present in APs only.
1513 *
1514 * Arguments:
1515 *      wlandev         wlan device structure
1516 *      inf             ptr to info frame (contents in hfa384x order)
1517 *
1518 * Returns:
1519 *      nothing
1520 *
1521 * Side effects:
1522 *
1523 * Call context:
1524 *      interrupt
1525 *
1526 */
1527static void prism2sta_inf_authreq(struct wlandevice *wlandev,
1528                                  struct hfa384x_inf_frame *inf)
1529{
1530        struct hfa384x *hw = wlandev->priv;
1531        struct sk_buff *skb;
1532
1533        skb = dev_alloc_skb(sizeof(*inf));
1534        if (skb) {
1535                skb_put(skb, sizeof(*inf));
1536                memcpy(skb->data, inf, sizeof(*inf));
1537                skb_queue_tail(&hw->authq, skb);
1538                schedule_work(&hw->link_bh);
1539        }
1540}
1541
1542static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev,
1543                                        struct hfa384x_inf_frame *inf)
1544{
1545        struct hfa384x *hw = wlandev->priv;
1546        struct hfa384x_authenticate_station_data rec;
1547
1548        int i, added, result, cnt;
1549        u8 *addr;
1550
1551        /*
1552         * Build the AuthenticateStation record.  Initialize it for denying
1553         * authentication.
1554         */
1555
1556        ether_addr_copy(rec.address, inf->info.authreq.sta_addr);
1557        rec.status = cpu_to_le16(P80211ENUM_status_unspec_failure);
1558
1559        /*
1560         * Authenticate based on the access mode.
1561         */
1562
1563        switch (hw->accessmode) {
1564        case WLAN_ACCESS_NONE:
1565
1566                /*
1567                 * Deny all new authentications.  However, if a station
1568                 * is ALREADY authenticated, then accept it.
1569                 */
1570
1571                for (i = 0; i < hw->authlist.cnt; i++)
1572                        if (ether_addr_equal(rec.address,
1573                                             hw->authlist.addr[i])) {
1574                                rec.status = cpu_to_le16(P80211ENUM_status_successful);
1575                                break;
1576                        }
1577
1578                break;
1579
1580        case WLAN_ACCESS_ALL:
1581
1582                /*
1583                 * Allow all authentications.
1584                 */
1585
1586                rec.status = cpu_to_le16(P80211ENUM_status_successful);
1587                break;
1588
1589        case WLAN_ACCESS_ALLOW:
1590
1591                /*
1592                 * Only allow the authentication if the MAC address
1593                 * is in the list of allowed addresses.
1594                 *
1595                 * Since this is the interrupt handler, we may be here
1596                 * while the access list is in the middle of being
1597                 * updated.  Choose the list which is currently okay.
1598                 * See "prism2mib_priv_accessallow()" for details.
1599                 */
1600
1601                if (hw->allow.modify == 0) {
1602                        cnt = hw->allow.cnt;
1603                        addr = hw->allow.addr[0];
1604                } else {
1605                        cnt = hw->allow.cnt1;
1606                        addr = hw->allow.addr1[0];
1607                }
1608
1609                for (i = 0; i < cnt; i++, addr += ETH_ALEN)
1610                        if (ether_addr_equal(rec.address, addr)) {
1611                                rec.status = cpu_to_le16(P80211ENUM_status_successful);
1612                                break;
1613                        }
1614
1615                break;
1616
1617        case WLAN_ACCESS_DENY:
1618
1619                /*
1620                 * Allow the authentication UNLESS the MAC address is
1621                 * in the list of denied addresses.
1622                 *
1623                 * Since this is the interrupt handler, we may be here
1624                 * while the access list is in the middle of being
1625                 * updated.  Choose the list which is currently okay.
1626                 * See "prism2mib_priv_accessdeny()" for details.
1627                 */
1628
1629                if (hw->deny.modify == 0) {
1630                        cnt = hw->deny.cnt;
1631                        addr = hw->deny.addr[0];
1632                } else {
1633                        cnt = hw->deny.cnt1;
1634                        addr = hw->deny.addr1[0];
1635                }
1636
1637                rec.status = cpu_to_le16(P80211ENUM_status_successful);
1638
1639                for (i = 0; i < cnt; i++, addr += ETH_ALEN)
1640                        if (ether_addr_equal(rec.address, addr)) {
1641                                rec.status = cpu_to_le16(P80211ENUM_status_unspec_failure);
1642                                break;
1643                        }
1644
1645                break;
1646        }
1647
1648        /*
1649         * If the authentication is okay, then add the MAC address to the
1650         * list of authenticated stations.  Don't add the address if it
1651         * is already in the list. (802.11b does not seem to disallow
1652         * a station from issuing an authentication request when the
1653         * station is already authenticated. Does this sort of thing
1654         * ever happen?  We might as well do the check just in case.)
1655         */
1656
1657        added = 0;
1658
1659        if (rec.status == cpu_to_le16(P80211ENUM_status_successful)) {
1660                for (i = 0; i < hw->authlist.cnt; i++)
1661                        if (ether_addr_equal(rec.address,
1662                                             hw->authlist.addr[i]))
1663                                break;
1664
1665                if (i >= hw->authlist.cnt) {
1666                        if (hw->authlist.cnt >= WLAN_AUTH_MAX) {
1667                                rec.status = cpu_to_le16(P80211ENUM_status_ap_full);
1668                        } else {
1669                                ether_addr_copy(hw->authlist.addr[hw->authlist.cnt],
1670                                                rec.address);
1671                                hw->authlist.cnt++;
1672                                added = 1;
1673                        }
1674                }
1675        }
1676
1677        /*
1678         * Send back the results of the authentication.  If this doesn't work,
1679         * then make sure to remove the address from the authenticated list if
1680         * it was added.
1681         */
1682
1683        rec.algorithm = inf->info.authreq.algorithm;
1684
1685        result = hfa384x_drvr_setconfig(hw, HFA384x_RID_AUTHENTICATESTA,
1686                                        &rec, sizeof(rec));
1687        if (result) {
1688                if (added)
1689                        hw->authlist.cnt--;
1690                netdev_err(wlandev->netdev,
1691                           "setconfig(authenticatestation) failed, result=%d\n",
1692                           result);
1693        }
1694}
1695
1696/*
1697 * prism2sta_inf_psusercnt
1698 *
1699 * Handles the receipt of a PowerSaveUserCount info frame. Should
1700 * be present in APs only.
1701 *
1702 * Arguments:
1703 *      wlandev         wlan device structure
1704 *      inf             ptr to info frame (contents in hfa384x order)
1705 *
1706 * Returns:
1707 *      nothing
1708 *
1709 * Side effects:
1710 *
1711 * Call context:
1712 *      interrupt
1713 */
1714static void prism2sta_inf_psusercnt(struct wlandevice *wlandev,
1715                                    struct hfa384x_inf_frame *inf)
1716{
1717        struct hfa384x *hw = wlandev->priv;
1718
1719        hw->psusercount = le16_to_cpu(inf->info.psusercnt.usercnt);
1720}
1721
1722/*
1723 * prism2sta_ev_info
1724 *
1725 * Handles the Info event.
1726 *
1727 * Arguments:
1728 *      wlandev         wlan device structure
1729 *      inf             ptr to a generic info frame
1730 *
1731 * Returns:
1732 *      nothing
1733 *
1734 * Side effects:
1735 *
1736 * Call context:
1737 *      interrupt
1738 */
1739void prism2sta_ev_info(struct wlandevice *wlandev,
1740                       struct hfa384x_inf_frame *inf)
1741{
1742        le16_to_cpus(&inf->infotype);
1743        /* Dispatch */
1744        switch (inf->infotype) {
1745        case HFA384x_IT_HANDOVERADDR:
1746                prism2sta_inf_handover(wlandev, inf);
1747                break;
1748        case HFA384x_IT_COMMTALLIES:
1749                prism2sta_inf_tallies(wlandev, inf);
1750                break;
1751        case HFA384x_IT_HOSTSCANRESULTS:
1752                prism2sta_inf_hostscanresults(wlandev, inf);
1753                break;
1754        case HFA384x_IT_SCANRESULTS:
1755                prism2sta_inf_scanresults(wlandev, inf);
1756                break;
1757        case HFA384x_IT_CHINFORESULTS:
1758                prism2sta_inf_chinforesults(wlandev, inf);
1759                break;
1760        case HFA384x_IT_LINKSTATUS:
1761                prism2sta_inf_linkstatus(wlandev, inf);
1762                break;
1763        case HFA384x_IT_ASSOCSTATUS:
1764                prism2sta_inf_assocstatus(wlandev, inf);
1765                break;
1766        case HFA384x_IT_AUTHREQ:
1767                prism2sta_inf_authreq(wlandev, inf);
1768                break;
1769        case HFA384x_IT_PSUSERCNT:
1770                prism2sta_inf_psusercnt(wlandev, inf);
1771                break;
1772        case HFA384x_IT_KEYIDCHANGED:
1773                netdev_warn(wlandev->netdev, "Unhandled IT_KEYIDCHANGED\n");
1774                break;
1775        case HFA384x_IT_ASSOCREQ:
1776                netdev_warn(wlandev->netdev, "Unhandled IT_ASSOCREQ\n");
1777                break;
1778        case HFA384x_IT_MICFAILURE:
1779                netdev_warn(wlandev->netdev, "Unhandled IT_MICFAILURE\n");
1780                break;
1781        default:
1782                netdev_warn(wlandev->netdev,
1783                            "Unknown info type=0x%02x\n", inf->infotype);
1784                break;
1785        }
1786}
1787
1788/*
1789 * prism2sta_ev_txexc
1790 *
1791 * Handles the TxExc event.  A Transmit Exception event indicates
1792 * that the MAC's TX process was unsuccessful - so the packet did
1793 * not get transmitted.
1794 *
1795 * Arguments:
1796 *      wlandev         wlan device structure
1797 *      status          tx frame status word
1798 *
1799 * Returns:
1800 *      nothing
1801 *
1802 * Side effects:
1803 *
1804 * Call context:
1805 *      interrupt
1806 */
1807void prism2sta_ev_txexc(struct wlandevice *wlandev, u16 status)
1808{
1809        pr_debug("TxExc status=0x%x.\n", status);
1810}
1811
1812/*
1813 * prism2sta_ev_tx
1814 *
1815 * Handles the Tx event.
1816 *
1817 * Arguments:
1818 *      wlandev         wlan device structure
1819 *      status          tx frame status word
1820 * Returns:
1821 *      nothing
1822 *
1823 * Side effects:
1824 *
1825 * Call context:
1826 *      interrupt
1827 */
1828void prism2sta_ev_tx(struct wlandevice *wlandev, u16 status)
1829{
1830        pr_debug("Tx Complete, status=0x%04x\n", status);
1831        /* update linux network stats */
1832        wlandev->netdev->stats.tx_packets++;
1833}
1834
1835/*
1836 * prism2sta_ev_alloc
1837 *
1838 * Handles the Alloc event.
1839 *
1840 * Arguments:
1841 *      wlandev         wlan device structure
1842 *
1843 * Returns:
1844 *      nothing
1845 *
1846 * Side effects:
1847 *
1848 * Call context:
1849 *      interrupt
1850 */
1851void prism2sta_ev_alloc(struct wlandevice *wlandev)
1852{
1853        netif_wake_queue(wlandev->netdev);
1854}
1855
1856/*
1857 * create_wlan
1858 *
1859 * Called at module init time.  This creates the struct wlandevice structure
1860 * and initializes it with relevant bits.
1861 *
1862 * Arguments:
1863 *      none
1864 *
1865 * Returns:
1866 *      the created struct wlandevice structure.
1867 *
1868 * Side effects:
1869 *      also allocates the priv/hw structures.
1870 *
1871 * Call context:
1872 *      process thread
1873 *
1874 */
1875static struct wlandevice *create_wlan(void)
1876{
1877        struct wlandevice *wlandev = NULL;
1878        struct hfa384x *hw = NULL;
1879
1880        /* Alloc our structures */
1881        wlandev = kzalloc(sizeof(*wlandev), GFP_KERNEL);
1882        hw = kzalloc(sizeof(*hw), GFP_KERNEL);
1883
1884        if (!wlandev || !hw) {
1885                kfree(wlandev);
1886                kfree(hw);
1887                return NULL;
1888        }
1889
1890        /* Initialize the network device object. */
1891        wlandev->nsdname = dev_info;
1892        wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
1893        wlandev->priv = hw;
1894        wlandev->open = prism2sta_open;
1895        wlandev->close = prism2sta_close;
1896        wlandev->reset = prism2sta_reset;
1897        wlandev->txframe = prism2sta_txframe;
1898        wlandev->mlmerequest = prism2sta_mlmerequest;
1899        wlandev->set_multicast_list = prism2sta_setmulticast;
1900        wlandev->tx_timeout = hfa384x_tx_timeout;
1901
1902        wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT | P80211_NSDCAP_AUTOJOIN;
1903
1904        /* Initialize the device private data structure. */
1905        hw->dot11_desired_bss_type = 1;
1906
1907        return wlandev;
1908}
1909
1910void prism2sta_commsqual_defer(struct work_struct *data)
1911{
1912        struct hfa384x *hw = container_of(data, struct hfa384x, commsqual_bh);
1913        struct wlandevice *wlandev = hw->wlandev;
1914        struct hfa384x_bytestr32 ssid;
1915        struct p80211msg_dot11req_mibget msg;
1916        struct p80211item_uint32 *mibitem = (struct p80211item_uint32 *)
1917                                                &msg.mibattribute.data;
1918        int result = 0;
1919
1920        if (hw->wlandev->hwremoved)
1921                return;
1922
1923        /* we don't care if we're in AP mode */
1924        if ((wlandev->macmode == WLAN_MACMODE_NONE) ||
1925            (wlandev->macmode == WLAN_MACMODE_ESS_AP)) {
1926                return;
1927        }
1928
1929        /* It only makes sense to poll these in non-IBSS */
1930        if (wlandev->macmode != WLAN_MACMODE_IBSS_STA) {
1931                result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DBMCOMMSQUALITY,
1932                                                &hw->qual, HFA384x_RID_DBMCOMMSQUALITY_LEN);
1933
1934                if (result) {
1935                        netdev_err(wlandev->netdev, "error fetching commsqual\n");
1936                        return;
1937                }
1938
1939                pr_debug("commsqual %d %d %d\n",
1940                         le16_to_cpu(hw->qual.cq_curr_bss),
1941                         le16_to_cpu(hw->qual.asl_curr_bss),
1942                         le16_to_cpu(hw->qual.anl_curr_fc));
1943        }
1944
1945        /* Get the signal rate */
1946        msg.msgcode = DIDMSG_DOT11REQ_MIBGET;
1947        mibitem->did = DIDMIB_P2_MAC_CURRENTTXRATE;
1948        result = p80211req_dorequest(wlandev, (u8 *)&msg);
1949
1950        if (result) {
1951                pr_debug("get signal rate failed, result = %d\n",
1952                         result);
1953                return;
1954        }
1955
1956        switch (mibitem->data) {
1957        case HFA384x_RATEBIT_1:
1958                hw->txrate = 10;
1959                break;
1960        case HFA384x_RATEBIT_2:
1961                hw->txrate = 20;
1962                break;
1963        case HFA384x_RATEBIT_5dot5:
1964                hw->txrate = 55;
1965                break;
1966        case HFA384x_RATEBIT_11:
1967                hw->txrate = 110;
1968                break;
1969        default:
1970                pr_debug("Bad ratebit (%d)\n", mibitem->data);
1971        }
1972
1973        /* Lastly, we need to make sure the BSSID didn't change on us */
1974        result = hfa384x_drvr_getconfig(hw,
1975                                        HFA384x_RID_CURRENTBSSID,
1976                                        wlandev->bssid, WLAN_BSSID_LEN);
1977        if (result) {
1978                pr_debug("getconfig(0x%02x) failed, result = %d\n",
1979                         HFA384x_RID_CURRENTBSSID, result);
1980                return;
1981        }
1982
1983        result = hfa384x_drvr_getconfig(hw,
1984                                        HFA384x_RID_CURRENTSSID,
1985                                        &ssid, sizeof(ssid));
1986        if (result) {
1987                pr_debug("getconfig(0x%02x) failed, result = %d\n",
1988                         HFA384x_RID_CURRENTSSID, result);
1989                return;
1990        }
1991        prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid,
1992                                (struct p80211pstrd *)&wlandev->ssid);
1993
1994        /* Reschedule timer */
1995        mod_timer(&hw->commsqual_timer, jiffies + HZ);
1996}
1997
1998void prism2sta_commsqual_timer(struct timer_list *t)
1999{
2000        struct hfa384x *hw = from_timer(hw, t, commsqual_timer);
2001
2002        schedule_work(&hw->commsqual_bh);
2003}
2004