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