Linux Audio

Check our new training course

Linux kernel drivers training

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