main.c (c9ae6ab4c7d7aa29f9607ac69daafbc241fc123e) | main.c (ef1b6cd9a1ba06a3daf9a03aa8f25d52d1f2c31a) |
---|---|
1/* 2 * Copyright (c) 2008-2011 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES --- 130 unchanged lines hidden (view full) --- 139 spin_unlock(&common->cc_lock); 140 141 ath9k_hw_setpower(sc->sc_ah, mode); 142 143 unlock: 144 spin_unlock_irqrestore(&sc->sc_pm_lock, flags); 145} 146 | 1/* 2 * Copyright (c) 2008-2011 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES --- 130 unchanged lines hidden (view full) --- 139 spin_unlock(&common->cc_lock); 140 141 ath9k_hw_setpower(sc->sc_ah, mode); 142 143 unlock: 144 spin_unlock_irqrestore(&sc->sc_pm_lock, flags); 145} 146 |
147void ath_start_ani(struct ath_common *common) 148{ 149 struct ath_hw *ah = common->ah; 150 unsigned long timestamp = jiffies_to_msecs(jiffies); 151 struct ath_softc *sc = (struct ath_softc *) common->priv; 152 153 if (!(sc->sc_flags & SC_OP_ANI_RUN)) 154 return; 155 156 if (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) 157 return; 158 159 common->ani.longcal_timer = timestamp; 160 common->ani.shortcal_timer = timestamp; 161 common->ani.checkani_timer = timestamp; 162 163 mod_timer(&common->ani.timer, 164 jiffies + 165 msecs_to_jiffies((u32)ah->config.ani_poll_interval)); 166} 167 168static void ath_update_survey_nf(struct ath_softc *sc, int channel) 169{ 170 struct ath_hw *ah = sc->sc_ah; 171 struct ath9k_channel *chan = &ah->channels[channel]; 172 struct survey_info *survey = &sc->survey[channel]; 173 174 if (chan->noisefloor) { 175 survey->filled |= SURVEY_INFO_NOISE_DBM; 176 survey->noise = ath9k_hw_getchan_noise(ah, chan); 177 } 178} 179 180/* 181 * Updates the survey statistics and returns the busy time since last 182 * update in %, if the measurement duration was long enough for the 183 * result to be useful, -1 otherwise. 184 */ 185static int ath_update_survey_stats(struct ath_softc *sc) 186{ 187 struct ath_hw *ah = sc->sc_ah; 188 struct ath_common *common = ath9k_hw_common(ah); 189 int pos = ah->curchan - &ah->channels[0]; 190 struct survey_info *survey = &sc->survey[pos]; 191 struct ath_cycle_counters *cc = &common->cc_survey; 192 unsigned int div = common->clockrate * 1000; 193 int ret = 0; 194 195 if (!ah->curchan) 196 return -1; 197 198 if (ah->power_mode == ATH9K_PM_AWAKE) 199 ath_hw_cycle_counters_update(common); 200 201 if (cc->cycles > 0) { 202 survey->filled |= SURVEY_INFO_CHANNEL_TIME | 203 SURVEY_INFO_CHANNEL_TIME_BUSY | 204 SURVEY_INFO_CHANNEL_TIME_RX | 205 SURVEY_INFO_CHANNEL_TIME_TX; 206 survey->channel_time += cc->cycles / div; 207 survey->channel_time_busy += cc->rx_busy / div; 208 survey->channel_time_rx += cc->rx_frame / div; 209 survey->channel_time_tx += cc->tx_frame / div; 210 } 211 212 if (cc->cycles < div) 213 return -1; 214 215 if (cc->cycles > 0) 216 ret = cc->rx_busy * 100 / cc->cycles; 217 218 memset(cc, 0, sizeof(*cc)); 219 220 ath_update_survey_nf(sc, pos); 221 222 return ret; 223} 224 | |
225static void __ath_cancel_work(struct ath_softc *sc) 226{ 227 cancel_work_sync(&sc->paprd_work); 228 cancel_work_sync(&sc->hw_check_work); 229 cancel_delayed_work_sync(&sc->tx_complete_work); 230 cancel_delayed_work_sync(&sc->hw_pll_work); 231} 232 --- 142 unchanged lines hidden (view full) --- 375 if (sc->sc_flags & SC_OP_INVALID) 376 return -EIO; 377 378 r = ath_reset_internal(sc, hchan, false); 379 380 return r; 381} 382 | 147static void __ath_cancel_work(struct ath_softc *sc) 148{ 149 cancel_work_sync(&sc->paprd_work); 150 cancel_work_sync(&sc->hw_check_work); 151 cancel_delayed_work_sync(&sc->tx_complete_work); 152 cancel_delayed_work_sync(&sc->hw_pll_work); 153} 154 --- 142 unchanged lines hidden (view full) --- 297 if (sc->sc_flags & SC_OP_INVALID) 298 return -EIO; 299 300 r = ath_reset_internal(sc, hchan, false); 301 302 return r; 303} 304 |
383static void ath_paprd_activate(struct ath_softc *sc) 384{ 385 struct ath_hw *ah = sc->sc_ah; 386 struct ath9k_hw_cal_data *caldata = ah->caldata; 387 int chain; 388 389 if (!caldata || !caldata->paprd_done) 390 return; 391 392 ath9k_ps_wakeup(sc); 393 ar9003_paprd_enable(ah, false); 394 for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { 395 if (!(ah->txchainmask & BIT(chain))) 396 continue; 397 398 ar9003_paprd_populate_single_table(ah, caldata, chain); 399 } 400 401 ar9003_paprd_enable(ah, true); 402 ath9k_ps_restore(sc); 403} 404 405static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain) 406{ 407 struct ieee80211_hw *hw = sc->hw; 408 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 409 struct ath_hw *ah = sc->sc_ah; 410 struct ath_common *common = ath9k_hw_common(ah); 411 struct ath_tx_control txctl; 412 int time_left; 413 414 memset(&txctl, 0, sizeof(txctl)); 415 txctl.txq = sc->tx.txq_map[WME_AC_BE]; 416 417 memset(tx_info, 0, sizeof(*tx_info)); 418 tx_info->band = hw->conf.channel->band; 419 tx_info->flags |= IEEE80211_TX_CTL_NO_ACK; 420 tx_info->control.rates[0].idx = 0; 421 tx_info->control.rates[0].count = 1; 422 tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS; 423 tx_info->control.rates[1].idx = -1; 424 425 init_completion(&sc->paprd_complete); 426 txctl.paprd = BIT(chain); 427 428 if (ath_tx_start(hw, skb, &txctl) != 0) { 429 ath_dbg(common, CALIBRATE, "PAPRD TX failed\n"); 430 dev_kfree_skb_any(skb); 431 return false; 432 } 433 434 time_left = wait_for_completion_timeout(&sc->paprd_complete, 435 msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); 436 437 if (!time_left) 438 ath_dbg(common, CALIBRATE, 439 "Timeout waiting for paprd training on TX chain %d\n", 440 chain); 441 442 return !!time_left; 443} 444 445void ath_paprd_calibrate(struct work_struct *work) 446{ 447 struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); 448 struct ieee80211_hw *hw = sc->hw; 449 struct ath_hw *ah = sc->sc_ah; 450 struct ieee80211_hdr *hdr; 451 struct sk_buff *skb = NULL; 452 struct ath9k_hw_cal_data *caldata = ah->caldata; 453 struct ath_common *common = ath9k_hw_common(ah); 454 int ftype; 455 int chain_ok = 0; 456 int chain; 457 int len = 1800; 458 459 if (!caldata) 460 return; 461 462 ath9k_ps_wakeup(sc); 463 464 if (ar9003_paprd_init_table(ah) < 0) 465 goto fail_paprd; 466 467 skb = alloc_skb(len, GFP_KERNEL); 468 if (!skb) 469 goto fail_paprd; 470 471 skb_put(skb, len); 472 memset(skb->data, 0, len); 473 hdr = (struct ieee80211_hdr *)skb->data; 474 ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC; 475 hdr->frame_control = cpu_to_le16(ftype); 476 hdr->duration_id = cpu_to_le16(10); 477 memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); 478 memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); 479 memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); 480 481 for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { 482 if (!(ah->txchainmask & BIT(chain))) 483 continue; 484 485 chain_ok = 0; 486 487 ath_dbg(common, CALIBRATE, 488 "Sending PAPRD frame for thermal measurement on chain %d\n", 489 chain); 490 if (!ath_paprd_send_frame(sc, skb, chain)) 491 goto fail_paprd; 492 493 ar9003_paprd_setup_gain_table(ah, chain); 494 495 ath_dbg(common, CALIBRATE, 496 "Sending PAPRD training frame on chain %d\n", chain); 497 if (!ath_paprd_send_frame(sc, skb, chain)) 498 goto fail_paprd; 499 500 if (!ar9003_paprd_is_done(ah)) { 501 ath_dbg(common, CALIBRATE, 502 "PAPRD not yet done on chain %d\n", chain); 503 break; 504 } 505 506 if (ar9003_paprd_create_curve(ah, caldata, chain)) { 507 ath_dbg(common, CALIBRATE, 508 "PAPRD create curve failed on chain %d\n", 509 chain); 510 break; 511 } 512 513 chain_ok = 1; 514 } 515 kfree_skb(skb); 516 517 if (chain_ok) { 518 caldata->paprd_done = true; 519 ath_paprd_activate(sc); 520 } 521 522fail_paprd: 523 ath9k_ps_restore(sc); 524} 525 526/* 527 * This routine performs the periodic noise floor calibration function 528 * that is used to adjust and optimize the chip performance. This 529 * takes environmental changes (location, temperature) into account. 530 * When the task is complete, it reschedules itself depending on the 531 * appropriate interval that was calculated. 532 */ 533void ath_ani_calibrate(unsigned long data) 534{ 535 struct ath_softc *sc = (struct ath_softc *)data; 536 struct ath_hw *ah = sc->sc_ah; 537 struct ath_common *common = ath9k_hw_common(ah); 538 bool longcal = false; 539 bool shortcal = false; 540 bool aniflag = false; 541 unsigned int timestamp = jiffies_to_msecs(jiffies); 542 u32 cal_interval, short_cal_interval, long_cal_interval; 543 unsigned long flags; 544 545 if (ah->caldata && ah->caldata->nfcal_interference) 546 long_cal_interval = ATH_LONG_CALINTERVAL_INT; 547 else 548 long_cal_interval = ATH_LONG_CALINTERVAL; 549 550 short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? 551 ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; 552 553 /* Only calibrate if awake */ 554 if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) 555 goto set_timer; 556 557 ath9k_ps_wakeup(sc); 558 559 /* Long calibration runs independently of short calibration. */ 560 if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { 561 longcal = true; 562 common->ani.longcal_timer = timestamp; 563 } 564 565 /* Short calibration applies only while caldone is false */ 566 if (!common->ani.caldone) { 567 if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { 568 shortcal = true; 569 common->ani.shortcal_timer = timestamp; 570 common->ani.resetcal_timer = timestamp; 571 } 572 } else { 573 if ((timestamp - common->ani.resetcal_timer) >= 574 ATH_RESTART_CALINTERVAL) { 575 common->ani.caldone = ath9k_hw_reset_calvalid(ah); 576 if (common->ani.caldone) 577 common->ani.resetcal_timer = timestamp; 578 } 579 } 580 581 /* Verify whether we must check ANI */ 582 if (sc->sc_ah->config.enable_ani 583 && (timestamp - common->ani.checkani_timer) >= 584 ah->config.ani_poll_interval) { 585 aniflag = true; 586 common->ani.checkani_timer = timestamp; 587 } 588 589 /* Call ANI routine if necessary */ 590 if (aniflag) { 591 spin_lock_irqsave(&common->cc_lock, flags); 592 ath9k_hw_ani_monitor(ah, ah->curchan); 593 ath_update_survey_stats(sc); 594 spin_unlock_irqrestore(&common->cc_lock, flags); 595 } 596 597 /* Perform calibration if necessary */ 598 if (longcal || shortcal) { 599 common->ani.caldone = 600 ath9k_hw_calibrate(ah, ah->curchan, 601 ah->rxchainmask, longcal); 602 } 603 604 ath_dbg(common, ANI, 605 "Calibration @%lu finished: %s %s %s, caldone: %s\n", 606 jiffies, 607 longcal ? "long" : "", shortcal ? "short" : "", 608 aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); 609 610 ath9k_ps_restore(sc); 611 612set_timer: 613 /* 614 * Set timer interval based on previous results. 615 * The interval must be the shortest necessary to satisfy ANI, 616 * short calibration and long calibration. 617 */ 618 ath9k_debug_samp_bb_mac(sc); 619 cal_interval = ATH_LONG_CALINTERVAL; 620 if (sc->sc_ah->config.enable_ani) 621 cal_interval = min(cal_interval, 622 (u32)ah->config.ani_poll_interval); 623 if (!common->ani.caldone) 624 cal_interval = min(cal_interval, (u32)short_cal_interval); 625 626 mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); 627 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { 628 if (!ah->caldata->paprd_done) 629 ieee80211_queue_work(sc->hw, &sc->paprd_work); 630 else if (!ah->paprd_table_write_done) 631 ath_paprd_activate(sc); 632 } 633} 634 | |
635static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, 636 struct ieee80211_vif *vif) 637{ 638 struct ath_node *an; 639 an = (struct ath_node *)sta->drv_priv; 640 641#ifdef CONFIG_ATH9K_DEBUGFS 642 spin_lock(&sc->nodes_lock); --- 21 unchanged lines hidden (view full) --- 664 spin_unlock(&sc->nodes_lock); 665 an->sta = NULL; 666#endif 667 668 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) 669 ath_tx_node_cleanup(sc, an); 670} 671 | 305static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, 306 struct ieee80211_vif *vif) 307{ 308 struct ath_node *an; 309 an = (struct ath_node *)sta->drv_priv; 310 311#ifdef CONFIG_ATH9K_DEBUGFS 312 spin_lock(&sc->nodes_lock); --- 21 unchanged lines hidden (view full) --- 334 spin_unlock(&sc->nodes_lock); 335 an->sta = NULL; 336#endif 337 338 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) 339 ath_tx_node_cleanup(sc, an); 340} 341 |
672 | |
673void ath9k_tasklet(unsigned long data) 674{ 675 struct ath_softc *sc = (struct ath_softc *)data; 676 struct ath_hw *ah = sc->sc_ah; 677 struct ath_common *common = ath9k_hw_common(ah); 678 679 u32 status = sc->intrstatus; 680 u32 rxmask; --- 217 unchanged lines hidden (view full) --- 898 899void ath_reset_work(struct work_struct *work) 900{ 901 struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); 902 903 ath_reset(sc, true); 904} 905 | 342void ath9k_tasklet(unsigned long data) 343{ 344 struct ath_softc *sc = (struct ath_softc *)data; 345 struct ath_hw *ah = sc->sc_ah; 346 struct ath_common *common = ath9k_hw_common(ah); 347 348 u32 status = sc->intrstatus; 349 u32 rxmask; --- 217 unchanged lines hidden (view full) --- 567 568void ath_reset_work(struct work_struct *work) 569{ 570 struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); 571 572 ath_reset(sc, true); 573} 574 |
906void ath_hw_check(struct work_struct *work) 907{ 908 struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); 909 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 910 unsigned long flags; 911 int busy; 912 u8 is_alive, nbeacon = 1; 913 914 ath9k_ps_wakeup(sc); 915 is_alive = ath9k_hw_check_alive(sc->sc_ah); 916 917 if (is_alive && !AR_SREV_9300(sc->sc_ah)) 918 goto out; 919 else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { 920 ath_dbg(common, RESET, 921 "DCU stuck is detected. Schedule chip reset\n"); 922 RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG); 923 goto sched_reset; 924 } 925 926 spin_lock_irqsave(&common->cc_lock, flags); 927 busy = ath_update_survey_stats(sc); 928 spin_unlock_irqrestore(&common->cc_lock, flags); 929 930 ath_dbg(common, RESET, "Possible baseband hang, busy=%d (try %d)\n", 931 busy, sc->hw_busy_count + 1); 932 if (busy >= 99) { 933 if (++sc->hw_busy_count >= 3) { 934 RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); 935 goto sched_reset; 936 } 937 } else if (busy >= 0) { 938 sc->hw_busy_count = 0; 939 nbeacon = 3; 940 } 941 942 ath_start_rx_poll(sc, nbeacon); 943 goto out; 944 945sched_reset: 946 ieee80211_queue_work(sc->hw, &sc->hw_reset_work); 947out: 948 ath9k_ps_restore(sc); 949} 950 951static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) 952{ 953 static int count; 954 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 955 956 if (pll_sqsum >= 0x40000) { 957 count++; 958 if (count == 3) { 959 /* Rx is hung for more than 500ms. Reset it */ 960 ath_dbg(common, RESET, "Possible RX hang, resetting\n"); 961 RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG); 962 ieee80211_queue_work(sc->hw, &sc->hw_reset_work); 963 count = 0; 964 } 965 } else 966 count = 0; 967} 968 969void ath_hw_pll_work(struct work_struct *work) 970{ 971 struct ath_softc *sc = container_of(work, struct ath_softc, 972 hw_pll_work.work); 973 u32 pll_sqsum; 974 975 if (AR_SREV_9485(sc->sc_ah)) { 976 977 ath9k_ps_wakeup(sc); 978 pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); 979 ath9k_ps_restore(sc); 980 981 ath_hw_pll_rx_hang_check(sc, pll_sqsum); 982 983 ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); 984 } 985} 986 | |
987/**********************/ 988/* mac80211 callbacks */ 989/**********************/ 990 991static int ath9k_start(struct ieee80211_hw *hw) 992{ 993 struct ath_softc *sc = hw->priv; 994 struct ath_hw *ah = sc->sc_ah; --- 389 unchanged lines hidden (view full) --- 1384 if (ath9k_uses_beacons(vif->type)) { 1385 /* Reserve a beacon slot for the vif */ 1386 ath9k_set_beaconing_status(sc, false); 1387 ath_beacon_alloc(sc, vif); 1388 ath9k_set_beaconing_status(sc, true); 1389 } 1390} 1391 | 575/**********************/ 576/* mac80211 callbacks */ 577/**********************/ 578 579static int ath9k_start(struct ieee80211_hw *hw) 580{ 581 struct ath_softc *sc = hw->priv; 582 struct ath_hw *ah = sc->sc_ah; --- 389 unchanged lines hidden (view full) --- 972 if (ath9k_uses_beacons(vif->type)) { 973 /* Reserve a beacon slot for the vif */ 974 ath9k_set_beaconing_status(sc, false); 975 ath_beacon_alloc(sc, vif); 976 ath9k_set_beaconing_status(sc, true); 977 } 978} 979 |
1392void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon) 1393{ 1394 if (!AR_SREV_9300(sc->sc_ah)) 1395 return; 1396 1397 if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) 1398 return; 1399 1400 mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies 1401 (nbeacon * sc->cur_beacon_conf.beacon_interval)); 1402} 1403 1404void ath_rx_poll(unsigned long data) 1405{ 1406 struct ath_softc *sc = (struct ath_softc *)data; 1407 1408 ieee80211_queue_work(sc->hw, &sc->hw_check_work); 1409} 1410 | |
1411static int ath9k_add_interface(struct ieee80211_hw *hw, 1412 struct ieee80211_vif *vif) 1413{ 1414 struct ath_softc *sc = hw->priv; 1415 struct ath_hw *ah = sc->sc_ah; 1416 struct ath_common *common = ath9k_hw_common(ah); 1417 int ret = 0; 1418 --- 1131 unchanged lines hidden --- | 980static int ath9k_add_interface(struct ieee80211_hw *hw, 981 struct ieee80211_vif *vif) 982{ 983 struct ath_softc *sc = hw->priv; 984 struct ath_hw *ah = sc->sc_ah; 985 struct ath_common *common = ath9k_hw_common(ah); 986 int ret = 0; 987 --- 1131 unchanged lines hidden --- |