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