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