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