Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[linux-2.6-microblaze.git] / drivers / staging / wlan-ng / prism2sta.c
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
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 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 }