root/drivers/staging/wlan-ng/prism2sta.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. prism2sta_open
  2. prism2sta_close
  3. prism2sta_reset
  4. prism2sta_txframe
  5. prism2sta_mlmerequest
  6. prism2sta_ifstate
  7. prism2sta_getcardinfo
  8. prism2sta_globalsetup
  9. prism2sta_setmulticast
  10. prism2sta_inf_handover
  11. prism2sta_inf_tallies
  12. prism2sta_inf_scanresults
  13. prism2sta_inf_hostscanresults
  14. prism2sta_inf_chinforesults
  15. prism2sta_processing_defer
  16. prism2sta_inf_linkstatus
  17. prism2sta_inf_assocstatus
  18. prism2sta_inf_authreq
  19. prism2sta_inf_authreq_defer
  20. prism2sta_inf_psusercnt
  21. prism2sta_ev_info
  22. prism2sta_ev_txexc
  23. prism2sta_ev_tx
  24. prism2sta_ev_alloc
  25. create_wlan
  26. prism2sta_commsqual_defer
  27. prism2sta_commsqual_timer

   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 
  84 static char *dev_info = "prism2_usb";
  85 static struct wlandevice *create_wlan(void);
  86 
  87 int prism2_reset_holdtime = 30; /* Reset hold time in ms */
  88 int prism2_reset_settletime = 100;      /* Reset settle time in ms */
  89 
  90 static int prism2_doreset;      /* Do a reset at init? */
  91 
  92 module_param(prism2_doreset, int, 0644);
  93 MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization");
  94 
  95 module_param(prism2_reset_holdtime, int, 0644);
  96 MODULE_PARM_DESC(prism2_reset_holdtime, "reset hold time in ms");
  97 module_param(prism2_reset_settletime, int, 0644);
  98 MODULE_PARM_DESC(prism2_reset_settletime, "reset settle time in ms");
  99 
 100 MODULE_LICENSE("Dual MPL/GPL");
 101 
 102 static int prism2sta_open(struct wlandevice *wlandev);
 103 static int prism2sta_close(struct wlandevice *wlandev);
 104 static void prism2sta_reset(struct wlandevice *wlandev);
 105 static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb,
 106                              union p80211_hdr *p80211_hdr,
 107                              struct p80211_metawep *p80211_wep);
 108 static int prism2sta_mlmerequest(struct wlandevice *wlandev,
 109                                  struct p80211msg *msg);
 110 static int prism2sta_getcardinfo(struct wlandevice *wlandev);
 111 static int prism2sta_globalsetup(struct wlandevice *wlandev);
 112 static int prism2sta_setmulticast(struct wlandevice *wlandev,
 113                                   struct net_device *dev);
 114 
 115 static void prism2sta_inf_handover(struct wlandevice *wlandev,
 116                                    struct hfa384x_inf_frame *inf);
 117 static void prism2sta_inf_tallies(struct wlandevice *wlandev,
 118                                   struct hfa384x_inf_frame *inf);
 119 static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev,
 120                                           struct hfa384x_inf_frame *inf);
 121 static void prism2sta_inf_scanresults(struct wlandevice *wlandev,
 122                                       struct hfa384x_inf_frame *inf);
 123 static void prism2sta_inf_chinforesults(struct wlandevice *wlandev,
 124                                         struct hfa384x_inf_frame *inf);
 125 static void prism2sta_inf_linkstatus(struct wlandevice *wlandev,
 126                                      struct hfa384x_inf_frame *inf);
 127 static void prism2sta_inf_assocstatus(struct wlandevice *wlandev,
 128                                       struct hfa384x_inf_frame *inf);
 129 static void prism2sta_inf_authreq(struct wlandevice *wlandev,
 130                                   struct hfa384x_inf_frame *inf);
 131 static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev,
 132                                         struct hfa384x_inf_frame *inf);
 133 static 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  */
 157 static 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  */
 191 static 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  */
 219 static 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  */
 244 static 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  */
 283 static 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  */
 409 u32 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 to
 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  */
 582 static 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;
 887 failed:
 888         netdev_err(wlandev->netdev, "Failed, result=%d\n", result);
 889 done:
 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  */
 911 static 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 
 920 static 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);
 940 exit:
 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  */
 962 static 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  */
 985 static 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  */
1031 static 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  */
1086 static 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  */
1127 static 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 
1170 void 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 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  */
1438 static 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  */
1466 static 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  */
1527 static 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 
1542 static 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  */
1714 static 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  */
1739 void 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  */
1807 void 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  */
1828 void 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  */
1851 void 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  */
1875 static 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 
1910 void 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 
1998 void 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 }

/* [<][>][^][v][top][bottom][index][help] */