prism2sta.c (54561B)
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 * 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 struct 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 struct 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->frame_control |= 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 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 u8 addr[ETH_ALEN]; 589 590 /* Collect version and compatibility info */ 591 /* Some are critical, some are not */ 592 /* NIC identity */ 593 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY, 594 &hw->ident_nic, 595 sizeof(struct hfa384x_compident)); 596 if (result) { 597 netdev_err(wlandev->netdev, "Failed to retrieve NICIDENTITY\n"); 598 goto failed; 599 } 600 601 /* get all the nic id fields in host byte order */ 602 le16_to_cpus(&hw->ident_nic.id); 603 le16_to_cpus(&hw->ident_nic.variant); 604 le16_to_cpus(&hw->ident_nic.major); 605 le16_to_cpus(&hw->ident_nic.minor); 606 607 netdev_info(wlandev->netdev, "ident: nic h/w: id=0x%02x %d.%d.%d\n", 608 hw->ident_nic.id, hw->ident_nic.major, 609 hw->ident_nic.minor, hw->ident_nic.variant); 610 611 /* Primary f/w identity */ 612 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY, 613 &hw->ident_pri_fw, 614 sizeof(struct hfa384x_compident)); 615 if (result) { 616 netdev_err(wlandev->netdev, "Failed to retrieve PRIIDENTITY\n"); 617 goto failed; 618 } 619 620 /* get all the private fw id fields in host byte order */ 621 le16_to_cpus(&hw->ident_pri_fw.id); 622 le16_to_cpus(&hw->ident_pri_fw.variant); 623 le16_to_cpus(&hw->ident_pri_fw.major); 624 le16_to_cpus(&hw->ident_pri_fw.minor); 625 626 netdev_info(wlandev->netdev, "ident: pri f/w: id=0x%02x %d.%d.%d\n", 627 hw->ident_pri_fw.id, hw->ident_pri_fw.major, 628 hw->ident_pri_fw.minor, hw->ident_pri_fw.variant); 629 630 /* Station (Secondary?) f/w identity */ 631 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY, 632 &hw->ident_sta_fw, 633 sizeof(struct hfa384x_compident)); 634 if (result) { 635 netdev_err(wlandev->netdev, "Failed to retrieve STAIDENTITY\n"); 636 goto failed; 637 } 638 639 if (hw->ident_nic.id < 0x8000) { 640 netdev_err(wlandev->netdev, 641 "FATAL: Card is not an Intersil Prism2/2.5/3\n"); 642 result = -1; 643 goto failed; 644 } 645 646 /* get all the station fw id fields in host byte order */ 647 le16_to_cpus(&hw->ident_sta_fw.id); 648 le16_to_cpus(&hw->ident_sta_fw.variant); 649 le16_to_cpus(&hw->ident_sta_fw.major); 650 le16_to_cpus(&hw->ident_sta_fw.minor); 651 652 /* strip out the 'special' variant bits */ 653 hw->mm_mods = hw->ident_sta_fw.variant & GENMASK(15, 14); 654 hw->ident_sta_fw.variant &= ~((u16)GENMASK(15, 14)); 655 656 if (hw->ident_sta_fw.id == 0x1f) { 657 netdev_info(wlandev->netdev, 658 "ident: sta f/w: id=0x%02x %d.%d.%d\n", 659 hw->ident_sta_fw.id, hw->ident_sta_fw.major, 660 hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); 661 } else { 662 netdev_info(wlandev->netdev, 663 "ident: ap f/w: id=0x%02x %d.%d.%d\n", 664 hw->ident_sta_fw.id, hw->ident_sta_fw.major, 665 hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); 666 netdev_err(wlandev->netdev, "Unsupported Tertiary AP firmware loaded!\n"); 667 goto failed; 668 } 669 670 /* Compatibility range, Modem supplier */ 671 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE, 672 &hw->cap_sup_mfi, 673 sizeof(struct hfa384x_caplevel)); 674 if (result) { 675 netdev_err(wlandev->netdev, "Failed to retrieve MFISUPRANGE\n"); 676 goto failed; 677 } 678 679 /* get all the Compatibility range, modem interface supplier 680 * fields in byte order 681 */ 682 le16_to_cpus(&hw->cap_sup_mfi.role); 683 le16_to_cpus(&hw->cap_sup_mfi.id); 684 le16_to_cpus(&hw->cap_sup_mfi.variant); 685 le16_to_cpus(&hw->cap_sup_mfi.bottom); 686 le16_to_cpus(&hw->cap_sup_mfi.top); 687 688 netdev_info(wlandev->netdev, 689 "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", 690 hw->cap_sup_mfi.role, hw->cap_sup_mfi.id, 691 hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom, 692 hw->cap_sup_mfi.top); 693 694 /* Compatibility range, Controller supplier */ 695 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE, 696 &hw->cap_sup_cfi, 697 sizeof(struct hfa384x_caplevel)); 698 if (result) { 699 netdev_err(wlandev->netdev, "Failed to retrieve CFISUPRANGE\n"); 700 goto failed; 701 } 702 703 /* get all the Compatibility range, controller interface supplier 704 * fields in byte order 705 */ 706 le16_to_cpus(&hw->cap_sup_cfi.role); 707 le16_to_cpus(&hw->cap_sup_cfi.id); 708 le16_to_cpus(&hw->cap_sup_cfi.variant); 709 le16_to_cpus(&hw->cap_sup_cfi.bottom); 710 le16_to_cpus(&hw->cap_sup_cfi.top); 711 712 netdev_info(wlandev->netdev, 713 "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", 714 hw->cap_sup_cfi.role, hw->cap_sup_cfi.id, 715 hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom, 716 hw->cap_sup_cfi.top); 717 718 /* Compatibility range, Primary f/w supplier */ 719 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE, 720 &hw->cap_sup_pri, 721 sizeof(struct hfa384x_caplevel)); 722 if (result) { 723 netdev_err(wlandev->netdev, "Failed to retrieve PRISUPRANGE\n"); 724 goto failed; 725 } 726 727 /* get all the Compatibility range, primary firmware supplier 728 * fields in byte order 729 */ 730 le16_to_cpus(&hw->cap_sup_pri.role); 731 le16_to_cpus(&hw->cap_sup_pri.id); 732 le16_to_cpus(&hw->cap_sup_pri.variant); 733 le16_to_cpus(&hw->cap_sup_pri.bottom); 734 le16_to_cpus(&hw->cap_sup_pri.top); 735 736 netdev_info(wlandev->netdev, 737 "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", 738 hw->cap_sup_pri.role, hw->cap_sup_pri.id, 739 hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom, 740 hw->cap_sup_pri.top); 741 742 /* Compatibility range, Station f/w supplier */ 743 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE, 744 &hw->cap_sup_sta, 745 sizeof(struct hfa384x_caplevel)); 746 if (result) { 747 netdev_err(wlandev->netdev, "Failed to retrieve STASUPRANGE\n"); 748 goto failed; 749 } 750 751 /* get all the Compatibility range, station firmware supplier 752 * fields in byte order 753 */ 754 le16_to_cpus(&hw->cap_sup_sta.role); 755 le16_to_cpus(&hw->cap_sup_sta.id); 756 le16_to_cpus(&hw->cap_sup_sta.variant); 757 le16_to_cpus(&hw->cap_sup_sta.bottom); 758 le16_to_cpus(&hw->cap_sup_sta.top); 759 760 if (hw->cap_sup_sta.id == 0x04) { 761 netdev_info(wlandev->netdev, 762 "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", 763 hw->cap_sup_sta.role, hw->cap_sup_sta.id, 764 hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, 765 hw->cap_sup_sta.top); 766 } else { 767 netdev_info(wlandev->netdev, 768 "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", 769 hw->cap_sup_sta.role, hw->cap_sup_sta.id, 770 hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, 771 hw->cap_sup_sta.top); 772 } 773 774 /* Compatibility range, primary f/w actor, CFI supplier */ 775 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES, 776 &hw->cap_act_pri_cfi, 777 sizeof(struct hfa384x_caplevel)); 778 if (result) { 779 netdev_err(wlandev->netdev, "Failed to retrieve PRI_CFIACTRANGES\n"); 780 goto failed; 781 } 782 783 /* get all the Compatibility range, primary f/w actor, CFI supplier 784 * fields in byte order 785 */ 786 le16_to_cpus(&hw->cap_act_pri_cfi.role); 787 le16_to_cpus(&hw->cap_act_pri_cfi.id); 788 le16_to_cpus(&hw->cap_act_pri_cfi.variant); 789 le16_to_cpus(&hw->cap_act_pri_cfi.bottom); 790 le16_to_cpus(&hw->cap_act_pri_cfi.top); 791 792 netdev_info(wlandev->netdev, 793 "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", 794 hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id, 795 hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom, 796 hw->cap_act_pri_cfi.top); 797 798 /* Compatibility range, sta f/w actor, CFI supplier */ 799 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES, 800 &hw->cap_act_sta_cfi, 801 sizeof(struct hfa384x_caplevel)); 802 if (result) { 803 netdev_err(wlandev->netdev, "Failed to retrieve STA_CFIACTRANGES\n"); 804 goto failed; 805 } 806 807 /* get all the Compatibility range, station f/w actor, CFI supplier 808 * fields in byte order 809 */ 810 le16_to_cpus(&hw->cap_act_sta_cfi.role); 811 le16_to_cpus(&hw->cap_act_sta_cfi.id); 812 le16_to_cpus(&hw->cap_act_sta_cfi.variant); 813 le16_to_cpus(&hw->cap_act_sta_cfi.bottom); 814 le16_to_cpus(&hw->cap_act_sta_cfi.top); 815 816 netdev_info(wlandev->netdev, 817 "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", 818 hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id, 819 hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom, 820 hw->cap_act_sta_cfi.top); 821 822 /* Compatibility range, sta f/w actor, MFI supplier */ 823 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES, 824 &hw->cap_act_sta_mfi, 825 sizeof(struct hfa384x_caplevel)); 826 if (result) { 827 netdev_err(wlandev->netdev, "Failed to retrieve STA_MFIACTRANGES\n"); 828 goto failed; 829 } 830 831 /* get all the Compatibility range, station f/w actor, MFI supplier 832 * fields in byte order 833 */ 834 le16_to_cpus(&hw->cap_act_sta_mfi.role); 835 le16_to_cpus(&hw->cap_act_sta_mfi.id); 836 le16_to_cpus(&hw->cap_act_sta_mfi.variant); 837 le16_to_cpus(&hw->cap_act_sta_mfi.bottom); 838 le16_to_cpus(&hw->cap_act_sta_mfi.top); 839 840 netdev_info(wlandev->netdev, 841 "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", 842 hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id, 843 hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom, 844 hw->cap_act_sta_mfi.top); 845 846 /* Serial Number */ 847 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, 848 snum, HFA384x_RID_NICSERIALNUMBER_LEN); 849 if (!result) { 850 netdev_info(wlandev->netdev, "Prism2 card SN: %*pE\n", 851 HFA384x_RID_NICSERIALNUMBER_LEN, snum); 852 } else { 853 netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n"); 854 goto failed; 855 } 856 857 /* Collect the MAC address */ 858 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNMACADDR, 859 addr, ETH_ALEN); 860 if (result != 0) { 861 netdev_err(wlandev->netdev, "Failed to retrieve mac address\n"); 862 goto failed; 863 } 864 eth_hw_addr_set(wlandev->netdev, addr); 865 866 /* short preamble is always implemented */ 867 wlandev->nsdcaps |= P80211_NSDCAP_SHORT_PREAMBLE; 868 869 /* find out if hardware wep is implemented */ 870 hfa384x_drvr_getconfig16(hw, HFA384x_RID_PRIVACYOPTIMP, &temp); 871 if (temp) 872 wlandev->nsdcaps |= P80211_NSDCAP_HARDWAREWEP; 873 874 /* get the dBm Scaling constant */ 875 hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFDBMADJUST, &temp); 876 hw->dbmadjust = temp; 877 878 /* Only enable scan by default on newer firmware */ 879 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, 880 hw->ident_sta_fw.minor, 881 hw->ident_sta_fw.variant) < 882 HFA384x_FIRMWARE_VERSION(1, 5, 5)) { 883 wlandev->nsdcaps |= P80211_NSDCAP_NOSCAN; 884 } 885 886 /* TODO: Set any internally managed config items */ 887 888 goto done; 889failed: 890 netdev_err(wlandev->netdev, "Failed, result=%d\n", result); 891done: 892 return result; 893} 894 895/* 896 * prism2sta_globalsetup 897 * 898 * Set any global RIDs that we want to set at device activation. 899 * 900 * Arguments: 901 * wlandev wlan device structure 902 * 903 * Returns: 904 * 0 success 905 * >0 f/w reported error 906 * <0 driver reported error 907 * 908 * Side effects: 909 * 910 * Call context: 911 * process thread 912 */ 913static int prism2sta_globalsetup(struct wlandevice *wlandev) 914{ 915 struct hfa384x *hw = wlandev->priv; 916 917 /* Set the maximum frame size */ 918 return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 919 WLAN_DATA_MAXLEN); 920} 921 922static int prism2sta_setmulticast(struct wlandevice *wlandev, 923 struct net_device *dev) 924{ 925 int result = 0; 926 struct hfa384x *hw = wlandev->priv; 927 928 u16 promisc; 929 930 /* If we're not ready, what's the point? */ 931 if (hw->state != HFA384x_STATE_RUNNING) 932 goto exit; 933 934 if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) 935 promisc = P80211ENUM_truth_true; 936 else 937 promisc = P80211ENUM_truth_false; 938 939 result = 940 hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE, 941 promisc); 942exit: 943 return result; 944} 945 946/* 947 * prism2sta_inf_handover 948 * 949 * Handles the receipt of a Handover info frame. Should only be present 950 * in APs only. 951 * 952 * Arguments: 953 * wlandev wlan device structure 954 * inf ptr to info frame (contents in hfa384x order) 955 * 956 * Returns: 957 * nothing 958 * 959 * Side effects: 960 * 961 * Call context: 962 * interrupt 963 */ 964static void prism2sta_inf_handover(struct wlandevice *wlandev, 965 struct hfa384x_inf_frame *inf) 966{ 967 pr_debug("received infoframe:HANDOVER (unhandled)\n"); 968} 969 970/* 971 * prism2sta_inf_tallies 972 * 973 * Handles the receipt of a CommTallies info frame. 974 * 975 * Arguments: 976 * wlandev wlan device structure 977 * inf ptr to info frame (contents in hfa384x order) 978 * 979 * Returns: 980 * nothing 981 * 982 * Side effects: 983 * 984 * Call context: 985 * interrupt 986 */ 987static void prism2sta_inf_tallies(struct wlandevice *wlandev, 988 struct hfa384x_inf_frame *inf) 989{ 990 struct hfa384x *hw = wlandev->priv; 991 __le16 *src16; 992 u32 *dst; 993 __le32 *src32; 994 int i; 995 int cnt; 996 997 /* 998 * Determine if these are 16-bit or 32-bit tallies, based on the 999 * record length of the info record. 1000 */ 1001 1002 cnt = sizeof(struct hfa384x_comm_tallies_32) / sizeof(u32); 1003 if (inf->framelen > 22) { 1004 dst = (u32 *)&hw->tallies; 1005 src32 = (__le32 *)&inf->info.commtallies32; 1006 for (i = 0; i < cnt; i++, dst++, src32++) 1007 *dst += le32_to_cpu(*src32); 1008 } else { 1009 dst = (u32 *)&hw->tallies; 1010 src16 = (__le16 *)&inf->info.commtallies16; 1011 for (i = 0; i < cnt; i++, dst++, src16++) 1012 *dst += le16_to_cpu(*src16); 1013 } 1014} 1015 1016/* 1017 * prism2sta_inf_scanresults 1018 * 1019 * Handles the receipt of a Scan Results info frame. 1020 * 1021 * Arguments: 1022 * wlandev wlan device structure 1023 * inf ptr to info frame (contents in hfa384x order) 1024 * 1025 * Returns: 1026 * nothing 1027 * 1028 * Side effects: 1029 * 1030 * Call context: 1031 * interrupt 1032 */ 1033static void prism2sta_inf_scanresults(struct wlandevice *wlandev, 1034 struct hfa384x_inf_frame *inf) 1035{ 1036 struct hfa384x *hw = wlandev->priv; 1037 int nbss; 1038 struct hfa384x_scan_result *sr = &inf->info.scanresult; 1039 int i; 1040 struct hfa384x_join_request_data joinreq; 1041 int result; 1042 1043 /* Get the number of results, first in bytes, then in results */ 1044 nbss = (inf->framelen * sizeof(u16)) - 1045 sizeof(inf->infotype) - sizeof(inf->info.scanresult.scanreason); 1046 nbss /= sizeof(struct hfa384x_scan_result_sub); 1047 1048 /* Print em */ 1049 pr_debug("rx scanresults, reason=%d, nbss=%d:\n", 1050 inf->info.scanresult.scanreason, nbss); 1051 for (i = 0; i < nbss; i++) { 1052 pr_debug("chid=%d anl=%d sl=%d bcnint=%d\n", 1053 sr->result[i].chid, 1054 sr->result[i].anl, 1055 sr->result[i].sl, sr->result[i].bcnint); 1056 pr_debug(" capinfo=0x%04x proberesp_rate=%d\n", 1057 sr->result[i].capinfo, sr->result[i].proberesp_rate); 1058 } 1059 /* issue a join request */ 1060 joinreq.channel = sr->result[0].chid; 1061 memcpy(joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN); 1062 result = hfa384x_drvr_setconfig(hw, 1063 HFA384x_RID_JOINREQUEST, 1064 &joinreq, HFA384x_RID_JOINREQUEST_LEN); 1065 if (result) { 1066 netdev_err(wlandev->netdev, "setconfig(joinreq) failed, result=%d\n", 1067 result); 1068 } 1069} 1070 1071/* 1072 * prism2sta_inf_hostscanresults 1073 * 1074 * Handles the receipt of a Scan Results info frame. 1075 * 1076 * Arguments: 1077 * wlandev wlan device structure 1078 * inf ptr to info frame (contents in hfa384x order) 1079 * 1080 * Returns: 1081 * nothing 1082 * 1083 * Side effects: 1084 * 1085 * Call context: 1086 * interrupt 1087 */ 1088static void prism2sta_inf_hostscanresults(struct wlandevice *wlandev, 1089 struct hfa384x_inf_frame *inf) 1090{ 1091 struct hfa384x *hw = wlandev->priv; 1092 int nbss; 1093 1094 nbss = (inf->framelen - 3) / 32; 1095 pr_debug("Received %d hostscan results\n", nbss); 1096 1097 if (nbss > 32) 1098 nbss = 32; 1099 1100 kfree(hw->scanresults); 1101 1102 hw->scanresults = kmemdup(inf, sizeof(*inf), GFP_ATOMIC); 1103 1104 if (nbss == 0) 1105 nbss = -1; 1106 1107 /* Notify/wake the sleeping caller. */ 1108 hw->scanflag = nbss; 1109 wake_up_interruptible(&hw->cmdq); 1110}; 1111 1112/* 1113 * prism2sta_inf_chinforesults 1114 * 1115 * Handles the receipt of a Channel Info Results info frame. 1116 * 1117 * Arguments: 1118 * wlandev wlan device structure 1119 * inf ptr to info frame (contents in hfa384x order) 1120 * 1121 * Returns: 1122 * nothing 1123 * 1124 * Side effects: 1125 * 1126 * Call context: 1127 * interrupt 1128 */ 1129static void prism2sta_inf_chinforesults(struct wlandevice *wlandev, 1130 struct hfa384x_inf_frame *inf) 1131{ 1132 struct hfa384x *hw = wlandev->priv; 1133 unsigned int i, n; 1134 1135 hw->channel_info.results.scanchannels = 1136 inf->info.chinforesult.scanchannels; 1137 1138 for (i = 0, n = 0; i < HFA384x_CHINFORESULT_MAX; i++) { 1139 struct hfa384x_ch_info_result_sub *result; 1140 struct hfa384x_ch_info_result_sub *chinforesult; 1141 int chan; 1142 1143 if (!(hw->channel_info.results.scanchannels & (1 << i))) 1144 continue; 1145 1146 result = &inf->info.chinforesult.result[n]; 1147 chan = result->chid - 1; 1148 1149 if (chan < 0 || chan >= HFA384x_CHINFORESULT_MAX) 1150 continue; 1151 1152 chinforesult = &hw->channel_info.results.result[chan]; 1153 chinforesult->chid = chan; 1154 chinforesult->anl = result->anl; 1155 chinforesult->pnl = result->pnl; 1156 chinforesult->active = result->active; 1157 1158 pr_debug("chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n", 1159 chan + 1, 1160 (chinforesult->active & HFA384x_CHINFORESULT_BSSACTIVE) 1161 ? "signal" : "noise", 1162 chinforesult->anl, chinforesult->pnl, 1163 (chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE) 1164 ? 1 : 0); 1165 n++; 1166 } 1167 atomic_set(&hw->channel_info.done, 2); 1168 1169 hw->channel_info.count = n; 1170} 1171 1172void prism2sta_processing_defer(struct work_struct *data) 1173{ 1174 struct hfa384x *hw = container_of(data, struct hfa384x, link_bh); 1175 struct wlandevice *wlandev = hw->wlandev; 1176 struct hfa384x_bytestr32 ssid; 1177 int result; 1178 1179 /* First let's process the auth frames */ 1180 { 1181 struct sk_buff *skb; 1182 struct hfa384x_inf_frame *inf; 1183 1184 while ((skb = skb_dequeue(&hw->authq))) { 1185 inf = (struct hfa384x_inf_frame *)skb->data; 1186 prism2sta_inf_authreq_defer(wlandev, inf); 1187 } 1188 } 1189 1190 /* Now let's handle the linkstatus stuff */ 1191 if (hw->link_status == hw->link_status_new) 1192 return; 1193 1194 hw->link_status = hw->link_status_new; 1195 1196 switch (hw->link_status) { 1197 case HFA384x_LINK_NOTCONNECTED: 1198 /* I'm currently assuming that this is the initial link 1199 * state. It should only be possible immediately 1200 * following an Enable command. 1201 * Response: 1202 * Block Transmits, Ignore receives of data frames 1203 */ 1204 netif_carrier_off(wlandev->netdev); 1205 1206 netdev_info(wlandev->netdev, "linkstatus=NOTCONNECTED (unhandled)\n"); 1207 break; 1208 1209 case HFA384x_LINK_CONNECTED: 1210 /* This one indicates a successful scan/join/auth/assoc. 1211 * When we have the full MLME complement, this event will 1212 * signify successful completion of both mlme_authenticate 1213 * and mlme_associate. State management will get a little 1214 * ugly here. 1215 * Response: 1216 * Indicate authentication and/or association 1217 * Enable Transmits, Receives and pass up data frames 1218 */ 1219 1220 netif_carrier_on(wlandev->netdev); 1221 1222 /* If we are joining a specific AP, set our 1223 * state and reset retries 1224 */ 1225 if (hw->join_ap == 1) 1226 hw->join_ap = 2; 1227 hw->join_retries = 60; 1228 1229 /* Don't call this in monitor mode */ 1230 if (wlandev->netdev->type == ARPHRD_ETHER) { 1231 u16 portstatus; 1232 1233 netdev_info(wlandev->netdev, "linkstatus=CONNECTED\n"); 1234 1235 /* For non-usb devices, we can use the sync versions */ 1236 /* Collect the BSSID, and set state to allow tx */ 1237 1238 result = hfa384x_drvr_getconfig(hw, 1239 HFA384x_RID_CURRENTBSSID, 1240 wlandev->bssid, 1241 WLAN_BSSID_LEN); 1242 if (result) { 1243 pr_debug 1244 ("getconfig(0x%02x) failed, result = %d\n", 1245 HFA384x_RID_CURRENTBSSID, result); 1246 return; 1247 } 1248 1249 result = hfa384x_drvr_getconfig(hw, 1250 HFA384x_RID_CURRENTSSID, 1251 &ssid, sizeof(ssid)); 1252 if (result) { 1253 pr_debug 1254 ("getconfig(0x%02x) failed, result = %d\n", 1255 HFA384x_RID_CURRENTSSID, result); 1256 return; 1257 } 1258 prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid, 1259 (struct p80211pstrd *)&wlandev->ssid); 1260 1261 /* Collect the port status */ 1262 result = hfa384x_drvr_getconfig16(hw, 1263 HFA384x_RID_PORTSTATUS, 1264 &portstatus); 1265 if (result) { 1266 pr_debug 1267 ("getconfig(0x%02x) failed, result = %d\n", 1268 HFA384x_RID_PORTSTATUS, result); 1269 return; 1270 } 1271 wlandev->macmode = 1272 (portstatus == HFA384x_PSTATUS_CONN_IBSS) ? 1273 WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA; 1274 1275 /* signal back up to cfg80211 layer */ 1276 prism2_connect_result(wlandev, P80211ENUM_truth_false); 1277 1278 /* Get the ball rolling on the comms quality stuff */ 1279 prism2sta_commsqual_defer(&hw->commsqual_bh); 1280 } 1281 break; 1282 1283 case HFA384x_LINK_DISCONNECTED: 1284 /* This one indicates that our association is gone. We've 1285 * lost connection with the AP and/or been disassociated. 1286 * This indicates that the MAC has completely cleared it's 1287 * associated state. We * should send a deauth indication 1288 * (implying disassoc) up * to the MLME. 1289 * Response: 1290 * Indicate Deauthentication 1291 * Block Transmits, Ignore receives of data frames 1292 */ 1293 if (wlandev->netdev->type == ARPHRD_ETHER) 1294 netdev_info(wlandev->netdev, 1295 "linkstatus=DISCONNECTED (unhandled)\n"); 1296 wlandev->macmode = WLAN_MACMODE_NONE; 1297 1298 netif_carrier_off(wlandev->netdev); 1299 1300 /* signal back up to cfg80211 layer */ 1301 prism2_disconnected(wlandev); 1302 1303 break; 1304 1305 case HFA384x_LINK_AP_CHANGE: 1306 /* This one indicates that the MAC has decided to and 1307 * successfully completed a change to another AP. We 1308 * should probably implement a reassociation indication 1309 * in response to this one. I'm thinking that the 1310 * p80211 layer needs to be notified in case of 1311 * buffering/queueing issues. User mode also needs to be 1312 * notified so that any BSS dependent elements can be 1313 * updated. 1314 * associated state. We * should send a deauth indication 1315 * (implying disassoc) up * to the MLME. 1316 * Response: 1317 * Indicate Reassociation 1318 * Enable Transmits, Receives and pass up data frames 1319 */ 1320 netdev_info(wlandev->netdev, "linkstatus=AP_CHANGE\n"); 1321 1322 result = hfa384x_drvr_getconfig(hw, 1323 HFA384x_RID_CURRENTBSSID, 1324 wlandev->bssid, WLAN_BSSID_LEN); 1325 if (result) { 1326 pr_debug("getconfig(0x%02x) failed, result = %d\n", 1327 HFA384x_RID_CURRENTBSSID, result); 1328 return; 1329 } 1330 1331 result = hfa384x_drvr_getconfig(hw, 1332 HFA384x_RID_CURRENTSSID, 1333 &ssid, sizeof(ssid)); 1334 if (result) { 1335 pr_debug("getconfig(0x%02x) failed, result = %d\n", 1336 HFA384x_RID_CURRENTSSID, result); 1337 return; 1338 } 1339 prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid, 1340 (struct p80211pstrd *)&wlandev->ssid); 1341 1342 hw->link_status = HFA384x_LINK_CONNECTED; 1343 netif_carrier_on(wlandev->netdev); 1344 1345 /* signal back up to cfg80211 layer */ 1346 prism2_roamed(wlandev); 1347 1348 break; 1349 1350 case HFA384x_LINK_AP_OUTOFRANGE: 1351 /* This one indicates that the MAC has decided that the 1352 * AP is out of range, but hasn't found a better candidate 1353 * so the MAC maintains its "associated" state in case 1354 * we get back in range. We should block transmits and 1355 * receives in this state. Do we need an indication here? 1356 * Probably not since a polling user-mode element would 1357 * get this status from p2PortStatus(FD40). What about 1358 * p80211? 1359 * Response: 1360 * Block Transmits, Ignore receives of data frames 1361 */ 1362 netdev_info(wlandev->netdev, "linkstatus=AP_OUTOFRANGE (unhandled)\n"); 1363 1364 netif_carrier_off(wlandev->netdev); 1365 1366 break; 1367 1368 case HFA384x_LINK_AP_INRANGE: 1369 /* This one indicates that the MAC has decided that the 1370 * AP is back in range. We continue working with our 1371 * existing association. 1372 * Response: 1373 * Enable Transmits, Receives and pass up data frames 1374 */ 1375 netdev_info(wlandev->netdev, "linkstatus=AP_INRANGE\n"); 1376 1377 hw->link_status = HFA384x_LINK_CONNECTED; 1378 netif_carrier_on(wlandev->netdev); 1379 1380 break; 1381 1382 case HFA384x_LINK_ASSOCFAIL: 1383 /* This one is actually a peer to CONNECTED. We've 1384 * requested a join for a given SSID and optionally BSSID. 1385 * We can use this one to indicate authentication and 1386 * association failures. The trick is going to be 1387 * 1) identifying the failure, and 2) state management. 1388 * Response: 1389 * Disable Transmits, Ignore receives of data frames 1390 */ 1391 if (hw->join_ap && --hw->join_retries > 0) { 1392 struct hfa384x_join_request_data joinreq; 1393 1394 joinreq = hw->joinreq; 1395 /* Send the join request */ 1396 hfa384x_drvr_setconfig(hw, 1397 HFA384x_RID_JOINREQUEST, 1398 &joinreq, 1399 HFA384x_RID_JOINREQUEST_LEN); 1400 netdev_info(wlandev->netdev, 1401 "linkstatus=ASSOCFAIL (re-submitting join)\n"); 1402 } else { 1403 netdev_info(wlandev->netdev, "linkstatus=ASSOCFAIL (unhandled)\n"); 1404 } 1405 1406 netif_carrier_off(wlandev->netdev); 1407 1408 /* signal back up to cfg80211 layer */ 1409 prism2_connect_result(wlandev, P80211ENUM_truth_true); 1410 1411 break; 1412 1413 default: 1414 /* This is bad, IO port problems? */ 1415 netdev_warn(wlandev->netdev, 1416 "unknown linkstatus=0x%02x\n", hw->link_status); 1417 return; 1418 } 1419 1420 wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED); 1421} 1422 1423/* 1424 * prism2sta_inf_linkstatus 1425 * 1426 * Handles the receipt of a Link Status info frame. 1427 * 1428 * Arguments: 1429 * wlandev wlan device structure 1430 * inf ptr to info frame (contents in hfa384x order) 1431 * 1432 * Returns: 1433 * nothing 1434 * 1435 * Side effects: 1436 * 1437 * Call context: 1438 * interrupt 1439 */ 1440static void prism2sta_inf_linkstatus(struct wlandevice *wlandev, 1441 struct hfa384x_inf_frame *inf) 1442{ 1443 struct hfa384x *hw = wlandev->priv; 1444 1445 hw->link_status_new = le16_to_cpu(inf->info.linkstatus.linkstatus); 1446 1447 schedule_work(&hw->link_bh); 1448} 1449 1450/* 1451 * prism2sta_inf_assocstatus 1452 * 1453 * Handles the receipt of an Association Status info frame. Should 1454 * be present in APs only. 1455 * 1456 * Arguments: 1457 * wlandev wlan device structure 1458 * inf ptr to info frame (contents in hfa384x order) 1459 * 1460 * Returns: 1461 * nothing 1462 * 1463 * Side effects: 1464 * 1465 * Call context: 1466 * interrupt 1467 */ 1468static void prism2sta_inf_assocstatus(struct wlandevice *wlandev, 1469 struct hfa384x_inf_frame *inf) 1470{ 1471 struct hfa384x *hw = wlandev->priv; 1472 struct hfa384x_assoc_status rec; 1473 int i; 1474 1475 memcpy(&rec, &inf->info.assocstatus, sizeof(rec)); 1476 le16_to_cpus(&rec.assocstatus); 1477 le16_to_cpus(&rec.reason); 1478 1479 /* 1480 * Find the address in the list of authenticated stations. 1481 * If it wasn't found, then this address has not been previously 1482 * authenticated and something weird has happened if this is 1483 * anything other than an "authentication failed" message. 1484 * If the address was found, then set the "associated" flag for 1485 * that station, based on whether the station is associating or 1486 * losing its association. Something weird has also happened 1487 * if we find the address in the list of authenticated stations 1488 * but we are getting an "authentication failed" message. 1489 */ 1490 1491 for (i = 0; i < hw->authlist.cnt; i++) 1492 if (ether_addr_equal(rec.sta_addr, hw->authlist.addr[i])) 1493 break; 1494 1495 if (i >= hw->authlist.cnt) { 1496 if (rec.assocstatus != HFA384x_ASSOCSTATUS_AUTHFAIL) 1497 netdev_warn(wlandev->netdev, 1498 "assocstatus info frame received for non-authenticated station.\n"); 1499 } else { 1500 hw->authlist.assoc[i] = 1501 (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC || 1502 rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC); 1503 1504 if (rec.assocstatus == HFA384x_ASSOCSTATUS_AUTHFAIL) 1505 netdev_warn(wlandev->netdev, 1506 "authfail assocstatus info frame received for authenticated station.\n"); 1507 } 1508} 1509 1510/* 1511 * prism2sta_inf_authreq 1512 * 1513 * Handles the receipt of an Authentication Request info frame. Should 1514 * be present in APs only. 1515 * 1516 * Arguments: 1517 * wlandev wlan device structure 1518 * inf ptr to info frame (contents in hfa384x order) 1519 * 1520 * Returns: 1521 * nothing 1522 * 1523 * Side effects: 1524 * 1525 * Call context: 1526 * interrupt 1527 * 1528 */ 1529static void prism2sta_inf_authreq(struct wlandevice *wlandev, 1530 struct hfa384x_inf_frame *inf) 1531{ 1532 struct hfa384x *hw = wlandev->priv; 1533 struct sk_buff *skb; 1534 1535 skb = dev_alloc_skb(sizeof(*inf)); 1536 if (skb) { 1537 skb_put(skb, sizeof(*inf)); 1538 memcpy(skb->data, inf, sizeof(*inf)); 1539 skb_queue_tail(&hw->authq, skb); 1540 schedule_work(&hw->link_bh); 1541 } 1542} 1543 1544static void prism2sta_inf_authreq_defer(struct wlandevice *wlandev, 1545 struct hfa384x_inf_frame *inf) 1546{ 1547 struct hfa384x *hw = wlandev->priv; 1548 struct hfa384x_authenticate_station_data rec; 1549 1550 int i, added, result, cnt; 1551 u8 *addr; 1552 1553 /* 1554 * Build the AuthenticateStation record. Initialize it for denying 1555 * authentication. 1556 */ 1557 1558 ether_addr_copy(rec.address, inf->info.authreq.sta_addr); 1559 rec.status = cpu_to_le16(P80211ENUM_status_unspec_failure); 1560 1561 /* 1562 * Authenticate based on the access mode. 1563 */ 1564 1565 switch (hw->accessmode) { 1566 case WLAN_ACCESS_NONE: 1567 1568 /* 1569 * Deny all new authentications. However, if a station 1570 * is ALREADY authenticated, then accept it. 1571 */ 1572 1573 for (i = 0; i < hw->authlist.cnt; i++) 1574 if (ether_addr_equal(rec.address, 1575 hw->authlist.addr[i])) { 1576 rec.status = cpu_to_le16(P80211ENUM_status_successful); 1577 break; 1578 } 1579 1580 break; 1581 1582 case WLAN_ACCESS_ALL: 1583 1584 /* 1585 * Allow all authentications. 1586 */ 1587 1588 rec.status = cpu_to_le16(P80211ENUM_status_successful); 1589 break; 1590 1591 case WLAN_ACCESS_ALLOW: 1592 1593 /* 1594 * Only allow the authentication if the MAC address 1595 * is in the list of allowed addresses. 1596 * 1597 * Since this is the interrupt handler, we may be here 1598 * while the access list is in the middle of being 1599 * updated. Choose the list which is currently okay. 1600 * See "prism2mib_priv_accessallow()" for details. 1601 */ 1602 1603 if (hw->allow.modify == 0) { 1604 cnt = hw->allow.cnt; 1605 addr = hw->allow.addr[0]; 1606 } else { 1607 cnt = hw->allow.cnt1; 1608 addr = hw->allow.addr1[0]; 1609 } 1610 1611 for (i = 0; i < cnt; i++, addr += ETH_ALEN) 1612 if (ether_addr_equal(rec.address, addr)) { 1613 rec.status = cpu_to_le16(P80211ENUM_status_successful); 1614 break; 1615 } 1616 1617 break; 1618 1619 case WLAN_ACCESS_DENY: 1620 1621 /* 1622 * Allow the authentication UNLESS the MAC address is 1623 * in the list of denied addresses. 1624 * 1625 * Since this is the interrupt handler, we may be here 1626 * while the access list is in the middle of being 1627 * updated. Choose the list which is currently okay. 1628 * See "prism2mib_priv_accessdeny()" for details. 1629 */ 1630 1631 if (hw->deny.modify == 0) { 1632 cnt = hw->deny.cnt; 1633 addr = hw->deny.addr[0]; 1634 } else { 1635 cnt = hw->deny.cnt1; 1636 addr = hw->deny.addr1[0]; 1637 } 1638 1639 rec.status = cpu_to_le16(P80211ENUM_status_successful); 1640 1641 for (i = 0; i < cnt; i++, addr += ETH_ALEN) 1642 if (ether_addr_equal(rec.address, addr)) { 1643 rec.status = cpu_to_le16(P80211ENUM_status_unspec_failure); 1644 break; 1645 } 1646 1647 break; 1648 } 1649 1650 /* 1651 * If the authentication is okay, then add the MAC address to the 1652 * list of authenticated stations. Don't add the address if it 1653 * is already in the list. (802.11b does not seem to disallow 1654 * a station from issuing an authentication request when the 1655 * station is already authenticated. Does this sort of thing 1656 * ever happen? We might as well do the check just in case.) 1657 */ 1658 1659 added = 0; 1660 1661 if (rec.status == cpu_to_le16(P80211ENUM_status_successful)) { 1662 for (i = 0; i < hw->authlist.cnt; i++) 1663 if (ether_addr_equal(rec.address, 1664 hw->authlist.addr[i])) 1665 break; 1666 1667 if (i >= hw->authlist.cnt) { 1668 if (hw->authlist.cnt >= WLAN_AUTH_MAX) { 1669 rec.status = cpu_to_le16(P80211ENUM_status_ap_full); 1670 } else { 1671 ether_addr_copy(hw->authlist.addr[hw->authlist.cnt], 1672 rec.address); 1673 hw->authlist.cnt++; 1674 added = 1; 1675 } 1676 } 1677 } 1678 1679 /* 1680 * Send back the results of the authentication. If this doesn't work, 1681 * then make sure to remove the address from the authenticated list if 1682 * it was added. 1683 */ 1684 1685 rec.algorithm = inf->info.authreq.algorithm; 1686 1687 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_AUTHENTICATESTA, 1688 &rec, sizeof(rec)); 1689 if (result) { 1690 if (added) 1691 hw->authlist.cnt--; 1692 netdev_err(wlandev->netdev, 1693 "setconfig(authenticatestation) failed, result=%d\n", 1694 result); 1695 } 1696} 1697 1698/* 1699 * prism2sta_inf_psusercnt 1700 * 1701 * Handles the receipt of a PowerSaveUserCount info frame. Should 1702 * be present in APs only. 1703 * 1704 * Arguments: 1705 * wlandev wlan device structure 1706 * inf ptr to info frame (contents in hfa384x order) 1707 * 1708 * Returns: 1709 * nothing 1710 * 1711 * Side effects: 1712 * 1713 * Call context: 1714 * interrupt 1715 */ 1716static void prism2sta_inf_psusercnt(struct wlandevice *wlandev, 1717 struct hfa384x_inf_frame *inf) 1718{ 1719 struct hfa384x *hw = wlandev->priv; 1720 1721 hw->psusercount = le16_to_cpu(inf->info.psusercnt.usercnt); 1722} 1723 1724/* 1725 * prism2sta_ev_info 1726 * 1727 * Handles the Info event. 1728 * 1729 * Arguments: 1730 * wlandev wlan device structure 1731 * inf ptr to a generic info frame 1732 * 1733 * Returns: 1734 * nothing 1735 * 1736 * Side effects: 1737 * 1738 * Call context: 1739 * interrupt 1740 */ 1741void prism2sta_ev_info(struct wlandevice *wlandev, 1742 struct hfa384x_inf_frame *inf) 1743{ 1744 le16_to_cpus(&inf->infotype); 1745 /* Dispatch */ 1746 switch (inf->infotype) { 1747 case HFA384x_IT_HANDOVERADDR: 1748 prism2sta_inf_handover(wlandev, inf); 1749 break; 1750 case HFA384x_IT_COMMTALLIES: 1751 prism2sta_inf_tallies(wlandev, inf); 1752 break; 1753 case HFA384x_IT_HOSTSCANRESULTS: 1754 prism2sta_inf_hostscanresults(wlandev, inf); 1755 break; 1756 case HFA384x_IT_SCANRESULTS: 1757 prism2sta_inf_scanresults(wlandev, inf); 1758 break; 1759 case HFA384x_IT_CHINFORESULTS: 1760 prism2sta_inf_chinforesults(wlandev, inf); 1761 break; 1762 case HFA384x_IT_LINKSTATUS: 1763 prism2sta_inf_linkstatus(wlandev, inf); 1764 break; 1765 case HFA384x_IT_ASSOCSTATUS: 1766 prism2sta_inf_assocstatus(wlandev, inf); 1767 break; 1768 case HFA384x_IT_AUTHREQ: 1769 prism2sta_inf_authreq(wlandev, inf); 1770 break; 1771 case HFA384x_IT_PSUSERCNT: 1772 prism2sta_inf_psusercnt(wlandev, inf); 1773 break; 1774 case HFA384x_IT_KEYIDCHANGED: 1775 netdev_warn(wlandev->netdev, "Unhandled IT_KEYIDCHANGED\n"); 1776 break; 1777 case HFA384x_IT_ASSOCREQ: 1778 netdev_warn(wlandev->netdev, "Unhandled IT_ASSOCREQ\n"); 1779 break; 1780 case HFA384x_IT_MICFAILURE: 1781 netdev_warn(wlandev->netdev, "Unhandled IT_MICFAILURE\n"); 1782 break; 1783 default: 1784 netdev_warn(wlandev->netdev, 1785 "Unknown info type=0x%02x\n", inf->infotype); 1786 break; 1787 } 1788} 1789 1790/* 1791 * prism2sta_ev_txexc 1792 * 1793 * Handles the TxExc event. A Transmit Exception event indicates 1794 * that the MAC's TX process was unsuccessful - so the packet did 1795 * not get transmitted. 1796 * 1797 * Arguments: 1798 * wlandev wlan device structure 1799 * status tx frame status word 1800 * 1801 * Returns: 1802 * nothing 1803 * 1804 * Side effects: 1805 * 1806 * Call context: 1807 * interrupt 1808 */ 1809void prism2sta_ev_txexc(struct wlandevice *wlandev, u16 status) 1810{ 1811 pr_debug("TxExc status=0x%x.\n", status); 1812} 1813 1814/* 1815 * prism2sta_ev_tx 1816 * 1817 * Handles the Tx event. 1818 * 1819 * Arguments: 1820 * wlandev wlan device structure 1821 * status tx frame status word 1822 * Returns: 1823 * nothing 1824 * 1825 * Side effects: 1826 * 1827 * Call context: 1828 * interrupt 1829 */ 1830void prism2sta_ev_tx(struct wlandevice *wlandev, u16 status) 1831{ 1832 pr_debug("Tx Complete, status=0x%04x\n", status); 1833 /* update linux network stats */ 1834 wlandev->netdev->stats.tx_packets++; 1835} 1836 1837/* 1838 * prism2sta_ev_alloc 1839 * 1840 * Handles the Alloc event. 1841 * 1842 * Arguments: 1843 * wlandev wlan device structure 1844 * 1845 * Returns: 1846 * nothing 1847 * 1848 * Side effects: 1849 * 1850 * Call context: 1851 * interrupt 1852 */ 1853void prism2sta_ev_alloc(struct wlandevice *wlandev) 1854{ 1855 netif_wake_queue(wlandev->netdev); 1856} 1857 1858/* 1859 * create_wlan 1860 * 1861 * Called at module init time. This creates the struct wlandevice structure 1862 * and initializes it with relevant bits. 1863 * 1864 * Arguments: 1865 * none 1866 * 1867 * Returns: 1868 * the created struct wlandevice structure. 1869 * 1870 * Side effects: 1871 * also allocates the priv/hw structures. 1872 * 1873 * Call context: 1874 * process thread 1875 * 1876 */ 1877static struct wlandevice *create_wlan(void) 1878{ 1879 struct wlandevice *wlandev = NULL; 1880 struct hfa384x *hw = NULL; 1881 1882 /* Alloc our structures */ 1883 wlandev = kzalloc(sizeof(*wlandev), GFP_KERNEL); 1884 hw = kzalloc(sizeof(*hw), GFP_KERNEL); 1885 1886 if (!wlandev || !hw) { 1887 kfree(wlandev); 1888 kfree(hw); 1889 return NULL; 1890 } 1891 1892 /* Initialize the network device object. */ 1893 wlandev->nsdname = dev_info; 1894 wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING; 1895 wlandev->priv = hw; 1896 wlandev->open = prism2sta_open; 1897 wlandev->close = prism2sta_close; 1898 wlandev->reset = prism2sta_reset; 1899 wlandev->txframe = prism2sta_txframe; 1900 wlandev->mlmerequest = prism2sta_mlmerequest; 1901 wlandev->set_multicast_list = prism2sta_setmulticast; 1902 wlandev->tx_timeout = hfa384x_tx_timeout; 1903 1904 wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT | P80211_NSDCAP_AUTOJOIN; 1905 1906 /* Initialize the device private data structure. */ 1907 hw->dot11_desired_bss_type = 1; 1908 1909 return wlandev; 1910} 1911 1912void prism2sta_commsqual_defer(struct work_struct *data) 1913{ 1914 struct hfa384x *hw = container_of(data, struct hfa384x, commsqual_bh); 1915 struct wlandevice *wlandev = hw->wlandev; 1916 struct hfa384x_bytestr32 ssid; 1917 struct p80211msg_dot11req_mibget msg; 1918 struct p80211item_uint32 *mibitem = (struct p80211item_uint32 *) 1919 &msg.mibattribute.data; 1920 int result = 0; 1921 1922 if (hw->wlandev->hwremoved) 1923 return; 1924 1925 /* we don't care if we're in AP mode */ 1926 if ((wlandev->macmode == WLAN_MACMODE_NONE) || 1927 (wlandev->macmode == WLAN_MACMODE_ESS_AP)) { 1928 return; 1929 } 1930 1931 /* It only makes sense to poll these in non-IBSS */ 1932 if (wlandev->macmode != WLAN_MACMODE_IBSS_STA) { 1933 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DBMCOMMSQUALITY, 1934 &hw->qual, HFA384x_RID_DBMCOMMSQUALITY_LEN); 1935 1936 if (result) { 1937 netdev_err(wlandev->netdev, "error fetching commsqual\n"); 1938 return; 1939 } 1940 1941 pr_debug("commsqual %d %d %d\n", 1942 le16_to_cpu(hw->qual.cq_curr_bss), 1943 le16_to_cpu(hw->qual.asl_curr_bss), 1944 le16_to_cpu(hw->qual.anl_curr_fc)); 1945 } 1946 1947 /* Get the signal rate */ 1948 msg.msgcode = DIDMSG_DOT11REQ_MIBGET; 1949 mibitem->did = DIDMIB_P2_MAC_CURRENTTXRATE; 1950 result = p80211req_dorequest(wlandev, (u8 *)&msg); 1951 1952 if (result) { 1953 pr_debug("get signal rate failed, result = %d\n", 1954 result); 1955 return; 1956 } 1957 1958 switch (mibitem->data) { 1959 case HFA384x_RATEBIT_1: 1960 hw->txrate = 10; 1961 break; 1962 case HFA384x_RATEBIT_2: 1963 hw->txrate = 20; 1964 break; 1965 case HFA384x_RATEBIT_5dot5: 1966 hw->txrate = 55; 1967 break; 1968 case HFA384x_RATEBIT_11: 1969 hw->txrate = 110; 1970 break; 1971 default: 1972 pr_debug("Bad ratebit (%d)\n", mibitem->data); 1973 } 1974 1975 /* Lastly, we need to make sure the BSSID didn't change on us */ 1976 result = hfa384x_drvr_getconfig(hw, 1977 HFA384x_RID_CURRENTBSSID, 1978 wlandev->bssid, WLAN_BSSID_LEN); 1979 if (result) { 1980 pr_debug("getconfig(0x%02x) failed, result = %d\n", 1981 HFA384x_RID_CURRENTBSSID, result); 1982 return; 1983 } 1984 1985 result = hfa384x_drvr_getconfig(hw, 1986 HFA384x_RID_CURRENTSSID, 1987 &ssid, sizeof(ssid)); 1988 if (result) { 1989 pr_debug("getconfig(0x%02x) failed, result = %d\n", 1990 HFA384x_RID_CURRENTSSID, result); 1991 return; 1992 } 1993 prism2mgmt_bytestr2pstr((struct hfa384x_bytestr *)&ssid, 1994 (struct p80211pstrd *)&wlandev->ssid); 1995 1996 /* Reschedule timer */ 1997 mod_timer(&hw->commsqual_timer, jiffies + HZ); 1998} 1999 2000void prism2sta_commsqual_timer(struct timer_list *t) 2001{ 2002 struct hfa384x *hw = from_timer(hw, t, commsqual_timer); 2003 2004 schedule_work(&hw->commsqual_bh); 2005}