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