Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
0002 /*
0003  *
0004  * Implements the station functionality for prism2
0005  *
0006  * Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
0007  * --------------------------------------------------------------------
0008  *
0009  * linux-wlan
0010  *
0011  *   The contents of this file are subject to the Mozilla Public
0012  *   License Version 1.1 (the "License"); you may not use this file
0013  *   except in compliance with the License. You may obtain a copy of
0014  *   the License at http://www.mozilla.org/MPL/
0015  *
0016  *   Software distributed under the License is distributed on an "AS
0017  *   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
0018  *   implied. See the License for the specific language governing
0019  *   rights and limitations under the License.
0020  *
0021  *   Alternatively, the contents of this file may be used under the
0022  *   terms of the GNU Public License version 2 (the "GPL"), in which
0023  *   case the provisions of the GPL are applicable instead of the
0024  *   above.  If you wish to allow the use of your version of this file
0025  *   only under the terms of the GPL and not to allow others to use
0026  *   your version of this file under the MPL, indicate your decision
0027  *   by deleting the provisions above and replace them with the notice
0028  *   and other provisions required by the GPL.  If you do not delete
0029  *   the provisions above, a recipient may use your version of this
0030  *   file under either the MPL or the GPL.
0031  *
0032  * --------------------------------------------------------------------
0033  *
0034  * Inquiries regarding the linux-wlan Open Source project can be
0035  * made directly to:
0036  *
0037  * AbsoluteValue Systems Inc.
0038  * info@linux-wlan.com
0039  * http://www.linux-wlan.com
0040  *
0041  * --------------------------------------------------------------------
0042  *
0043  * Portions of the development of this software were funded by
0044  * Intersil Corporation as part of PRISM(R) chipset product development.
0045  *
0046  * --------------------------------------------------------------------
0047  *
0048  * This file implements the module and linux pcmcia routines for the
0049  * prism2 driver.
0050  *
0051  * --------------------------------------------------------------------
0052  */
0053 
0054 #include <linux/module.h>
0055 #include <linux/kernel.h>
0056 #include <linux/sched.h>
0057 #include <linux/types.h>
0058 #include <linux/slab.h>
0059 #include <linux/wireless.h>
0060 #include <linux/netdevice.h>
0061 #include <linux/workqueue.h>
0062 #include <linux/byteorder/generic.h>
0063 #include <linux/etherdevice.h>
0064 
0065 #include <linux/io.h>
0066 #include <linux/delay.h>
0067 #include <asm/byteorder.h>
0068 #include <linux/if_arp.h>
0069 #include <linux/if_ether.h>
0070 #include <linux/bitops.h>
0071 
0072 #include "p80211types.h"
0073 #include "p80211hdr.h"
0074 #include "p80211mgmt.h"
0075 #include "p80211conv.h"
0076 #include "p80211msg.h"
0077 #include "p80211netdev.h"
0078 #include "p80211req.h"
0079 #include "p80211metadef.h"
0080 #include "p80211metastruct.h"
0081 #include "hfa384x.h"
0082 #include "prism2mgmt.h"
0083 
0084 static char *dev_info = "prism2_usb";
0085 static struct wlandevice *create_wlan(void);
0086 
0087 int prism2_reset_holdtime = 30; /* Reset hold time in ms */
0088 int prism2_reset_settletime = 100;  /* Reset settle time in ms */
0089 
0090 static int prism2_doreset;  /* Do a reset at init? */
0091 
0092 module_param(prism2_doreset, int, 0644);
0093 MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization");
0094 
0095 module_param(prism2_reset_holdtime, int, 0644);
0096 MODULE_PARM_DESC(prism2_reset_holdtime, "reset hold time in ms");
0097 module_param(prism2_reset_settletime, int, 0644);
0098 MODULE_PARM_DESC(prism2_reset_settletime, "reset settle time in ms");
0099 
0100 MODULE_LICENSE("Dual MPL/GPL");
0101 
0102 static int prism2sta_open(struct wlandevice *wlandev);
0103 static int prism2sta_close(struct wlandevice *wlandev);
0104 static void prism2sta_reset(struct wlandevice *wlandev);
0105 static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb,
0106                  struct p80211_hdr *p80211_hdr,
0107                  struct p80211_metawep *p80211_wep);
0108 static int prism2sta_mlmerequest(struct wlandevice *wlandev,
0109                  struct p80211msg *msg);
0110 static int prism2sta_getcardinfo(struct wlandevice *wlandev);
0111 static int prism2sta_globalsetup(struct wlandevice *wlandev);
0112 static int prism2sta_setmulticast(struct wlandevice *wlandev,
0113                   struct net_device *dev);
0114 
0115 static void prism2sta_inf_handover(struct wlandevice *wlandev,
0116                    struct hfa384x_inf_frame *inf);
0117 static void prism2sta_inf_tallies(struct wlandevice *wlandev,
0118                   struct hfa384x_inf_frame *inf);
0119 static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev,
0120                       struct hfa384x_inf_frame *inf);
0121 static void prism2sta_inf_scanresults(struct wlandevice *wlandev,
0122                       struct hfa384x_inf_frame *inf);
0123 static void prism2sta_inf_chinforesults(struct wlandevice *wlandev,
0124                     struct hfa384x_inf_frame *inf);
0125 static void prism2sta_inf_linkstatus(struct wlandevice *wlandev,
0126                      struct hfa384x_inf_frame *inf);
0127 static void prism2sta_inf_assocstatus(struct wlandevice *wlandev,
0128                       struct hfa384x_inf_frame *inf);
0129 static void prism2sta_inf_authreq(struct wlandevice *wlandev,
0130                   struct hfa384x_inf_frame *inf);
0131 static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev,
0132                     struct hfa384x_inf_frame *inf);
0133 static void prism2sta_inf_psusercnt(struct wlandevice *wlandev,
0134                     struct hfa384x_inf_frame *inf);
0135 
0136 /*
0137  * prism2sta_open
0138  *
0139  * WLAN device open method.  Called from p80211netdev when kernel
0140  * device open (start) method is called in response to the
0141  * SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
0142  * from clear to set.
0143  *
0144  * Arguments:
0145  *  wlandev     wlan device structure
0146  *
0147  * Returns:
0148  *  0   success
0149  *  >0  f/w reported error
0150  *  <0  driver reported error
0151  *
0152  * Side effects:
0153  *
0154  * Call context:
0155  *  process thread
0156  */
0157 static int prism2sta_open(struct wlandevice *wlandev)
0158 {
0159     /* We don't currently have to do anything else.
0160      * The setup of the MAC should be subsequently completed via
0161      * the mlme commands.
0162      * Higher layers know we're ready from dev->start==1 and
0163      * dev->tbusy==0.  Our rx path knows to pass up received/
0164      * frames because of dev->flags&IFF_UP is true.
0165      */
0166 
0167     return 0;
0168 }
0169 
0170 /*
0171  * prism2sta_close
0172  *
0173  * WLAN device close method.  Called from p80211netdev when kernel
0174  * device close method is called in response to the
0175  * SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
0176  * from set to clear.
0177  *
0178  * Arguments:
0179  *  wlandev     wlan device structure
0180  *
0181  * Returns:
0182  *  0   success
0183  *  >0  f/w reported error
0184  *  <0  driver reported error
0185  *
0186  * Side effects:
0187  *
0188  * Call context:
0189  *  process thread
0190  */
0191 static int prism2sta_close(struct wlandevice *wlandev)
0192 {
0193     /* We don't currently have to do anything else.
0194      * Higher layers know we're not ready from dev->start==0 and
0195      * dev->tbusy==1.  Our rx path knows to not pass up received
0196      * frames because of dev->flags&IFF_UP is false.
0197      */
0198 
0199     return 0;
0200 }
0201 
0202 /*
0203  * prism2sta_reset
0204  *
0205  * Currently not implemented.
0206  *
0207  * Arguments:
0208  *  wlandev     wlan device structure
0209  *  none
0210  *
0211  * Returns:
0212  *  nothing
0213  *
0214  * Side effects:
0215  *
0216  * Call context:
0217  *  process thread
0218  */
0219 static void prism2sta_reset(struct wlandevice *wlandev)
0220 {
0221 }
0222 
0223 /*
0224  * prism2sta_txframe
0225  *
0226  * Takes a frame from p80211 and queues it for transmission.
0227  *
0228  * Arguments:
0229  *  wlandev     wlan device structure
0230  *  pb      packet buffer struct.  Contains an 802.11
0231  *          data frame.
0232  *       p80211_hdr      points to the 802.11 header for the packet.
0233  * Returns:
0234  *  0       Success and more buffs available
0235  *  1       Success but no more buffs
0236  *  2       Allocation failure
0237  *  4       Buffer full or queue busy
0238  *
0239  * Side effects:
0240  *
0241  * Call context:
0242  *  process thread
0243  */
0244 static int prism2sta_txframe(struct wlandevice *wlandev, struct sk_buff *skb,
0245                  struct p80211_hdr *p80211_hdr,
0246                  struct p80211_metawep *p80211_wep)
0247 {
0248     struct hfa384x *hw = wlandev->priv;
0249 
0250     /* If necessary, set the 802.11 WEP bit */
0251     if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) ==
0252         HOSTWEP_PRIVACYINVOKED) {
0253         p80211_hdr->frame_control |= cpu_to_le16(WLAN_SET_FC_ISWEP(1));
0254     }
0255 
0256     return hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep);
0257 }
0258 
0259 /*
0260  * prism2sta_mlmerequest
0261  *
0262  * wlan command message handler.  All we do here is pass the message
0263  * over to the prism2sta_mgmt_handler.
0264  *
0265  * Arguments:
0266  *  wlandev     wlan device structure
0267  *  msg     wlan command message
0268  * Returns:
0269  *  0       success
0270  *  <0      successful acceptance of message, but we're
0271  *          waiting for an async process to finish before
0272  *          we're done with the msg.  When the asynch
0273  *          process is done, we'll call the p80211
0274  *          function p80211req_confirm() .
0275  *  >0      An error occurred while we were handling
0276  *          the message.
0277  *
0278  * Side effects:
0279  *
0280  * Call context:
0281  *  process thread
0282  */
0283 static int prism2sta_mlmerequest(struct wlandevice *wlandev,
0284                  struct p80211msg *msg)
0285 {
0286     struct hfa384x *hw = wlandev->priv;
0287 
0288     int result = 0;
0289 
0290     switch (msg->msgcode) {
0291     case DIDMSG_DOT11REQ_MIBGET:
0292         pr_debug("Received mibget request\n");
0293         result = prism2mgmt_mibset_mibget(wlandev, msg);
0294         break;
0295     case DIDMSG_DOT11REQ_MIBSET:
0296         pr_debug("Received mibset request\n");
0297         result = prism2mgmt_mibset_mibget(wlandev, msg);
0298         break;
0299     case DIDMSG_DOT11REQ_SCAN:
0300         pr_debug("Received scan request\n");
0301         result = prism2mgmt_scan(wlandev, msg);
0302         break;
0303     case DIDMSG_DOT11REQ_SCAN_RESULTS:
0304         pr_debug("Received scan_results request\n");
0305         result = prism2mgmt_scan_results(wlandev, msg);
0306         break;
0307     case DIDMSG_DOT11REQ_START:
0308         pr_debug("Received mlme start request\n");
0309         result = prism2mgmt_start(wlandev, msg);
0310         break;
0311         /*
0312          * Prism2 specific messages
0313          */
0314     case DIDMSG_P2REQ_READPDA:
0315         pr_debug("Received mlme readpda request\n");
0316         result = prism2mgmt_readpda(wlandev, msg);
0317         break;
0318     case DIDMSG_P2REQ_RAMDL_STATE:
0319         pr_debug("Received mlme ramdl_state request\n");
0320         result = prism2mgmt_ramdl_state(wlandev, msg);
0321         break;
0322     case DIDMSG_P2REQ_RAMDL_WRITE:
0323         pr_debug("Received mlme ramdl_write request\n");
0324         result = prism2mgmt_ramdl_write(wlandev, msg);
0325         break;
0326     case DIDMSG_P2REQ_FLASHDL_STATE:
0327         pr_debug("Received mlme flashdl_state request\n");
0328         result = prism2mgmt_flashdl_state(wlandev, msg);
0329         break;
0330     case DIDMSG_P2REQ_FLASHDL_WRITE:
0331         pr_debug("Received mlme flashdl_write request\n");
0332         result = prism2mgmt_flashdl_write(wlandev, msg);
0333         break;
0334         /*
0335          * Linux specific messages
0336          */
0337     case DIDMSG_LNXREQ_HOSTWEP:
0338         break;      /* ignore me. */
0339     case DIDMSG_LNXREQ_IFSTATE: {
0340         struct p80211msg_lnxreq_ifstate *ifstatemsg;
0341 
0342         pr_debug("Received mlme ifstate request\n");
0343         ifstatemsg = (struct p80211msg_lnxreq_ifstate *)msg;
0344         result = prism2sta_ifstate(wlandev,
0345                        ifstatemsg->ifstate.data);
0346         ifstatemsg->resultcode.status =
0347             P80211ENUM_msgitem_status_data_ok;
0348         ifstatemsg->resultcode.data = result;
0349         result = 0;
0350         break;
0351     }
0352     case DIDMSG_LNXREQ_WLANSNIFF:
0353         pr_debug("Received mlme wlansniff request\n");
0354         result = prism2mgmt_wlansniff(wlandev, msg);
0355         break;
0356     case DIDMSG_LNXREQ_AUTOJOIN:
0357         pr_debug("Received mlme autojoin request\n");
0358         result = prism2mgmt_autojoin(wlandev, msg);
0359         break;
0360     case DIDMSG_LNXREQ_COMMSQUALITY: {
0361         struct p80211msg_lnxreq_commsquality *qualmsg;
0362 
0363         pr_debug("Received commsquality request\n");
0364 
0365         qualmsg = (struct p80211msg_lnxreq_commsquality *)msg;
0366 
0367         qualmsg->link.status = P80211ENUM_msgitem_status_data_ok;
0368         qualmsg->level.status = P80211ENUM_msgitem_status_data_ok;
0369         qualmsg->noise.status = P80211ENUM_msgitem_status_data_ok;
0370 
0371         qualmsg->link.data = le16_to_cpu(hw->qual.cq_curr_bss);
0372         qualmsg->level.data = le16_to_cpu(hw->qual.asl_curr_bss);
0373         qualmsg->noise.data = le16_to_cpu(hw->qual.anl_curr_fc);
0374         qualmsg->txrate.data = hw->txrate;
0375 
0376         break;
0377     }
0378     default:
0379         netdev_warn(wlandev->netdev,
0380                 "Unknown mgmt request message 0x%08x",
0381                 msg->msgcode);
0382         break;
0383     }
0384 
0385     return result;
0386 }
0387 
0388 /*
0389  * prism2sta_ifstate
0390  *
0391  * Interface state.  This is the primary WLAN interface enable/disable
0392  * handler.  Following the driver/load/deviceprobe sequence, this
0393  * function must be called with a state of "enable" before any other
0394  * commands will be accepted.
0395  *
0396  * Arguments:
0397  *  wlandev     wlan device structure
0398  *  msgp        ptr to msg buffer
0399  *
0400  * Returns:
0401  *  A p80211 message resultcode value.
0402  *
0403  * Side effects:
0404  *
0405  * Call context:
0406  *  process thread  (usually)
0407  *  interrupt
0408  */
0409 u32 prism2sta_ifstate(struct wlandevice *wlandev, u32 ifstate)
0410 {
0411     struct hfa384x *hw = wlandev->priv;
0412     u32 result;
0413 
0414     result = P80211ENUM_resultcode_implementation_failure;
0415 
0416     pr_debug("Current MSD state(%d), requesting(%d)\n",
0417          wlandev->msdstate, ifstate);
0418     switch (ifstate) {
0419     case P80211ENUM_ifstate_fwload:
0420         switch (wlandev->msdstate) {
0421         case WLAN_MSD_HWPRESENT:
0422             wlandev->msdstate = WLAN_MSD_FWLOAD_PENDING;
0423             /*
0424              * Initialize the device+driver sufficiently
0425              * for firmware loading.
0426              */
0427             result = hfa384x_drvr_start(hw);
0428             if (result) {
0429                 netdev_err(wlandev->netdev,
0430                        "hfa384x_drvr_start() failed,result=%d\n",
0431                        (int)result);
0432                 result =
0433                  P80211ENUM_resultcode_implementation_failure;
0434                 wlandev->msdstate = WLAN_MSD_HWPRESENT;
0435                 break;
0436             }
0437             wlandev->msdstate = WLAN_MSD_FWLOAD;
0438             result = P80211ENUM_resultcode_success;
0439             break;
0440         case WLAN_MSD_FWLOAD:
0441             hfa384x_cmd_initialize(hw);
0442             result = P80211ENUM_resultcode_success;
0443             break;
0444         case WLAN_MSD_RUNNING:
0445             netdev_warn(wlandev->netdev,
0446                     "Cannot enter fwload state from enable state, you must disable first.\n");
0447             result = P80211ENUM_resultcode_invalid_parameters;
0448             break;
0449         case WLAN_MSD_HWFAIL:
0450         default:
0451             /* probe() had a problem or the msdstate contains
0452              * an unrecognized value, there's nothing we can do.
0453              */
0454             result = P80211ENUM_resultcode_implementation_failure;
0455             break;
0456         }
0457         break;
0458     case P80211ENUM_ifstate_enable:
0459         switch (wlandev->msdstate) {
0460         case WLAN_MSD_HWPRESENT:
0461         case WLAN_MSD_FWLOAD:
0462             wlandev->msdstate = WLAN_MSD_RUNNING_PENDING;
0463             /* Initialize the device+driver for full
0464              * operation. Note that this might me an FWLOAD
0465              * to RUNNING transition so we must not do a chip
0466              * or board level reset.  Note that on failure,
0467              * the MSD state is set to HWPRESENT because we
0468              * can't make any assumptions about the state
0469              * of the hardware or a previous firmware load.
0470              */
0471             result = hfa384x_drvr_start(hw);
0472             if (result) {
0473                 netdev_err(wlandev->netdev,
0474                        "hfa384x_drvr_start() failed,result=%d\n",
0475                        (int)result);
0476                 result =
0477                   P80211ENUM_resultcode_implementation_failure;
0478                 wlandev->msdstate = WLAN_MSD_HWPRESENT;
0479                 break;
0480             }
0481 
0482             result = prism2sta_getcardinfo(wlandev);
0483             if (result) {
0484                 netdev_err(wlandev->netdev,
0485                        "prism2sta_getcardinfo() failed,result=%d\n",
0486                        (int)result);
0487                 result =
0488                   P80211ENUM_resultcode_implementation_failure;
0489                 hfa384x_drvr_stop(hw);
0490                 wlandev->msdstate = WLAN_MSD_HWPRESENT;
0491                 break;
0492             }
0493             result = prism2sta_globalsetup(wlandev);
0494             if (result) {
0495                 netdev_err(wlandev->netdev,
0496                        "prism2sta_globalsetup() failed,result=%d\n",
0497                        (int)result);
0498                 result =
0499                   P80211ENUM_resultcode_implementation_failure;
0500                 hfa384x_drvr_stop(hw);
0501                 wlandev->msdstate = WLAN_MSD_HWPRESENT;
0502                 break;
0503             }
0504             wlandev->msdstate = WLAN_MSD_RUNNING;
0505             hw->join_ap = 0;
0506             hw->join_retries = 60;
0507             result = P80211ENUM_resultcode_success;
0508             break;
0509         case WLAN_MSD_RUNNING:
0510             /* Do nothing, we're already in this state. */
0511             result = P80211ENUM_resultcode_success;
0512             break;
0513         case WLAN_MSD_HWFAIL:
0514         default:
0515             /* probe() had a problem or the msdstate contains
0516              * an unrecognized value, there's nothing we can do.
0517              */
0518             result = P80211ENUM_resultcode_implementation_failure;
0519             break;
0520         }
0521         break;
0522     case P80211ENUM_ifstate_disable:
0523         switch (wlandev->msdstate) {
0524         case WLAN_MSD_HWPRESENT:
0525             /* Do nothing, we're already in this state. */
0526             result = P80211ENUM_resultcode_success;
0527             break;
0528         case WLAN_MSD_FWLOAD:
0529         case WLAN_MSD_RUNNING:
0530             wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
0531             /*
0532              * TODO: Shut down the MAC completely. Here a chip
0533              * or board level reset is probably called for.
0534              * After a "disable" _all_ results are lost, even
0535              * those from a fwload.
0536              */
0537             if (!wlandev->hwremoved)
0538                 netif_carrier_off(wlandev->netdev);
0539 
0540             hfa384x_drvr_stop(hw);
0541 
0542             wlandev->macmode = WLAN_MACMODE_NONE;
0543             wlandev->msdstate = WLAN_MSD_HWPRESENT;
0544             result = P80211ENUM_resultcode_success;
0545             break;
0546         case WLAN_MSD_HWFAIL:
0547         default:
0548             /* probe() had a problem or the msdstate contains
0549              * an unrecognized value, there's nothing we can do.
0550              */
0551             result = P80211ENUM_resultcode_implementation_failure;
0552             break;
0553         }
0554         break;
0555     default:
0556         result = P80211ENUM_resultcode_invalid_parameters;
0557         break;
0558     }
0559 
0560     return result;
0561 }
0562 
0563 /*
0564  * prism2sta_getcardinfo
0565  *
0566  * Collect the NICID, firmware version and any other identifiers
0567  * we'd like to have in host-side data structures.
0568  *
0569  * Arguments:
0570  *  wlandev     wlan device structure
0571  *
0572  * Returns:
0573  *  0   success
0574  *  >0  f/w reported error
0575  *  <0  driver reported error
0576  *
0577  * Side effects:
0578  *
0579  * Call context:
0580  *  Either.
0581  */
0582 static int prism2sta_getcardinfo(struct wlandevice *wlandev)
0583 {
0584     int result = 0;
0585     struct hfa384x *hw = wlandev->priv;
0586     u16 temp;
0587     u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN];
0588     u8 addr[ETH_ALEN];
0589 
0590     /* Collect version and compatibility info */
0591     /*  Some are critical, some are not */
0592     /* NIC identity */
0593     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY,
0594                     &hw->ident_nic,
0595                     sizeof(struct hfa384x_compident));
0596     if (result) {
0597         netdev_err(wlandev->netdev, "Failed to retrieve NICIDENTITY\n");
0598         goto failed;
0599     }
0600 
0601     /* get all the nic id fields in host byte order */
0602     le16_to_cpus(&hw->ident_nic.id);
0603     le16_to_cpus(&hw->ident_nic.variant);
0604     le16_to_cpus(&hw->ident_nic.major);
0605     le16_to_cpus(&hw->ident_nic.minor);
0606 
0607     netdev_info(wlandev->netdev, "ident: nic h/w: id=0x%02x %d.%d.%d\n",
0608             hw->ident_nic.id, hw->ident_nic.major,
0609             hw->ident_nic.minor, hw->ident_nic.variant);
0610 
0611     /* Primary f/w identity */
0612     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY,
0613                     &hw->ident_pri_fw,
0614                     sizeof(struct hfa384x_compident));
0615     if (result) {
0616         netdev_err(wlandev->netdev, "Failed to retrieve PRIIDENTITY\n");
0617         goto failed;
0618     }
0619 
0620     /* get all the private fw id fields in host byte order */
0621     le16_to_cpus(&hw->ident_pri_fw.id);
0622     le16_to_cpus(&hw->ident_pri_fw.variant);
0623     le16_to_cpus(&hw->ident_pri_fw.major);
0624     le16_to_cpus(&hw->ident_pri_fw.minor);
0625 
0626     netdev_info(wlandev->netdev, "ident: pri f/w: id=0x%02x %d.%d.%d\n",
0627             hw->ident_pri_fw.id, hw->ident_pri_fw.major,
0628             hw->ident_pri_fw.minor, hw->ident_pri_fw.variant);
0629 
0630     /* Station (Secondary?) f/w identity */
0631     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY,
0632                     &hw->ident_sta_fw,
0633                     sizeof(struct hfa384x_compident));
0634     if (result) {
0635         netdev_err(wlandev->netdev, "Failed to retrieve STAIDENTITY\n");
0636         goto failed;
0637     }
0638 
0639     if (hw->ident_nic.id < 0x8000) {
0640         netdev_err(wlandev->netdev,
0641                "FATAL: Card is not an Intersil Prism2/2.5/3\n");
0642         result = -1;
0643         goto failed;
0644     }
0645 
0646     /* get all the station fw id fields in host byte order */
0647     le16_to_cpus(&hw->ident_sta_fw.id);
0648     le16_to_cpus(&hw->ident_sta_fw.variant);
0649     le16_to_cpus(&hw->ident_sta_fw.major);
0650     le16_to_cpus(&hw->ident_sta_fw.minor);
0651 
0652     /* strip out the 'special' variant bits */
0653     hw->mm_mods = hw->ident_sta_fw.variant & GENMASK(15, 14);
0654     hw->ident_sta_fw.variant &= ~((u16)GENMASK(15, 14));
0655 
0656     if (hw->ident_sta_fw.id == 0x1f) {
0657         netdev_info(wlandev->netdev,
0658                 "ident: sta f/w: id=0x%02x %d.%d.%d\n",
0659                 hw->ident_sta_fw.id, hw->ident_sta_fw.major,
0660                 hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
0661     } else {
0662         netdev_info(wlandev->netdev,
0663                 "ident:  ap f/w: id=0x%02x %d.%d.%d\n",
0664                 hw->ident_sta_fw.id, hw->ident_sta_fw.major,
0665                 hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
0666         netdev_err(wlandev->netdev, "Unsupported Tertiary AP firmware loaded!\n");
0667         goto failed;
0668     }
0669 
0670     /* Compatibility range, Modem supplier */
0671     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE,
0672                     &hw->cap_sup_mfi,
0673                     sizeof(struct hfa384x_caplevel));
0674     if (result) {
0675         netdev_err(wlandev->netdev, "Failed to retrieve MFISUPRANGE\n");
0676         goto failed;
0677     }
0678 
0679     /* get all the Compatibility range, modem interface supplier
0680      * fields in byte order
0681      */
0682     le16_to_cpus(&hw->cap_sup_mfi.role);
0683     le16_to_cpus(&hw->cap_sup_mfi.id);
0684     le16_to_cpus(&hw->cap_sup_mfi.variant);
0685     le16_to_cpus(&hw->cap_sup_mfi.bottom);
0686     le16_to_cpus(&hw->cap_sup_mfi.top);
0687 
0688     netdev_info(wlandev->netdev,
0689             "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
0690             hw->cap_sup_mfi.role, hw->cap_sup_mfi.id,
0691             hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom,
0692             hw->cap_sup_mfi.top);
0693 
0694     /* Compatibility range, Controller supplier */
0695     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE,
0696                     &hw->cap_sup_cfi,
0697                     sizeof(struct hfa384x_caplevel));
0698     if (result) {
0699         netdev_err(wlandev->netdev, "Failed to retrieve CFISUPRANGE\n");
0700         goto failed;
0701     }
0702 
0703     /* get all the Compatibility range, controller interface supplier
0704      * fields in byte order
0705      */
0706     le16_to_cpus(&hw->cap_sup_cfi.role);
0707     le16_to_cpus(&hw->cap_sup_cfi.id);
0708     le16_to_cpus(&hw->cap_sup_cfi.variant);
0709     le16_to_cpus(&hw->cap_sup_cfi.bottom);
0710     le16_to_cpus(&hw->cap_sup_cfi.top);
0711 
0712     netdev_info(wlandev->netdev,
0713             "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
0714             hw->cap_sup_cfi.role, hw->cap_sup_cfi.id,
0715             hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom,
0716             hw->cap_sup_cfi.top);
0717 
0718     /* Compatibility range, Primary f/w supplier */
0719     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE,
0720                     &hw->cap_sup_pri,
0721                     sizeof(struct hfa384x_caplevel));
0722     if (result) {
0723         netdev_err(wlandev->netdev, "Failed to retrieve PRISUPRANGE\n");
0724         goto failed;
0725     }
0726 
0727     /* get all the Compatibility range, primary firmware supplier
0728      * fields in byte order
0729      */
0730     le16_to_cpus(&hw->cap_sup_pri.role);
0731     le16_to_cpus(&hw->cap_sup_pri.id);
0732     le16_to_cpus(&hw->cap_sup_pri.variant);
0733     le16_to_cpus(&hw->cap_sup_pri.bottom);
0734     le16_to_cpus(&hw->cap_sup_pri.top);
0735 
0736     netdev_info(wlandev->netdev,
0737             "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
0738             hw->cap_sup_pri.role, hw->cap_sup_pri.id,
0739             hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom,
0740             hw->cap_sup_pri.top);
0741 
0742     /* Compatibility range, Station f/w supplier */
0743     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE,
0744                     &hw->cap_sup_sta,
0745                     sizeof(struct hfa384x_caplevel));
0746     if (result) {
0747         netdev_err(wlandev->netdev, "Failed to retrieve STASUPRANGE\n");
0748         goto failed;
0749     }
0750 
0751     /* get all the Compatibility range, station firmware supplier
0752      * fields in byte order
0753      */
0754     le16_to_cpus(&hw->cap_sup_sta.role);
0755     le16_to_cpus(&hw->cap_sup_sta.id);
0756     le16_to_cpus(&hw->cap_sup_sta.variant);
0757     le16_to_cpus(&hw->cap_sup_sta.bottom);
0758     le16_to_cpus(&hw->cap_sup_sta.top);
0759 
0760     if (hw->cap_sup_sta.id == 0x04) {
0761         netdev_info(wlandev->netdev,
0762                 "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
0763                 hw->cap_sup_sta.role, hw->cap_sup_sta.id,
0764                 hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
0765                 hw->cap_sup_sta.top);
0766     } else {
0767         netdev_info(wlandev->netdev,
0768                 "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
0769                 hw->cap_sup_sta.role, hw->cap_sup_sta.id,
0770                 hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
0771                 hw->cap_sup_sta.top);
0772     }
0773 
0774     /* Compatibility range, primary f/w actor, CFI supplier */
0775     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES,
0776                     &hw->cap_act_pri_cfi,
0777                     sizeof(struct hfa384x_caplevel));
0778     if (result) {
0779         netdev_err(wlandev->netdev, "Failed to retrieve PRI_CFIACTRANGES\n");
0780         goto failed;
0781     }
0782 
0783     /* get all the Compatibility range, primary f/w actor, CFI supplier
0784      * fields in byte order
0785      */
0786     le16_to_cpus(&hw->cap_act_pri_cfi.role);
0787     le16_to_cpus(&hw->cap_act_pri_cfi.id);
0788     le16_to_cpus(&hw->cap_act_pri_cfi.variant);
0789     le16_to_cpus(&hw->cap_act_pri_cfi.bottom);
0790     le16_to_cpus(&hw->cap_act_pri_cfi.top);
0791 
0792     netdev_info(wlandev->netdev,
0793             "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
0794             hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id,
0795             hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom,
0796             hw->cap_act_pri_cfi.top);
0797 
0798     /* Compatibility range, sta f/w actor, CFI supplier */
0799     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES,
0800                     &hw->cap_act_sta_cfi,
0801                     sizeof(struct hfa384x_caplevel));
0802     if (result) {
0803         netdev_err(wlandev->netdev, "Failed to retrieve STA_CFIACTRANGES\n");
0804         goto failed;
0805     }
0806 
0807     /* get all the Compatibility range, station f/w actor, CFI supplier
0808      * fields in byte order
0809      */
0810     le16_to_cpus(&hw->cap_act_sta_cfi.role);
0811     le16_to_cpus(&hw->cap_act_sta_cfi.id);
0812     le16_to_cpus(&hw->cap_act_sta_cfi.variant);
0813     le16_to_cpus(&hw->cap_act_sta_cfi.bottom);
0814     le16_to_cpus(&hw->cap_act_sta_cfi.top);
0815 
0816     netdev_info(wlandev->netdev,
0817             "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
0818             hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id,
0819             hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom,
0820             hw->cap_act_sta_cfi.top);
0821 
0822     /* Compatibility range, sta f/w actor, MFI supplier */
0823     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES,
0824                     &hw->cap_act_sta_mfi,
0825                     sizeof(struct hfa384x_caplevel));
0826     if (result) {
0827         netdev_err(wlandev->netdev, "Failed to retrieve STA_MFIACTRANGES\n");
0828         goto failed;
0829     }
0830 
0831     /* get all the Compatibility range, station f/w actor, MFI supplier
0832      * fields in byte order
0833      */
0834     le16_to_cpus(&hw->cap_act_sta_mfi.role);
0835     le16_to_cpus(&hw->cap_act_sta_mfi.id);
0836     le16_to_cpus(&hw->cap_act_sta_mfi.variant);
0837     le16_to_cpus(&hw->cap_act_sta_mfi.bottom);
0838     le16_to_cpus(&hw->cap_act_sta_mfi.top);
0839 
0840     netdev_info(wlandev->netdev,
0841             "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
0842             hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id,
0843             hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom,
0844             hw->cap_act_sta_mfi.top);
0845 
0846     /* Serial Number */
0847     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER,
0848                     snum, HFA384x_RID_NICSERIALNUMBER_LEN);
0849     if (!result) {
0850         netdev_info(wlandev->netdev, "Prism2 card SN: %*pE\n",
0851                 HFA384x_RID_NICSERIALNUMBER_LEN, snum);
0852     } else {
0853         netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n");
0854         goto failed;
0855     }
0856 
0857     /* Collect the MAC address */
0858     result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNMACADDR,
0859                     addr, ETH_ALEN);
0860     if (result != 0) {
0861         netdev_err(wlandev->netdev, "Failed to retrieve mac address\n");
0862         goto failed;
0863     }
0864     eth_hw_addr_set(wlandev->netdev, addr);
0865 
0866     /* short preamble is always implemented */
0867     wlandev->nsdcaps |= P80211_NSDCAP_SHORT_PREAMBLE;
0868 
0869     /* find out if hardware wep is implemented */
0870     hfa384x_drvr_getconfig16(hw, HFA384x_RID_PRIVACYOPTIMP, &temp);
0871     if (temp)
0872         wlandev->nsdcaps |= P80211_NSDCAP_HARDWAREWEP;
0873 
0874     /* get the dBm Scaling constant */
0875     hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFDBMADJUST, &temp);
0876     hw->dbmadjust = temp;
0877 
0878     /* Only enable scan by default on newer firmware */
0879     if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
0880                      hw->ident_sta_fw.minor,
0881                      hw->ident_sta_fw.variant) <
0882         HFA384x_FIRMWARE_VERSION(1, 5, 5)) {
0883         wlandev->nsdcaps |= P80211_NSDCAP_NOSCAN;
0884     }
0885 
0886     /* TODO: Set any internally managed config items */
0887 
0888     goto done;
0889 failed:
0890     netdev_err(wlandev->netdev, "Failed, result=%d\n", result);
0891 done:
0892     return result;
0893 }
0894 
0895 /*
0896  * prism2sta_globalsetup
0897  *
0898  * Set any global RIDs that we want to set at device activation.
0899  *
0900  * Arguments:
0901  *  wlandev     wlan device structure
0902  *
0903  * Returns:
0904  *  0   success
0905  *  >0  f/w reported error
0906  *  <0  driver reported error
0907  *
0908  * Side effects:
0909  *
0910  * Call context:
0911  *  process thread
0912  */
0913 static int prism2sta_globalsetup(struct wlandevice *wlandev)
0914 {
0915     struct hfa384x *hw = wlandev->priv;
0916 
0917     /* Set the maximum frame size */
0918     return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN,
0919                     WLAN_DATA_MAXLEN);
0920 }
0921 
0922 static int prism2sta_setmulticast(struct wlandevice *wlandev,
0923                   struct net_device *dev)
0924 {
0925     int result = 0;
0926     struct hfa384x *hw = wlandev->priv;
0927 
0928     u16 promisc;
0929 
0930     /* If we're not ready, what's the point? */
0931     if (hw->state != HFA384x_STATE_RUNNING)
0932         goto exit;
0933 
0934     if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
0935         promisc = P80211ENUM_truth_true;
0936     else
0937         promisc = P80211ENUM_truth_false;
0938 
0939     result =
0940         hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE,
0941                        promisc);
0942 exit:
0943     return result;
0944 }
0945 
0946 /*
0947  * prism2sta_inf_handover
0948  *
0949  * Handles the receipt of a Handover info frame. Should only be present
0950  * in APs only.
0951  *
0952  * Arguments:
0953  *  wlandev     wlan device structure
0954  *  inf     ptr to info frame (contents in hfa384x order)
0955  *
0956  * Returns:
0957  *  nothing
0958  *
0959  * Side effects:
0960  *
0961  * Call context:
0962  *  interrupt
0963  */
0964 static void prism2sta_inf_handover(struct wlandevice *wlandev,
0965                    struct hfa384x_inf_frame *inf)
0966 {
0967     pr_debug("received infoframe:HANDOVER (unhandled)\n");
0968 }
0969 
0970 /*
0971  * prism2sta_inf_tallies
0972  *
0973  * Handles the receipt of a CommTallies info frame.
0974  *
0975  * Arguments:
0976  *  wlandev     wlan device structure
0977  *  inf     ptr to info frame (contents in hfa384x order)
0978  *
0979  * Returns:
0980  *  nothing
0981  *
0982  * Side effects:
0983  *
0984  * Call context:
0985  *  interrupt
0986  */
0987 static void prism2sta_inf_tallies(struct wlandevice *wlandev,
0988                   struct hfa384x_inf_frame *inf)
0989 {
0990     struct hfa384x *hw = wlandev->priv;
0991     __le16 *src16;
0992     u32 *dst;
0993     __le32 *src32;
0994     int i;
0995     int cnt;
0996 
0997     /*
0998      * Determine if these are 16-bit or 32-bit tallies, based on the
0999      * record length of the info record.
1000      */
1001 
1002     cnt = sizeof(struct hfa384x_comm_tallies_32) / sizeof(u32);
1003     if (inf->framelen > 22) {
1004         dst = (u32 *)&hw->tallies;
1005         src32 = (__le32 *)&inf->info.commtallies32;
1006         for (i = 0; i < cnt; i++, dst++, src32++)
1007             *dst += le32_to_cpu(*src32);
1008     } else {
1009         dst = (u32 *)&hw->tallies;
1010         src16 = (__le16 *)&inf->info.commtallies16;
1011         for (i = 0; i < cnt; i++, dst++, src16++)
1012             *dst += le16_to_cpu(*src16);
1013     }
1014 }
1015 
1016 /*
1017  * prism2sta_inf_scanresults
1018  *
1019  * Handles the receipt of a Scan Results info frame.
1020  *
1021  * Arguments:
1022  *  wlandev     wlan device structure
1023  *  inf     ptr to info frame (contents in hfa384x order)
1024  *
1025  * Returns:
1026  *  nothing
1027  *
1028  * Side effects:
1029  *
1030  * Call context:
1031  *  interrupt
1032  */
1033 static void prism2sta_inf_scanresults(struct wlandevice *wlandev,
1034                       struct hfa384x_inf_frame *inf)
1035 {
1036     struct hfa384x *hw = wlandev->priv;
1037     int nbss;
1038     struct hfa384x_scan_result *sr = &inf->info.scanresult;
1039     int i;
1040     struct hfa384x_join_request_data joinreq;
1041     int result;
1042 
1043     /* Get the number of results, first in bytes, then in results */
1044     nbss = (inf->framelen * sizeof(u16)) -
1045         sizeof(inf->infotype) - sizeof(inf->info.scanresult.scanreason);
1046     nbss /= sizeof(struct hfa384x_scan_result_sub);
1047 
1048     /* Print em */
1049     pr_debug("rx scanresults, reason=%d, nbss=%d:\n",
1050          inf->info.scanresult.scanreason, nbss);
1051     for (i = 0; i < nbss; i++) {
1052         pr_debug("chid=%d anl=%d sl=%d bcnint=%d\n",
1053              sr->result[i].chid,
1054              sr->result[i].anl,
1055              sr->result[i].sl, sr->result[i].bcnint);
1056         pr_debug("  capinfo=0x%04x proberesp_rate=%d\n",
1057              sr->result[i].capinfo, sr->result[i].proberesp_rate);
1058     }
1059     /* issue a join request */
1060     joinreq.channel = sr->result[0].chid;
1061     memcpy(joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN);
1062     result = hfa384x_drvr_setconfig(hw,
1063                     HFA384x_RID_JOINREQUEST,
1064                     &joinreq, HFA384x_RID_JOINREQUEST_LEN);
1065     if (result) {
1066         netdev_err(wlandev->netdev, "setconfig(joinreq) failed, result=%d\n",
1067                result);
1068     }
1069 }
1070 
1071 /*
1072  * prism2sta_inf_hostscanresults
1073  *
1074  * Handles the receipt of a Scan Results info frame.
1075  *
1076  * Arguments:
1077  *  wlandev     wlan device structure
1078  *  inf     ptr to info frame (contents in hfa384x order)
1079  *
1080  * Returns:
1081  *  nothing
1082  *
1083  * Side effects:
1084  *
1085  * Call context:
1086  *  interrupt
1087  */
1088 static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev,
1089                       struct hfa384x_inf_frame *inf)
1090 {
1091     struct hfa384x *hw = wlandev->priv;
1092     int nbss;
1093 
1094     nbss = (inf->framelen - 3) / 32;
1095     pr_debug("Received %d hostscan results\n", nbss);
1096 
1097     if (nbss > 32)
1098         nbss = 32;
1099 
1100     kfree(hw->scanresults);
1101 
1102     hw->scanresults = kmemdup(inf, sizeof(*inf), GFP_ATOMIC);
1103 
1104     if (nbss == 0)
1105         nbss = -1;
1106 
1107     /* Notify/wake the sleeping caller. */
1108     hw->scanflag = nbss;
1109     wake_up_interruptible(&hw->cmdq);
1110 };
1111 
1112 /*
1113  * prism2sta_inf_chinforesults
1114  *
1115  * Handles the receipt of a Channel Info Results info frame.
1116  *
1117  * Arguments:
1118  *  wlandev     wlan device structure
1119  *  inf     ptr to info frame (contents in hfa384x order)
1120  *
1121  * Returns:
1122  *  nothing
1123  *
1124  * Side effects:
1125  *
1126  * Call context:
1127  *  interrupt
1128  */
1129 static void prism2sta_inf_chinforesults(struct wlandevice *wlandev,
1130                     struct hfa384x_inf_frame *inf)
1131 {
1132     struct hfa384x *hw = wlandev->priv;
1133     unsigned int i, n;
1134 
1135     hw->channel_info.results.scanchannels =
1136         inf->info.chinforesult.scanchannels;
1137 
1138     for (i = 0, n = 0; i < HFA384x_CHINFORESULT_MAX; i++) {
1139         struct hfa384x_ch_info_result_sub *result;
1140         struct hfa384x_ch_info_result_sub *chinforesult;
1141         int chan;
1142 
1143         if (!(hw->channel_info.results.scanchannels & (1 << i)))
1144             continue;
1145 
1146         result = &inf->info.chinforesult.result[n];
1147         chan = result->chid - 1;
1148 
1149         if (chan < 0 || chan >= HFA384x_CHINFORESULT_MAX)
1150             continue;
1151 
1152         chinforesult = &hw->channel_info.results.result[chan];
1153         chinforesult->chid = chan;
1154         chinforesult->anl = result->anl;
1155         chinforesult->pnl = result->pnl;
1156         chinforesult->active = result->active;
1157 
1158         pr_debug("chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n",
1159              chan + 1,
1160              (chinforesult->active & HFA384x_CHINFORESULT_BSSACTIVE)
1161                 ? "signal" : "noise",
1162              chinforesult->anl, chinforesult->pnl,
1163              (chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE)
1164                 ? 1 : 0);
1165         n++;
1166     }
1167     atomic_set(&hw->channel_info.done, 2);
1168 
1169     hw->channel_info.count = n;
1170 }
1171 
1172 void prism2sta_processing_defer(struct work_struct *data)
1173 {
1174     struct hfa384x *hw = container_of(data, struct hfa384x, link_bh);
1175     struct wlandevice *wlandev = hw->wlandev;
1176     struct hfa384x_bytestr32 ssid;
1177     int result;
1178 
1179     /* First let's process the auth frames */
1180     {
1181         struct sk_buff *skb;
1182         struct hfa384x_inf_frame *inf;
1183 
1184         while ((skb = skb_dequeue(&hw->authq))) {
1185             inf = (struct hfa384x_inf_frame *)skb->data;
1186             prism2sta_inf_authreq_defer(wlandev, inf);
1187         }
1188     }
1189 
1190     /* Now let's handle the linkstatus stuff */
1191     if (hw->link_status == hw->link_status_new)
1192         return;
1193 
1194     hw->link_status = hw->link_status_new;
1195 
1196     switch (hw->link_status) {
1197     case HFA384x_LINK_NOTCONNECTED:
1198         /* I'm currently assuming that this is the initial link
1199          * state.  It should only be possible immediately
1200          * following an Enable command.
1201          * Response:
1202          * Block Transmits, Ignore receives of data frames
1203          */
1204         netif_carrier_off(wlandev->netdev);
1205 
1206         netdev_info(wlandev->netdev, "linkstatus=NOTCONNECTED (unhandled)\n");
1207         break;
1208 
1209     case HFA384x_LINK_CONNECTED:
1210         /* This one indicates a successful scan/join/auth/assoc.
1211          * When we have the full MLME complement, this event will
1212          * signify successful completion of both mlme_authenticate
1213          * and mlme_associate.  State management will get a little
1214          * ugly here.
1215          * Response:
1216          * Indicate authentication and/or association
1217          * Enable Transmits, Receives and pass up data frames
1218          */
1219 
1220         netif_carrier_on(wlandev->netdev);
1221 
1222         /* If we are joining a specific AP, set our
1223          * state and reset retries
1224          */
1225         if (hw->join_ap == 1)
1226             hw->join_ap = 2;
1227         hw->join_retries = 60;
1228 
1229         /* Don't call this in monitor mode */
1230         if (wlandev->netdev->type == ARPHRD_ETHER) {
1231             u16 portstatus;
1232 
1233             netdev_info(wlandev->netdev, "linkstatus=CONNECTED\n");
1234 
1235             /* For non-usb devices, we can use the sync versions */
1236             /* Collect the BSSID, and set state to allow tx */
1237 
1238             result = hfa384x_drvr_getconfig(hw,
1239                             HFA384x_RID_CURRENTBSSID,
1240                             wlandev->bssid,
1241                             WLAN_BSSID_LEN);
1242             if (result) {
1243                 pr_debug
1244                     ("getconfig(0x%02x) failed, result = %d\n",
1245                      HFA384x_RID_CURRENTBSSID, result);
1246                 return;
1247             }
1248 
1249             result = hfa384x_drvr_getconfig(hw,
1250                             HFA384x_RID_CURRENTSSID,
1251                             &ssid, sizeof(ssid));
1252             if (result) {
1253                 pr_debug
1254                     ("getconfig(0x%02x) failed, result = %d\n",
1255                      HFA384x_RID_CURRENTSSID, result);
1256                 return;
1257             }
1258             prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid,
1259                         (struct p80211pstrd *)&wlandev->ssid);
1260 
1261             /* Collect the port status */
1262             result = hfa384x_drvr_getconfig16(hw,
1263                               HFA384x_RID_PORTSTATUS,
1264                               &portstatus);
1265             if (result) {
1266                 pr_debug
1267                     ("getconfig(0x%02x) failed, result = %d\n",
1268                      HFA384x_RID_PORTSTATUS, result);
1269                 return;
1270             }
1271             wlandev->macmode =
1272                 (portstatus == HFA384x_PSTATUS_CONN_IBSS) ?
1273                 WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA;
1274 
1275             /* signal back up to cfg80211 layer */
1276             prism2_connect_result(wlandev, P80211ENUM_truth_false);
1277 
1278             /* Get the ball rolling on the comms quality stuff */
1279             prism2sta_commsqual_defer(&hw->commsqual_bh);
1280         }
1281         break;
1282 
1283     case HFA384x_LINK_DISCONNECTED:
1284         /* This one indicates that our association is gone.  We've
1285          * lost connection with the AP and/or been disassociated.
1286          * This indicates that the MAC has completely cleared it's
1287          * associated state.  We * should send a deauth indication
1288          * (implying disassoc) up * to the MLME.
1289          * Response:
1290          * Indicate Deauthentication
1291          * Block Transmits, Ignore receives of data frames
1292          */
1293         if (wlandev->netdev->type == ARPHRD_ETHER)
1294             netdev_info(wlandev->netdev,
1295                     "linkstatus=DISCONNECTED (unhandled)\n");
1296         wlandev->macmode = WLAN_MACMODE_NONE;
1297 
1298         netif_carrier_off(wlandev->netdev);
1299 
1300         /* signal back up to cfg80211 layer */
1301         prism2_disconnected(wlandev);
1302 
1303         break;
1304 
1305     case HFA384x_LINK_AP_CHANGE:
1306         /* This one indicates that the MAC has decided to and
1307          * successfully completed a change to another AP.  We
1308          * should probably implement a reassociation indication
1309          * in response to this one.  I'm thinking that the
1310          * p80211 layer needs to be notified in case of
1311          * buffering/queueing issues.  User mode also needs to be
1312          * notified so that any BSS dependent elements can be
1313          * updated.
1314          * associated state.  We * should send a deauth indication
1315          * (implying disassoc) up * to the MLME.
1316          * Response:
1317          * Indicate Reassociation
1318          * Enable Transmits, Receives and pass up data frames
1319          */
1320         netdev_info(wlandev->netdev, "linkstatus=AP_CHANGE\n");
1321 
1322         result = hfa384x_drvr_getconfig(hw,
1323                         HFA384x_RID_CURRENTBSSID,
1324                         wlandev->bssid, WLAN_BSSID_LEN);
1325         if (result) {
1326             pr_debug("getconfig(0x%02x) failed, result = %d\n",
1327                  HFA384x_RID_CURRENTBSSID, result);
1328             return;
1329         }
1330 
1331         result = hfa384x_drvr_getconfig(hw,
1332                         HFA384x_RID_CURRENTSSID,
1333                         &ssid, sizeof(ssid));
1334         if (result) {
1335             pr_debug("getconfig(0x%02x) failed, result = %d\n",
1336                  HFA384x_RID_CURRENTSSID, result);
1337             return;
1338         }
1339         prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid,
1340                     (struct p80211pstrd *)&wlandev->ssid);
1341 
1342         hw->link_status = HFA384x_LINK_CONNECTED;
1343         netif_carrier_on(wlandev->netdev);
1344 
1345         /* signal back up to cfg80211 layer */
1346         prism2_roamed(wlandev);
1347 
1348         break;
1349 
1350     case HFA384x_LINK_AP_OUTOFRANGE:
1351         /* This one indicates that the MAC has decided that the
1352          * AP is out of range, but hasn't found a better candidate
1353          * so the MAC maintains its "associated" state in case
1354          * we get back in range.  We should block transmits and
1355          * receives in this state.  Do we need an indication here?
1356          * Probably not since a polling user-mode element would
1357          * get this status from p2PortStatus(FD40). What about
1358          * p80211?
1359          * Response:
1360          * Block Transmits, Ignore receives of data frames
1361          */
1362         netdev_info(wlandev->netdev, "linkstatus=AP_OUTOFRANGE (unhandled)\n");
1363 
1364         netif_carrier_off(wlandev->netdev);
1365 
1366         break;
1367 
1368     case HFA384x_LINK_AP_INRANGE:
1369         /* This one indicates that the MAC has decided that the
1370          * AP is back in range.  We continue working with our
1371          * existing association.
1372          * Response:
1373          * Enable Transmits, Receives and pass up data frames
1374          */
1375         netdev_info(wlandev->netdev, "linkstatus=AP_INRANGE\n");
1376 
1377         hw->link_status = HFA384x_LINK_CONNECTED;
1378         netif_carrier_on(wlandev->netdev);
1379 
1380         break;
1381 
1382     case HFA384x_LINK_ASSOCFAIL:
1383         /* This one is actually a peer to CONNECTED.  We've
1384          * requested a join for a given SSID and optionally BSSID.
1385          * We can use this one to indicate authentication and
1386          * association failures.  The trick is going to be
1387          * 1) identifying the failure, and 2) state management.
1388          * Response:
1389          * Disable Transmits, Ignore receives of data frames
1390          */
1391         if (hw->join_ap && --hw->join_retries > 0) {
1392             struct hfa384x_join_request_data joinreq;
1393 
1394             joinreq = hw->joinreq;
1395             /* Send the join request */
1396             hfa384x_drvr_setconfig(hw,
1397                            HFA384x_RID_JOINREQUEST,
1398                            &joinreq,
1399                            HFA384x_RID_JOINREQUEST_LEN);
1400             netdev_info(wlandev->netdev,
1401                     "linkstatus=ASSOCFAIL (re-submitting join)\n");
1402         } else {
1403             netdev_info(wlandev->netdev, "linkstatus=ASSOCFAIL (unhandled)\n");
1404         }
1405 
1406         netif_carrier_off(wlandev->netdev);
1407 
1408         /* signal back up to cfg80211 layer */
1409         prism2_connect_result(wlandev, P80211ENUM_truth_true);
1410 
1411         break;
1412 
1413     default:
1414         /* This is bad, IO port problems? */
1415         netdev_warn(wlandev->netdev,
1416                 "unknown linkstatus=0x%02x\n", hw->link_status);
1417         return;
1418     }
1419 
1420     wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED);
1421 }
1422 
1423 /*
1424  * prism2sta_inf_linkstatus
1425  *
1426  * Handles the receipt of a Link Status info frame.
1427  *
1428  * Arguments:
1429  *  wlandev     wlan device structure
1430  *  inf     ptr to info frame (contents in hfa384x order)
1431  *
1432  * Returns:
1433  *  nothing
1434  *
1435  * Side effects:
1436  *
1437  * Call context:
1438  *  interrupt
1439  */
1440 static void prism2sta_inf_linkstatus(struct wlandevice *wlandev,
1441                      struct hfa384x_inf_frame *inf)
1442 {
1443     struct hfa384x *hw = wlandev->priv;
1444 
1445     hw->link_status_new = le16_to_cpu(inf->info.linkstatus.linkstatus);
1446 
1447     schedule_work(&hw->link_bh);
1448 }
1449 
1450 /*
1451  * prism2sta_inf_assocstatus
1452  *
1453  * Handles the receipt of an Association Status info frame. Should
1454  * be present in APs only.
1455  *
1456  * Arguments:
1457  *  wlandev     wlan device structure
1458  *  inf     ptr to info frame (contents in hfa384x order)
1459  *
1460  * Returns:
1461  *  nothing
1462  *
1463  * Side effects:
1464  *
1465  * Call context:
1466  *  interrupt
1467  */
1468 static void prism2sta_inf_assocstatus(struct wlandevice *wlandev,
1469                       struct hfa384x_inf_frame *inf)
1470 {
1471     struct hfa384x *hw = wlandev->priv;
1472     struct hfa384x_assoc_status rec;
1473     int i;
1474 
1475     memcpy(&rec, &inf->info.assocstatus, sizeof(rec));
1476     le16_to_cpus(&rec.assocstatus);
1477     le16_to_cpus(&rec.reason);
1478 
1479     /*
1480      * Find the address in the list of authenticated stations.
1481      * If it wasn't found, then this address has not been previously
1482      * authenticated and something weird has happened if this is
1483      * anything other than an "authentication failed" message.
1484      * If the address was found, then set the "associated" flag for
1485      * that station, based on whether the station is associating or
1486      * losing its association.  Something weird has also happened
1487      * if we find the address in the list of authenticated stations
1488      * but we are getting an "authentication failed" message.
1489      */
1490 
1491     for (i = 0; i < hw->authlist.cnt; i++)
1492         if (ether_addr_equal(rec.sta_addr, hw->authlist.addr[i]))
1493             break;
1494 
1495     if (i >= hw->authlist.cnt) {
1496         if (rec.assocstatus != HFA384x_ASSOCSTATUS_AUTHFAIL)
1497             netdev_warn(wlandev->netdev,
1498                     "assocstatus info frame received for non-authenticated station.\n");
1499     } else {
1500         hw->authlist.assoc[i] =
1501             (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC ||
1502              rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC);
1503 
1504         if (rec.assocstatus == HFA384x_ASSOCSTATUS_AUTHFAIL)
1505             netdev_warn(wlandev->netdev,
1506                     "authfail assocstatus info frame received for authenticated station.\n");
1507     }
1508 }
1509 
1510 /*
1511  * prism2sta_inf_authreq
1512  *
1513  * Handles the receipt of an Authentication Request info frame. Should
1514  * be present in APs only.
1515  *
1516  * Arguments:
1517  *  wlandev     wlan device structure
1518  *  inf     ptr to info frame (contents in hfa384x order)
1519  *
1520  * Returns:
1521  *  nothing
1522  *
1523  * Side effects:
1524  *
1525  * Call context:
1526  *  interrupt
1527  *
1528  */
1529 static void prism2sta_inf_authreq(struct wlandevice *wlandev,
1530                   struct hfa384x_inf_frame *inf)
1531 {
1532     struct hfa384x *hw = wlandev->priv;
1533     struct sk_buff *skb;
1534 
1535     skb = dev_alloc_skb(sizeof(*inf));
1536     if (skb) {
1537         skb_put(skb, sizeof(*inf));
1538         memcpy(skb->data, inf, sizeof(*inf));
1539         skb_queue_tail(&hw->authq, skb);
1540         schedule_work(&hw->link_bh);
1541     }
1542 }
1543 
1544 static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev,
1545                     struct hfa384x_inf_frame *inf)
1546 {
1547     struct hfa384x *hw = wlandev->priv;
1548     struct hfa384x_authenticate_station_data rec;
1549 
1550     int i, added, result, cnt;
1551     u8 *addr;
1552 
1553     /*
1554      * Build the AuthenticateStation record.  Initialize it for denying
1555      * authentication.
1556      */
1557 
1558     ether_addr_copy(rec.address, inf->info.authreq.sta_addr);
1559     rec.status = cpu_to_le16(P80211ENUM_status_unspec_failure);
1560 
1561     /*
1562      * Authenticate based on the access mode.
1563      */
1564 
1565     switch (hw->accessmode) {
1566     case WLAN_ACCESS_NONE:
1567 
1568         /*
1569          * Deny all new authentications.  However, if a station
1570          * is ALREADY authenticated, then accept it.
1571          */
1572 
1573         for (i = 0; i < hw->authlist.cnt; i++)
1574             if (ether_addr_equal(rec.address,
1575                          hw->authlist.addr[i])) {
1576                 rec.status = cpu_to_le16(P80211ENUM_status_successful);
1577                 break;
1578             }
1579 
1580         break;
1581 
1582     case WLAN_ACCESS_ALL:
1583 
1584         /*
1585          * Allow all authentications.
1586          */
1587 
1588         rec.status = cpu_to_le16(P80211ENUM_status_successful);
1589         break;
1590 
1591     case WLAN_ACCESS_ALLOW:
1592 
1593         /*
1594          * Only allow the authentication if the MAC address
1595          * is in the list of allowed addresses.
1596          *
1597          * Since this is the interrupt handler, we may be here
1598          * while the access list is in the middle of being
1599          * updated.  Choose the list which is currently okay.
1600          * See "prism2mib_priv_accessallow()" for details.
1601          */
1602 
1603         if (hw->allow.modify == 0) {
1604             cnt = hw->allow.cnt;
1605             addr = hw->allow.addr[0];
1606         } else {
1607             cnt = hw->allow.cnt1;
1608             addr = hw->allow.addr1[0];
1609         }
1610 
1611         for (i = 0; i < cnt; i++, addr += ETH_ALEN)
1612             if (ether_addr_equal(rec.address, addr)) {
1613                 rec.status = cpu_to_le16(P80211ENUM_status_successful);
1614                 break;
1615             }
1616 
1617         break;
1618 
1619     case WLAN_ACCESS_DENY:
1620 
1621         /*
1622          * Allow the authentication UNLESS the MAC address is
1623          * in the list of denied addresses.
1624          *
1625          * Since this is the interrupt handler, we may be here
1626          * while the access list is in the middle of being
1627          * updated.  Choose the list which is currently okay.
1628          * See "prism2mib_priv_accessdeny()" for details.
1629          */
1630 
1631         if (hw->deny.modify == 0) {
1632             cnt = hw->deny.cnt;
1633             addr = hw->deny.addr[0];
1634         } else {
1635             cnt = hw->deny.cnt1;
1636             addr = hw->deny.addr1[0];
1637         }
1638 
1639         rec.status = cpu_to_le16(P80211ENUM_status_successful);
1640 
1641         for (i = 0; i < cnt; i++, addr += ETH_ALEN)
1642             if (ether_addr_equal(rec.address, addr)) {
1643                 rec.status = cpu_to_le16(P80211ENUM_status_unspec_failure);
1644                 break;
1645             }
1646 
1647         break;
1648     }
1649 
1650     /*
1651      * If the authentication is okay, then add the MAC address to the
1652      * list of authenticated stations.  Don't add the address if it
1653      * is already in the list. (802.11b does not seem to disallow
1654      * a station from issuing an authentication request when the
1655      * station is already authenticated. Does this sort of thing
1656      * ever happen?  We might as well do the check just in case.)
1657      */
1658 
1659     added = 0;
1660 
1661     if (rec.status == cpu_to_le16(P80211ENUM_status_successful)) {
1662         for (i = 0; i < hw->authlist.cnt; i++)
1663             if (ether_addr_equal(rec.address,
1664                          hw->authlist.addr[i]))
1665                 break;
1666 
1667         if (i >= hw->authlist.cnt) {
1668             if (hw->authlist.cnt >= WLAN_AUTH_MAX) {
1669                 rec.status = cpu_to_le16(P80211ENUM_status_ap_full);
1670             } else {
1671                 ether_addr_copy(hw->authlist.addr[hw->authlist.cnt],
1672                         rec.address);
1673                 hw->authlist.cnt++;
1674                 added = 1;
1675             }
1676         }
1677     }
1678 
1679     /*
1680      * Send back the results of the authentication.  If this doesn't work,
1681      * then make sure to remove the address from the authenticated list if
1682      * it was added.
1683      */
1684 
1685     rec.algorithm = inf->info.authreq.algorithm;
1686 
1687     result = hfa384x_drvr_setconfig(hw, HFA384x_RID_AUTHENTICATESTA,
1688                     &rec, sizeof(rec));
1689     if (result) {
1690         if (added)
1691             hw->authlist.cnt--;
1692         netdev_err(wlandev->netdev,
1693                "setconfig(authenticatestation) failed, result=%d\n",
1694                result);
1695     }
1696 }
1697 
1698 /*
1699  * prism2sta_inf_psusercnt
1700  *
1701  * Handles the receipt of a PowerSaveUserCount info frame. Should
1702  * be present in APs only.
1703  *
1704  * Arguments:
1705  *  wlandev     wlan device structure
1706  *  inf     ptr to info frame (contents in hfa384x order)
1707  *
1708  * Returns:
1709  *  nothing
1710  *
1711  * Side effects:
1712  *
1713  * Call context:
1714  *  interrupt
1715  */
1716 static void prism2sta_inf_psusercnt(struct wlandevice *wlandev,
1717                     struct hfa384x_inf_frame *inf)
1718 {
1719     struct hfa384x *hw = wlandev->priv;
1720 
1721     hw->psusercount = le16_to_cpu(inf->info.psusercnt.usercnt);
1722 }
1723 
1724 /*
1725  * prism2sta_ev_info
1726  *
1727  * Handles the Info event.
1728  *
1729  * Arguments:
1730  *  wlandev     wlan device structure
1731  *  inf     ptr to a generic info frame
1732  *
1733  * Returns:
1734  *  nothing
1735  *
1736  * Side effects:
1737  *
1738  * Call context:
1739  *  interrupt
1740  */
1741 void prism2sta_ev_info(struct wlandevice *wlandev,
1742                struct hfa384x_inf_frame *inf)
1743 {
1744     le16_to_cpus(&inf->infotype);
1745     /* Dispatch */
1746     switch (inf->infotype) {
1747     case HFA384x_IT_HANDOVERADDR:
1748         prism2sta_inf_handover(wlandev, inf);
1749         break;
1750     case HFA384x_IT_COMMTALLIES:
1751         prism2sta_inf_tallies(wlandev, inf);
1752         break;
1753     case HFA384x_IT_HOSTSCANRESULTS:
1754         prism2sta_inf_hostscanresults(wlandev, inf);
1755         break;
1756     case HFA384x_IT_SCANRESULTS:
1757         prism2sta_inf_scanresults(wlandev, inf);
1758         break;
1759     case HFA384x_IT_CHINFORESULTS:
1760         prism2sta_inf_chinforesults(wlandev, inf);
1761         break;
1762     case HFA384x_IT_LINKSTATUS:
1763         prism2sta_inf_linkstatus(wlandev, inf);
1764         break;
1765     case HFA384x_IT_ASSOCSTATUS:
1766         prism2sta_inf_assocstatus(wlandev, inf);
1767         break;
1768     case HFA384x_IT_AUTHREQ:
1769         prism2sta_inf_authreq(wlandev, inf);
1770         break;
1771     case HFA384x_IT_PSUSERCNT:
1772         prism2sta_inf_psusercnt(wlandev, inf);
1773         break;
1774     case HFA384x_IT_KEYIDCHANGED:
1775         netdev_warn(wlandev->netdev, "Unhandled IT_KEYIDCHANGED\n");
1776         break;
1777     case HFA384x_IT_ASSOCREQ:
1778         netdev_warn(wlandev->netdev, "Unhandled IT_ASSOCREQ\n");
1779         break;
1780     case HFA384x_IT_MICFAILURE:
1781         netdev_warn(wlandev->netdev, "Unhandled IT_MICFAILURE\n");
1782         break;
1783     default:
1784         netdev_warn(wlandev->netdev,
1785                 "Unknown info type=0x%02x\n", inf->infotype);
1786         break;
1787     }
1788 }
1789 
1790 /*
1791  * prism2sta_ev_txexc
1792  *
1793  * Handles the TxExc event.  A Transmit Exception event indicates
1794  * that the MAC's TX process was unsuccessful - so the packet did
1795  * not get transmitted.
1796  *
1797  * Arguments:
1798  *  wlandev     wlan device structure
1799  *  status      tx frame status word
1800  *
1801  * Returns:
1802  *  nothing
1803  *
1804  * Side effects:
1805  *
1806  * Call context:
1807  *  interrupt
1808  */
1809 void prism2sta_ev_txexc(struct wlandevice *wlandev, u16 status)
1810 {
1811     pr_debug("TxExc status=0x%x.\n", status);
1812 }
1813 
1814 /*
1815  * prism2sta_ev_tx
1816  *
1817  * Handles the Tx event.
1818  *
1819  * Arguments:
1820  *  wlandev     wlan device structure
1821  *  status      tx frame status word
1822  * Returns:
1823  *  nothing
1824  *
1825  * Side effects:
1826  *
1827  * Call context:
1828  *  interrupt
1829  */
1830 void prism2sta_ev_tx(struct wlandevice *wlandev, u16 status)
1831 {
1832     pr_debug("Tx Complete, status=0x%04x\n", status);
1833     /* update linux network stats */
1834     wlandev->netdev->stats.tx_packets++;
1835 }
1836 
1837 /*
1838  * prism2sta_ev_alloc
1839  *
1840  * Handles the Alloc event.
1841  *
1842  * Arguments:
1843  *  wlandev     wlan device structure
1844  *
1845  * Returns:
1846  *  nothing
1847  *
1848  * Side effects:
1849  *
1850  * Call context:
1851  *  interrupt
1852  */
1853 void prism2sta_ev_alloc(struct wlandevice *wlandev)
1854 {
1855     netif_wake_queue(wlandev->netdev);
1856 }
1857 
1858 /*
1859  * create_wlan
1860  *
1861  * Called at module init time.  This creates the struct wlandevice structure
1862  * and initializes it with relevant bits.
1863  *
1864  * Arguments:
1865  *  none
1866  *
1867  * Returns:
1868  *  the created struct wlandevice structure.
1869  *
1870  * Side effects:
1871  *  also allocates the priv/hw structures.
1872  *
1873  * Call context:
1874  *  process thread
1875  *
1876  */
1877 static struct wlandevice *create_wlan(void)
1878 {
1879     struct wlandevice *wlandev = NULL;
1880     struct hfa384x *hw = NULL;
1881 
1882     /* Alloc our structures */
1883     wlandev = kzalloc(sizeof(*wlandev), GFP_KERNEL);
1884     hw = kzalloc(sizeof(*hw), GFP_KERNEL);
1885 
1886     if (!wlandev || !hw) {
1887         kfree(wlandev);
1888         kfree(hw);
1889         return NULL;
1890     }
1891 
1892     /* Initialize the network device object. */
1893     wlandev->nsdname = dev_info;
1894     wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
1895     wlandev->priv = hw;
1896     wlandev->open = prism2sta_open;
1897     wlandev->close = prism2sta_close;
1898     wlandev->reset = prism2sta_reset;
1899     wlandev->txframe = prism2sta_txframe;
1900     wlandev->mlmerequest = prism2sta_mlmerequest;
1901     wlandev->set_multicast_list = prism2sta_setmulticast;
1902     wlandev->tx_timeout = hfa384x_tx_timeout;
1903 
1904     wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT | P80211_NSDCAP_AUTOJOIN;
1905 
1906     /* Initialize the device private data structure. */
1907     hw->dot11_desired_bss_type = 1;
1908 
1909     return wlandev;
1910 }
1911 
1912 void prism2sta_commsqual_defer(struct work_struct *data)
1913 {
1914     struct hfa384x *hw = container_of(data, struct hfa384x, commsqual_bh);
1915     struct wlandevice *wlandev = hw->wlandev;
1916     struct hfa384x_bytestr32 ssid;
1917     struct p80211msg_dot11req_mibget msg;
1918     struct p80211item_uint32 *mibitem = (struct p80211item_uint32 *)
1919                         &msg.mibattribute.data;
1920     int result = 0;
1921 
1922     if (hw->wlandev->hwremoved)
1923         return;
1924 
1925     /* we don't care if we're in AP mode */
1926     if ((wlandev->macmode == WLAN_MACMODE_NONE) ||
1927         (wlandev->macmode == WLAN_MACMODE_ESS_AP)) {
1928         return;
1929     }
1930 
1931     /* It only makes sense to poll these in non-IBSS */
1932     if (wlandev->macmode != WLAN_MACMODE_IBSS_STA) {
1933         result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DBMCOMMSQUALITY,
1934                         &hw->qual, HFA384x_RID_DBMCOMMSQUALITY_LEN);
1935 
1936         if (result) {
1937             netdev_err(wlandev->netdev, "error fetching commsqual\n");
1938             return;
1939         }
1940 
1941         pr_debug("commsqual %d %d %d\n",
1942              le16_to_cpu(hw->qual.cq_curr_bss),
1943              le16_to_cpu(hw->qual.asl_curr_bss),
1944              le16_to_cpu(hw->qual.anl_curr_fc));
1945     }
1946 
1947     /* Get the signal rate */
1948     msg.msgcode = DIDMSG_DOT11REQ_MIBGET;
1949     mibitem->did = DIDMIB_P2_MAC_CURRENTTXRATE;
1950     result = p80211req_dorequest(wlandev, (u8 *)&msg);
1951 
1952     if (result) {
1953         pr_debug("get signal rate failed, result = %d\n",
1954              result);
1955         return;
1956     }
1957 
1958     switch (mibitem->data) {
1959     case HFA384x_RATEBIT_1:
1960         hw->txrate = 10;
1961         break;
1962     case HFA384x_RATEBIT_2:
1963         hw->txrate = 20;
1964         break;
1965     case HFA384x_RATEBIT_5dot5:
1966         hw->txrate = 55;
1967         break;
1968     case HFA384x_RATEBIT_11:
1969         hw->txrate = 110;
1970         break;
1971     default:
1972         pr_debug("Bad ratebit (%d)\n", mibitem->data);
1973     }
1974 
1975     /* Lastly, we need to make sure the BSSID didn't change on us */
1976     result = hfa384x_drvr_getconfig(hw,
1977                     HFA384x_RID_CURRENTBSSID,
1978                     wlandev->bssid, WLAN_BSSID_LEN);
1979     if (result) {
1980         pr_debug("getconfig(0x%02x) failed, result = %d\n",
1981              HFA384x_RID_CURRENTBSSID, result);
1982         return;
1983     }
1984 
1985     result = hfa384x_drvr_getconfig(hw,
1986                     HFA384x_RID_CURRENTSSID,
1987                     &ssid, sizeof(ssid));
1988     if (result) {
1989         pr_debug("getconfig(0x%02x) failed, result = %d\n",
1990              HFA384x_RID_CURRENTSSID, result);
1991         return;
1992     }
1993     prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid,
1994                 (struct p80211pstrd *)&wlandev->ssid);
1995 
1996     /* Reschedule timer */
1997     mod_timer(&hw->commsqual_timer, jiffies + HZ);
1998 }
1999 
2000 void prism2sta_commsqual_timer(struct timer_list *t)
2001 {
2002     struct hfa384x *hw = from_timer(hw, t, commsqual_timer);
2003 
2004     schedule_work(&hw->commsqual_bh);
2005 }