aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/base.c
diff options
context:
space:
mode:
authorBruno Randolf <br1@einfach.org>2010-04-02 05:44:08 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-07 14:37:53 -0400
commit2111ac0d888767999c7dd6d1309dcc1fb8012022 (patch)
tree1d388cf94a88790a527a5e695081fb3508127a3a /drivers/net/wireless/ath/ath5k/base.c
parentbc53e5129ce879ba024b7d21981871ea63a37b42 (diff)
ath5k: Adaptive Noise Immunity (ANI) Implementation
This is an Adaptive Noise Imunity (ANI) implementation for ath5k. I have looked at both ath9k and HAL sources (they are nearly the same), and even though i have implemented some things differently, the basic algorithm is practically the same, for now. I hope that this can serve as a clean start to improve the algorithm later. This also adds a possibility to manually control ANI settings, right now only thru a debugfs file: * set lowest sensitivity (=highest noise immunity): echo sens-low > /sys/kernel/debug/ath5k/phy0/ani * set highest sensitivity (=lowest noise immunity): echo sens-high > /sys/kernel/debug/ath5k/phy0/ani * automatically control immunity (default): echo ani-on > /sys/kernel/debug/ath5k/phy0/ani * to see the parameters in use and watch them change: cat /sys/kernel/debug/ath5k/phy0/ani Manually setting sensitivity will turn the automatic control off. You can also control each of the five immunity parameters (noise immunity, spur immunity, firstep, ofdm weak signal detection, cck weak signal detection) manually thru the debugfs file. This is tested on AR5414 and nearly doubles the thruput in a noisy 2GHz band. Signed-off-by: Bruno Randolf <br1@einfach.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/base.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index a1c0dcb4926e..c085a06f1e05 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -58,6 +58,7 @@
58#include "base.h" 58#include "base.h"
59#include "reg.h" 59#include "reg.h"
60#include "debug.h" 60#include "debug.h"
61#include "ani.h"
61 62
62static int modparam_nohwcrypt; 63static int modparam_nohwcrypt;
63module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); 64module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
@@ -363,6 +364,7 @@ static void ath5k_beacon_send(struct ath5k_softc *sc);
363static void ath5k_beacon_config(struct ath5k_softc *sc); 364static void ath5k_beacon_config(struct ath5k_softc *sc);
364static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); 365static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
365static void ath5k_tasklet_beacon(unsigned long data); 366static void ath5k_tasklet_beacon(unsigned long data);
367static void ath5k_tasklet_ani(unsigned long data);
366 368
367static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) 369static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
368{ 370{
@@ -828,6 +830,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
828 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); 830 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
829 tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); 831 tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
830 tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); 832 tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
833 tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
831 834
832 ret = ath5k_eeprom_read_mac(ah, mac); 835 ret = ath5k_eeprom_read_mac(ah, mac);
833 if (ret) { 836 if (ret) {
@@ -2530,7 +2533,8 @@ ath5k_init(struct ath5k_softc *sc)
2530 sc->curband = &sc->sbands[sc->curchan->band]; 2533 sc->curband = &sc->sbands[sc->curchan->band];
2531 sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | 2534 sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
2532 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | 2535 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
2533 AR5K_INT_FATAL | AR5K_INT_GLOBAL; 2536 AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
2537
2534 ret = ath5k_reset(sc, NULL); 2538 ret = ath5k_reset(sc, NULL);
2535 if (ret) 2539 if (ret)
2536 goto done; 2540 goto done;
@@ -2642,6 +2646,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
2642 tasklet_kill(&sc->restq); 2646 tasklet_kill(&sc->restq);
2643 tasklet_kill(&sc->calib); 2647 tasklet_kill(&sc->calib);
2644 tasklet_kill(&sc->beacontq); 2648 tasklet_kill(&sc->beacontq);
2649 tasklet_kill(&sc->ani_tasklet);
2645 2650
2646 ath5k_rfkill_hw_stop(sc->ah); 2651 ath5k_rfkill_hw_stop(sc->ah);
2647 2652
@@ -2651,7 +2656,14 @@ ath5k_stop_hw(struct ath5k_softc *sc)
2651static void 2656static void
2652ath5k_intr_calibration_poll(struct ath5k_hw *ah) 2657ath5k_intr_calibration_poll(struct ath5k_hw *ah)
2653{ 2658{
2654 if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { 2659 if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) &&
2660 !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) {
2661 /* run ANI only when full calibration is not active */
2662 ah->ah_cal_next_ani = jiffies +
2663 msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI);
2664 tasklet_schedule(&ah->ah_sc->ani_tasklet);
2665
2666 } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) {
2655 ah->ah_cal_next_full = jiffies + 2667 ah->ah_cal_next_full = jiffies +
2656 msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); 2668 msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
2657 tasklet_schedule(&ah->ah_sc->calib); 2669 tasklet_schedule(&ah->ah_sc->calib);
@@ -2710,7 +2722,9 @@ ath5k_intr(int irq, void *dev_id)
2710 /* TODO */ 2722 /* TODO */
2711 } 2723 }
2712 if (status & AR5K_INT_MIB) { 2724 if (status & AR5K_INT_MIB) {
2725 sc->stats.mib_intr++;
2713 ath5k_hw_update_mib_counters(ah); 2726 ath5k_hw_update_mib_counters(ah);
2727 ath5k_ani_mib_intr(ah);
2714 } 2728 }
2715 if (status & AR5K_INT_GPIO) 2729 if (status & AR5K_INT_GPIO)
2716 tasklet_schedule(&sc->rf_kill.toggleq); 2730 tasklet_schedule(&sc->rf_kill.toggleq);
@@ -2775,6 +2789,18 @@ ath5k_tasklet_calibrate(unsigned long data)
2775} 2789}
2776 2790
2777 2791
2792static void
2793ath5k_tasklet_ani(unsigned long data)
2794{
2795 struct ath5k_softc *sc = (void *)data;
2796 struct ath5k_hw *ah = sc->ah;
2797
2798 ah->ah_cal_mask |= AR5K_CALIBRATION_ANI;
2799 ath5k_ani_calibration(ah);
2800 ah->ah_cal_mask &= ~AR5K_CALIBRATION_ANI;
2801}
2802
2803
2778/********************\ 2804/********************\
2779* Mac80211 functions * 2805* Mac80211 functions *
2780\********************/ 2806\********************/
@@ -2874,6 +2900,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
2874 goto err; 2900 goto err;
2875 } 2901 }
2876 2902
2903 ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode);
2904
2877 /* 2905 /*
2878 * Change channels and update the h/w rate map if we're switching; 2906 * Change channels and update the h/w rate map if we're switching;
2879 * e.g. 11a to 11b/g. 2907 * e.g. 11a to 11b/g.