1 /*- 2 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 3 * Copyright (c) 2004-2005 Atheros Communications, Inc. 4 * Copyright (c) 2006 Devicescape Software, Inc. 5 * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> 6 * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> 7 * Copyright (c) 2010 Bruno Randolf <br1@einfach.org> 8 * 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 19 * redistribution must be conditioned upon including a substantially 20 * similar Disclaimer requirement for further binary redistribution. 21 * 3. Neither the names of the above-listed copyright holders nor the names 22 * of any contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * Alternatively, this software may be distributed under the terms of the 26 * GNU General Public License ("GPL") version 2 as published by the Free 27 * Software Foundation. 28 * 29 * NO WARRANTY 30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 32 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 33 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 34 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 35 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 38 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 40 * THE POSSIBILITY OF SUCH DAMAGES. 41 * 42 */ 43 44 #include <asm/unaligned.h> 45 46 #include "base.h" 47 #include "reg.h" 48 49 extern int ath5k_modparam_nohwcrypt; 50 51 /* functions used from base.c */ 52 void set_beacon_filter(struct ieee80211_hw *hw, bool enable); 53 bool ath_any_vif_assoc(struct ath5k_softc *sc); 54 int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, 55 struct ath5k_txq *txq); 56 int ath5k_init_hw(struct ath5k_softc *sc); 57 int ath5k_stop_hw(struct ath5k_softc *sc); 58 void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif); 59 void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, 60 struct ieee80211_vif *vif); 61 int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan); 62 void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); 63 int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 64 void ath5k_beacon_config(struct ath5k_softc *sc); 65 void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf); 66 void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf); 67 68 /********************\ 69 * Mac80211 functions * 70 \********************/ 71 72 static int 73 ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 74 { 75 struct ath5k_softc *sc = hw->priv; 76 u16 qnum = skb_get_queue_mapping(skb); 77 78 if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) { 79 dev_kfree_skb_any(skb); 80 return 0; 81 } 82 83 return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]); 84 } 85 86 87 static int 88 ath5k_start(struct ieee80211_hw *hw) 89 { 90 return ath5k_init_hw(hw->priv); 91 } 92 93 94 static void 95 ath5k_stop(struct ieee80211_hw *hw) 96 { 97 ath5k_stop_hw(hw->priv); 98 } 99 100 101 static int 102 ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 103 { 104 struct ath5k_softc *sc = hw->priv; 105 int ret; 106 struct ath5k_vif *avf = (void *)vif->drv_priv; 107 108 mutex_lock(&sc->lock); 109 110 if ((vif->type == NL80211_IFTYPE_AP || 111 vif->type == NL80211_IFTYPE_ADHOC) 112 && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) { 113 ret = -ELNRNG; 114 goto end; 115 } 116 117 /* Don't allow other interfaces if one ad-hoc is configured. 118 * TODO: Fix the problems with ad-hoc and multiple other interfaces. 119 * We would need to operate the HW in ad-hoc mode to allow TSF updates 120 * for the IBSS, but this breaks with additional AP or STA interfaces 121 * at the moment. */ 122 if (sc->num_adhoc_vifs || 123 (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { 124 ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n"); 125 ret = -ELNRNG; 126 goto end; 127 } 128 129 switch (vif->type) { 130 case NL80211_IFTYPE_AP: 131 case NL80211_IFTYPE_STATION: 132 case NL80211_IFTYPE_ADHOC: 133 case NL80211_IFTYPE_MESH_POINT: 134 avf->opmode = vif->type; 135 break; 136 default: 137 ret = -EOPNOTSUPP; 138 goto end; 139 } 140 141 sc->nvifs++; 142 ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode); 143 144 /* Assign the vap/adhoc to a beacon xmit slot. */ 145 if ((avf->opmode == NL80211_IFTYPE_AP) || 146 (avf->opmode == NL80211_IFTYPE_ADHOC) || 147 (avf->opmode == NL80211_IFTYPE_MESH_POINT)) { 148 int slot; 149 150 WARN_ON(list_empty(&sc->bcbuf)); 151 avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf, 152 list); 153 list_del(&avf->bbuf->list); 154 155 avf->bslot = 0; 156 for (slot = 0; slot < ATH_BCBUF; slot++) { 157 if (!sc->bslot[slot]) { 158 avf->bslot = slot; 159 break; 160 } 161 } 162 BUG_ON(sc->bslot[avf->bslot] != NULL); 163 sc->bslot[avf->bslot] = vif; 164 if (avf->opmode == NL80211_IFTYPE_AP) 165 sc->num_ap_vifs++; 166 else if (avf->opmode == NL80211_IFTYPE_ADHOC) 167 sc->num_adhoc_vifs++; 168 } 169 170 /* Any MAC address is fine, all others are included through the 171 * filter. 172 */ 173 memcpy(&sc->lladdr, vif->addr, ETH_ALEN); 174 ath5k_hw_set_lladdr(sc->ah, vif->addr); 175 176 memcpy(&avf->lladdr, vif->addr, ETH_ALEN); 177 178 ath5k_mode_setup(sc, vif); 179 180 ret = 0; 181 end: 182 mutex_unlock(&sc->lock); 183 return ret; 184 } 185 186 187 static void 188 ath5k_remove_interface(struct ieee80211_hw *hw, 189 struct ieee80211_vif *vif) 190 { 191 struct ath5k_softc *sc = hw->priv; 192 struct ath5k_vif *avf = (void *)vif->drv_priv; 193 unsigned int i; 194 195 mutex_lock(&sc->lock); 196 sc->nvifs--; 197 198 if (avf->bbuf) { 199 ath5k_txbuf_free_skb(sc, avf->bbuf); 200 list_add_tail(&avf->bbuf->list, &sc->bcbuf); 201 for (i = 0; i < ATH_BCBUF; i++) { 202 if (sc->bslot[i] == vif) { 203 sc->bslot[i] = NULL; 204 break; 205 } 206 } 207 avf->bbuf = NULL; 208 } 209 if (avf->opmode == NL80211_IFTYPE_AP) 210 sc->num_ap_vifs--; 211 else if (avf->opmode == NL80211_IFTYPE_ADHOC) 212 sc->num_adhoc_vifs--; 213 214 ath5k_update_bssid_mask_and_opmode(sc, NULL); 215 mutex_unlock(&sc->lock); 216 } 217 218 219 /* 220 * TODO: Phy disable/diversity etc 221 */ 222 static int 223 ath5k_config(struct ieee80211_hw *hw, u32 changed) 224 { 225 struct ath5k_softc *sc = hw->priv; 226 struct ath5k_hw *ah = sc->ah; 227 struct ieee80211_conf *conf = &hw->conf; 228 int ret = 0; 229 230 mutex_lock(&sc->lock); 231 232 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 233 ret = ath5k_chan_set(sc, conf->channel); 234 if (ret < 0) 235 goto unlock; 236 } 237 238 if ((changed & IEEE80211_CONF_CHANGE_POWER) && 239 (sc->power_level != conf->power_level)) { 240 sc->power_level = conf->power_level; 241 242 /* Half dB steps */ 243 ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); 244 } 245 246 /* TODO: 247 * 1) Move this on config_interface and handle each case 248 * separately eg. when we have only one STA vif, use 249 * AR5K_ANTMODE_SINGLE_AP 250 * 251 * 2) Allow the user to change antenna mode eg. when only 252 * one antenna is present 253 * 254 * 3) Allow the user to set default/tx antenna when possible 255 * 256 * 4) Default mode should handle 90% of the cases, together 257 * with fixed a/b and single AP modes we should be able to 258 * handle 99%. Sectored modes are extreme cases and i still 259 * haven't found a usage for them. If we decide to support them, 260 * then we must allow the user to set how many tx antennas we 261 * have available 262 */ 263 ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); 264 265 unlock: 266 mutex_unlock(&sc->lock); 267 return ret; 268 } 269 270 271 static void 272 ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 273 struct ieee80211_bss_conf *bss_conf, u32 changes) 274 { 275 struct ath5k_vif *avf = (void *)vif->drv_priv; 276 struct ath5k_softc *sc = hw->priv; 277 struct ath5k_hw *ah = sc->ah; 278 struct ath_common *common = ath5k_hw_common(ah); 279 unsigned long flags; 280 281 mutex_lock(&sc->lock); 282 283 if (changes & BSS_CHANGED_BSSID) { 284 /* Cache for later use during resets */ 285 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); 286 common->curaid = 0; 287 ath5k_hw_set_bssid(ah); 288 mmiowb(); 289 } 290 291 if (changes & BSS_CHANGED_BEACON_INT) 292 sc->bintval = bss_conf->beacon_int; 293 294 if (changes & BSS_CHANGED_ASSOC) { 295 avf->assoc = bss_conf->assoc; 296 if (bss_conf->assoc) 297 sc->assoc = bss_conf->assoc; 298 else 299 sc->assoc = ath_any_vif_assoc(sc); 300 301 if (sc->opmode == NL80211_IFTYPE_STATION) 302 set_beacon_filter(hw, sc->assoc); 303 ath5k_hw_set_ledstate(sc->ah, sc->assoc ? 304 AR5K_LED_ASSOC : AR5K_LED_INIT); 305 if (bss_conf->assoc) { 306 ATH5K_DBG(sc, ATH5K_DEBUG_ANY, 307 "Bss Info ASSOC %d, bssid: %pM\n", 308 bss_conf->aid, common->curbssid); 309 common->curaid = bss_conf->aid; 310 ath5k_hw_set_bssid(ah); 311 /* Once ANI is available you would start it here */ 312 } 313 } 314 315 if (changes & BSS_CHANGED_BEACON) { 316 spin_lock_irqsave(&sc->block, flags); 317 ath5k_beacon_update(hw, vif); 318 spin_unlock_irqrestore(&sc->block, flags); 319 } 320 321 if (changes & BSS_CHANGED_BEACON_ENABLED) 322 sc->enable_beacon = bss_conf->enable_beacon; 323 324 if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | 325 BSS_CHANGED_BEACON_INT)) 326 ath5k_beacon_config(sc); 327 328 mutex_unlock(&sc->lock); 329 } 330 331 332 static u64 333 ath5k_prepare_multicast(struct ieee80211_hw *hw, 334 struct netdev_hw_addr_list *mc_list) 335 { 336 u32 mfilt[2], val; 337 u8 pos; 338 struct netdev_hw_addr *ha; 339 340 mfilt[0] = 0; 341 mfilt[1] = 1; 342 343 netdev_hw_addr_list_for_each(ha, mc_list) { 344 /* calculate XOR of eight 6-bit values */ 345 val = get_unaligned_le32(ha->addr + 0); 346 pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; 347 val = get_unaligned_le32(ha->addr + 3); 348 pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; 349 pos &= 0x3f; 350 mfilt[pos / 32] |= (1 << (pos % 32)); 351 /* XXX: we might be able to just do this instead, 352 * but not sure, needs testing, if we do use this we'd 353 * neet to inform below to not reset the mcast */ 354 /* ath5k_hw_set_mcast_filterindex(ah, 355 * ha->addr[5]); */ 356 } 357 358 return ((u64)(mfilt[1]) << 32) | mfilt[0]; 359 } 360 361 362 /* 363 * o always accept unicast, broadcast, and multicast traffic 364 * o multicast traffic for all BSSIDs will be enabled if mac80211 365 * says it should be 366 * o maintain current state of phy ofdm or phy cck error reception. 367 * If the hardware detects any of these type of errors then 368 * ath5k_hw_get_rx_filter() will pass to us the respective 369 * hardware filters to be able to receive these type of frames. 370 * o probe request frames are accepted only when operating in 371 * hostap, adhoc, or monitor modes 372 * o enable promiscuous mode according to the interface state 373 * o accept beacons: 374 * - when operating in adhoc mode so the 802.11 layer creates 375 * node table entries for peers, 376 * - when operating in station mode for collecting rssi data when 377 * the station is otherwise quiet, or 378 * - when scanning 379 */ 380 static void 381 ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, 382 unsigned int *new_flags, u64 multicast) 383 { 384 #define SUPPORTED_FIF_FLAGS \ 385 (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ 386 FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ 387 FIF_BCN_PRBRESP_PROMISC) 388 389 struct ath5k_softc *sc = hw->priv; 390 struct ath5k_hw *ah = sc->ah; 391 u32 mfilt[2], rfilt; 392 393 mutex_lock(&sc->lock); 394 395 mfilt[0] = multicast; 396 mfilt[1] = multicast >> 32; 397 398 /* Only deal with supported flags */ 399 changed_flags &= SUPPORTED_FIF_FLAGS; 400 *new_flags &= SUPPORTED_FIF_FLAGS; 401 402 /* If HW detects any phy or radar errors, leave those filters on. 403 * Also, always enable Unicast, Broadcasts and Multicast 404 * XXX: move unicast, bssid broadcasts and multicast to mac80211 */ 405 rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) | 406 (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | 407 AR5K_RX_FILTER_MCAST); 408 409 if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { 410 if (*new_flags & FIF_PROMISC_IN_BSS) 411 __set_bit(ATH_STAT_PROMISC, sc->status); 412 else 413 __clear_bit(ATH_STAT_PROMISC, sc->status); 414 } 415 416 if (test_bit(ATH_STAT_PROMISC, sc->status)) 417 rfilt |= AR5K_RX_FILTER_PROM; 418 419 /* Note, AR5K_RX_FILTER_MCAST is already enabled */ 420 if (*new_flags & FIF_ALLMULTI) { 421 mfilt[0] = ~0; 422 mfilt[1] = ~0; 423 } 424 425 /* This is the best we can do */ 426 if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)) 427 rfilt |= AR5K_RX_FILTER_PHYERR; 428 429 /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons 430 * and probes for any BSSID */ 431 if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1)) 432 rfilt |= AR5K_RX_FILTER_BEACON; 433 434 /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not 435 * set we should only pass on control frames for this 436 * station. This needs testing. I believe right now this 437 * enables *all* control frames, which is OK.. but 438 * but we should see if we can improve on granularity */ 439 if (*new_flags & FIF_CONTROL) 440 rfilt |= AR5K_RX_FILTER_CONTROL; 441 442 /* Additional settings per mode -- this is per ath5k */ 443 444 /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ 445 446 switch (sc->opmode) { 447 case NL80211_IFTYPE_MESH_POINT: 448 rfilt |= AR5K_RX_FILTER_CONTROL | 449 AR5K_RX_FILTER_BEACON | 450 AR5K_RX_FILTER_PROBEREQ | 451 AR5K_RX_FILTER_PROM; 452 break; 453 case NL80211_IFTYPE_AP: 454 case NL80211_IFTYPE_ADHOC: 455 rfilt |= AR5K_RX_FILTER_PROBEREQ | 456 AR5K_RX_FILTER_BEACON; 457 break; 458 case NL80211_IFTYPE_STATION: 459 if (sc->assoc) 460 rfilt |= AR5K_RX_FILTER_BEACON; 461 default: 462 break; 463 } 464 465 /* Set filters */ 466 ath5k_hw_set_rx_filter(ah, rfilt); 467 468 /* Set multicast bits */ 469 ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); 470 /* Set the cached hw filter flags, this will later actually 471 * be set in HW */ 472 sc->filter_flags = rfilt; 473 474 mutex_unlock(&sc->lock); 475 } 476 477 478 static int 479 ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 480 struct ieee80211_vif *vif, struct ieee80211_sta *sta, 481 struct ieee80211_key_conf *key) 482 { 483 struct ath5k_softc *sc = hw->priv; 484 struct ath5k_hw *ah = sc->ah; 485 struct ath_common *common = ath5k_hw_common(ah); 486 int ret = 0; 487 488 if (ath5k_modparam_nohwcrypt) 489 return -EOPNOTSUPP; 490 491 switch (key->cipher) { 492 case WLAN_CIPHER_SUITE_WEP40: 493 case WLAN_CIPHER_SUITE_WEP104: 494 case WLAN_CIPHER_SUITE_TKIP: 495 break; 496 case WLAN_CIPHER_SUITE_CCMP: 497 if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM) 498 break; 499 return -EOPNOTSUPP; 500 default: 501 WARN_ON(1); 502 return -EINVAL; 503 } 504 505 mutex_lock(&sc->lock); 506 507 switch (cmd) { 508 case SET_KEY: 509 ret = ath_key_config(common, vif, sta, key); 510 if (ret >= 0) { 511 key->hw_key_idx = ret; 512 /* push IV and Michael MIC generation to stack */ 513 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 514 if (key->cipher == WLAN_CIPHER_SUITE_TKIP) 515 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 516 if (key->cipher == WLAN_CIPHER_SUITE_CCMP) 517 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; 518 ret = 0; 519 } 520 break; 521 case DISABLE_KEY: 522 ath_key_delete(common, key); 523 break; 524 default: 525 ret = -EINVAL; 526 } 527 528 mmiowb(); 529 mutex_unlock(&sc->lock); 530 return ret; 531 } 532 533 534 static void 535 ath5k_sw_scan_start(struct ieee80211_hw *hw) 536 { 537 struct ath5k_softc *sc = hw->priv; 538 if (!sc->assoc) 539 ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN); 540 } 541 542 543 static void 544 ath5k_sw_scan_complete(struct ieee80211_hw *hw) 545 { 546 struct ath5k_softc *sc = hw->priv; 547 ath5k_hw_set_ledstate(sc->ah, sc->assoc ? 548 AR5K_LED_ASSOC : AR5K_LED_INIT); 549 } 550 551 552 static int 553 ath5k_get_stats(struct ieee80211_hw *hw, 554 struct ieee80211_low_level_stats *stats) 555 { 556 struct ath5k_softc *sc = hw->priv; 557 558 /* Force update */ 559 ath5k_hw_update_mib_counters(sc->ah); 560 561 stats->dot11ACKFailureCount = sc->stats.ack_fail; 562 stats->dot11RTSFailureCount = sc->stats.rts_fail; 563 stats->dot11RTSSuccessCount = sc->stats.rts_ok; 564 stats->dot11FCSErrorCount = sc->stats.fcs_error; 565 566 return 0; 567 } 568 569 570 static int 571 ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, 572 const struct ieee80211_tx_queue_params *params) 573 { 574 struct ath5k_softc *sc = hw->priv; 575 struct ath5k_hw *ah = sc->ah; 576 struct ath5k_txq_info qi; 577 int ret = 0; 578 579 if (queue >= ah->ah_capabilities.cap_queues.q_tx_num) 580 return 0; 581 582 mutex_lock(&sc->lock); 583 584 ath5k_hw_get_tx_queueprops(ah, queue, &qi); 585 586 qi.tqi_aifs = params->aifs; 587 qi.tqi_cw_min = params->cw_min; 588 qi.tqi_cw_max = params->cw_max; 589 qi.tqi_burst_time = params->txop; 590 591 ATH5K_DBG(sc, ATH5K_DEBUG_ANY, 592 "Configure tx [queue %d], " 593 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", 594 queue, params->aifs, params->cw_min, 595 params->cw_max, params->txop); 596 597 if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) { 598 ATH5K_ERR(sc, 599 "Unable to update hardware queue %u!\n", queue); 600 ret = -EIO; 601 } else 602 ath5k_hw_reset_tx_queue(ah, queue); 603 604 mutex_unlock(&sc->lock); 605 606 return ret; 607 } 608 609 610 static u64 611 ath5k_get_tsf(struct ieee80211_hw *hw) 612 { 613 struct ath5k_softc *sc = hw->priv; 614 615 return ath5k_hw_get_tsf64(sc->ah); 616 } 617 618 619 static void 620 ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) 621 { 622 struct ath5k_softc *sc = hw->priv; 623 624 ath5k_hw_set_tsf64(sc->ah, tsf); 625 } 626 627 628 static void 629 ath5k_reset_tsf(struct ieee80211_hw *hw) 630 { 631 struct ath5k_softc *sc = hw->priv; 632 633 /* 634 * in IBSS mode we need to update the beacon timers too. 635 * this will also reset the TSF if we call it with 0 636 */ 637 if (sc->opmode == NL80211_IFTYPE_ADHOC) 638 ath5k_beacon_update_timers(sc, 0); 639 else 640 ath5k_hw_reset_tsf(sc->ah); 641 } 642 643 644 static int 645 ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) 646 { 647 struct ath5k_softc *sc = hw->priv; 648 struct ieee80211_conf *conf = &hw->conf; 649 struct ath_common *common = ath5k_hw_common(sc->ah); 650 struct ath_cycle_counters *cc = &common->cc_survey; 651 unsigned int div = common->clockrate * 1000; 652 653 if (idx != 0) 654 return -ENOENT; 655 656 spin_lock_bh(&common->cc_lock); 657 ath_hw_cycle_counters_update(common); 658 if (cc->cycles > 0) { 659 sc->survey.channel_time += cc->cycles / div; 660 sc->survey.channel_time_busy += cc->rx_busy / div; 661 sc->survey.channel_time_rx += cc->rx_frame / div; 662 sc->survey.channel_time_tx += cc->tx_frame / div; 663 } 664 memset(cc, 0, sizeof(*cc)); 665 spin_unlock_bh(&common->cc_lock); 666 667 memcpy(survey, &sc->survey, sizeof(*survey)); 668 669 survey->channel = conf->channel; 670 survey->noise = sc->ah->ah_noise_floor; 671 survey->filled = SURVEY_INFO_NOISE_DBM | 672 SURVEY_INFO_CHANNEL_TIME | 673 SURVEY_INFO_CHANNEL_TIME_BUSY | 674 SURVEY_INFO_CHANNEL_TIME_RX | 675 SURVEY_INFO_CHANNEL_TIME_TX; 676 677 return 0; 678 } 679 680 681 /** 682 * ath5k_set_coverage_class - Set IEEE 802.11 coverage class 683 * 684 * @hw: struct ieee80211_hw pointer 685 * @coverage_class: IEEE 802.11 coverage class number 686 * 687 * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given 688 * coverage class. The values are persistent, they are restored after device 689 * reset. 690 */ 691 static void 692 ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) 693 { 694 struct ath5k_softc *sc = hw->priv; 695 696 mutex_lock(&sc->lock); 697 ath5k_hw_set_coverage_class(sc->ah, coverage_class); 698 mutex_unlock(&sc->lock); 699 } 700 701 702 static int 703 ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) 704 { 705 struct ath5k_softc *sc = hw->priv; 706 707 if (tx_ant == 1 && rx_ant == 1) 708 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); 709 else if (tx_ant == 2 && rx_ant == 2) 710 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); 711 else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) 712 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); 713 else 714 return -EINVAL; 715 return 0; 716 } 717 718 719 static int 720 ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) 721 { 722 struct ath5k_softc *sc = hw->priv; 723 724 switch (sc->ah->ah_ant_mode) { 725 case AR5K_ANTMODE_FIXED_A: 726 *tx_ant = 1; *rx_ant = 1; break; 727 case AR5K_ANTMODE_FIXED_B: 728 *tx_ant = 2; *rx_ant = 2; break; 729 case AR5K_ANTMODE_DEFAULT: 730 *tx_ant = 3; *rx_ant = 3; break; 731 } 732 return 0; 733 } 734 735 736 const struct ieee80211_ops ath5k_hw_ops = { 737 .tx = ath5k_tx, 738 .start = ath5k_start, 739 .stop = ath5k_stop, 740 .add_interface = ath5k_add_interface, 741 /* .change_interface = not implemented */ 742 .remove_interface = ath5k_remove_interface, 743 .config = ath5k_config, 744 .bss_info_changed = ath5k_bss_info_changed, 745 .prepare_multicast = ath5k_prepare_multicast, 746 .configure_filter = ath5k_configure_filter, 747 /* .set_tim = not implemented */ 748 .set_key = ath5k_set_key, 749 /* .update_tkip_key = not implemented */ 750 /* .hw_scan = not implemented */ 751 .sw_scan_start = ath5k_sw_scan_start, 752 .sw_scan_complete = ath5k_sw_scan_complete, 753 .get_stats = ath5k_get_stats, 754 /* .get_tkip_seq = not implemented */ 755 /* .set_frag_threshold = not implemented */ 756 /* .set_rts_threshold = not implemented */ 757 /* .sta_add = not implemented */ 758 /* .sta_remove = not implemented */ 759 /* .sta_notify = not implemented */ 760 .conf_tx = ath5k_conf_tx, 761 .get_tsf = ath5k_get_tsf, 762 .set_tsf = ath5k_set_tsf, 763 .reset_tsf = ath5k_reset_tsf, 764 /* .tx_last_beacon = not implemented */ 765 /* .ampdu_action = not needed */ 766 .get_survey = ath5k_get_survey, 767 .set_coverage_class = ath5k_set_coverage_class, 768 /* .rfkill_poll = not implemented */ 769 /* .flush = not implemented */ 770 /* .channel_switch = not implemented */ 771 /* .napi_poll = not implemented */ 772 .set_antenna = ath5k_set_antenna, 773 .get_antenna = ath5k_get_antenna, 774 }; 775