aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/base.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c129
1 files changed, 102 insertions, 27 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 7ac3a720e52c..93005f1d326d 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -59,8 +59,8 @@
59#include "base.h" 59#include "base.h"
60#include "reg.h" 60#include "reg.h"
61#include "debug.h" 61#include "debug.h"
62#include "ani.h"
62 63
63static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
64static int modparam_nohwcrypt; 64static int modparam_nohwcrypt;
65module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); 65module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
66MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); 66MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
@@ -365,6 +365,7 @@ static void ath5k_beacon_send(struct ath5k_softc *sc);
365static void ath5k_beacon_config(struct ath5k_softc *sc); 365static void ath5k_beacon_config(struct ath5k_softc *sc);
366static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); 366static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
367static void ath5k_tasklet_beacon(unsigned long data); 367static void ath5k_tasklet_beacon(unsigned long data);
368static void ath5k_tasklet_ani(unsigned long data);
368 369
369static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) 370static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
370{ 371{
@@ -830,6 +831,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
830 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); 831 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
831 tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); 832 tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
832 tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); 833 tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
834 tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
833 835
834 ret = ath5k_eeprom_read_mac(ah, mac); 836 ret = ath5k_eeprom_read_mac(ah, mac);
835 if (ret) { 837 if (ret) {
@@ -1635,7 +1637,6 @@ ath5k_txq_cleanup(struct ath5k_softc *sc)
1635 sc->txqs[i].link); 1637 sc->txqs[i].link);
1636 } 1638 }
1637 } 1639 }
1638 ieee80211_wake_queues(sc->hw); /* XXX move to callers */
1639 1640
1640 for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) 1641 for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
1641 if (sc->txqs[i].setup) 1642 if (sc->txqs[i].setup)
@@ -1805,6 +1806,25 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
1805 } 1806 }
1806} 1807}
1807 1808
1809static void
1810ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
1811{
1812 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
1813 struct ath5k_hw *ah = sc->ah;
1814 struct ath_common *common = ath5k_hw_common(ah);
1815
1816 /* only beacons from our BSSID */
1817 if (!ieee80211_is_beacon(mgmt->frame_control) ||
1818 memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0)
1819 return;
1820
1821 ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg,
1822 rssi);
1823
1824 /* in IBSS mode we should keep RSSI statistics per neighbour */
1825 /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */
1826}
1827
1808/* 1828/*
1809 * Compute padding position. skb must contains an IEEE 802.11 frame 1829 * Compute padding position. skb must contains an IEEE 802.11 frame
1810 */ 1830 */
@@ -1923,6 +1943,8 @@ ath5k_tasklet_rx(unsigned long data)
1923 sc->stats.rxerr_fifo++; 1943 sc->stats.rxerr_fifo++;
1924 if (rs.rs_status & AR5K_RXERR_PHY) { 1944 if (rs.rs_status & AR5K_RXERR_PHY) {
1925 sc->stats.rxerr_phy++; 1945 sc->stats.rxerr_phy++;
1946 if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32)
1947 sc->stats.rxerr_phy_code[rs.rs_phyerr]++;
1926 goto next; 1948 goto next;
1927 } 1949 }
1928 if (rs.rs_status & AR5K_RXERR_DECRYPT) { 1950 if (rs.rs_status & AR5K_RXERR_DECRYPT) {
@@ -2024,6 +2046,8 @@ accept:
2024 2046
2025 ath5k_debug_dump_skb(sc, skb, "RX ", 0); 2047 ath5k_debug_dump_skb(sc, skb, "RX ", 0);
2026 2048
2049 ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi);
2050
2027 /* check beacons in IBSS mode */ 2051 /* check beacons in IBSS mode */
2028 if (sc->opmode == NL80211_IFTYPE_ADHOC) 2052 if (sc->opmode == NL80211_IFTYPE_ADHOC)
2029 ath5k_check_ibss_tsf(sc, skb, rxs); 2053 ath5k_check_ibss_tsf(sc, skb, rxs);
@@ -2060,6 +2084,17 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
2060 list_for_each_entry_safe(bf, bf0, &txq->q, list) { 2084 list_for_each_entry_safe(bf, bf0, &txq->q, list) {
2061 ds = bf->desc; 2085 ds = bf->desc;
2062 2086
2087 /*
2088 * It's possible that the hardware can say the buffer is
2089 * completed when it hasn't yet loaded the ds_link from
2090 * host memory and moved on. If there are more TX
2091 * descriptors in the queue, wait for TXDP to change
2092 * before processing this one.
2093 */
2094 if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr &&
2095 !list_is_last(&bf->list, &txq->q))
2096 break;
2097
2063 ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); 2098 ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
2064 if (unlikely(ret == -EINPROGRESS)) 2099 if (unlikely(ret == -EINPROGRESS))
2065 break; 2100 break;
@@ -2095,7 +2130,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
2095 info->status.rates[ts.ts_final_idx].count++; 2130 info->status.rates[ts.ts_final_idx].count++;
2096 2131
2097 if (unlikely(ts.ts_status)) { 2132 if (unlikely(ts.ts_status)) {
2098 sc->ll_stats.dot11ACKFailureCount++; 2133 sc->stats.ack_fail++;
2099 if (ts.ts_status & AR5K_TXERR_FILT) { 2134 if (ts.ts_status & AR5K_TXERR_FILT) {
2100 info->flags |= IEEE80211_TX_STAT_TX_FILTERED; 2135 info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
2101 sc->stats.txerr_filt++; 2136 sc->stats.txerr_filt++;
@@ -2498,9 +2533,6 @@ ath5k_init(struct ath5k_softc *sc)
2498 */ 2533 */
2499 ath5k_stop_locked(sc); 2534 ath5k_stop_locked(sc);
2500 2535
2501 /* Set PHY calibration interval */
2502 ah->ah_cal_intval = ath5k_calinterval;
2503
2504 /* 2536 /*
2505 * The basic interface to setting the hardware in a good 2537 * The basic interface to setting the hardware in a good
2506 * state is ``reset''. On return the hardware is known to 2538 * state is ``reset''. On return the hardware is known to
@@ -2512,7 +2544,8 @@ ath5k_init(struct ath5k_softc *sc)
2512 sc->curband = &sc->sbands[sc->curchan->band]; 2544 sc->curband = &sc->sbands[sc->curchan->band];
2513 sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | 2545 sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
2514 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | 2546 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
2515 AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI; 2547 AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
2548
2516 ret = ath5k_reset(sc, NULL); 2549 ret = ath5k_reset(sc, NULL);
2517 if (ret) 2550 if (ret)
2518 goto done; 2551 goto done;
@@ -2526,8 +2559,7 @@ ath5k_init(struct ath5k_softc *sc)
2526 for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) 2559 for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
2527 ath5k_hw_reset_key(ah, i); 2560 ath5k_hw_reset_key(ah, i);
2528 2561
2529 /* Set ack to be sent at low bit-rates */ 2562 ath5k_hw_set_ack_bitrate_high(ah, true);
2530 ath5k_hw_set_ack_bitrate_high(ah, false);
2531 ret = 0; 2563 ret = 0;
2532done: 2564done:
2533 mmiowb(); 2565 mmiowb();
@@ -2624,12 +2656,33 @@ ath5k_stop_hw(struct ath5k_softc *sc)
2624 tasklet_kill(&sc->restq); 2656 tasklet_kill(&sc->restq);
2625 tasklet_kill(&sc->calib); 2657 tasklet_kill(&sc->calib);
2626 tasklet_kill(&sc->beacontq); 2658 tasklet_kill(&sc->beacontq);
2659 tasklet_kill(&sc->ani_tasklet);
2627 2660
2628 ath5k_rfkill_hw_stop(sc->ah); 2661 ath5k_rfkill_hw_stop(sc->ah);
2629 2662
2630 return ret; 2663 return ret;
2631} 2664}
2632 2665
2666static void
2667ath5k_intr_calibration_poll(struct ath5k_hw *ah)
2668{
2669 if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) &&
2670 !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) {
2671 /* run ANI only when full calibration is not active */
2672 ah->ah_cal_next_ani = jiffies +
2673 msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI);
2674 tasklet_schedule(&ah->ah_sc->ani_tasklet);
2675
2676 } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) {
2677 ah->ah_cal_next_full = jiffies +
2678 msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
2679 tasklet_schedule(&ah->ah_sc->calib);
2680 }
2681 /* we could use SWI to generate enough interrupts to meet our
2682 * calibration interval requirements, if necessary:
2683 * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
2684}
2685
2633static irqreturn_t 2686static irqreturn_t
2634ath5k_intr(int irq, void *dev_id) 2687ath5k_intr(int irq, void *dev_id)
2635{ 2688{
@@ -2653,7 +2706,20 @@ ath5k_intr(int irq, void *dev_id)
2653 */ 2706 */
2654 tasklet_schedule(&sc->restq); 2707 tasklet_schedule(&sc->restq);
2655 } else if (unlikely(status & AR5K_INT_RXORN)) { 2708 } else if (unlikely(status & AR5K_INT_RXORN)) {
2656 tasklet_schedule(&sc->restq); 2709 /*
2710 * Receive buffers are full. Either the bus is busy or
2711 * the CPU is not fast enough to process all received
2712 * frames.
2713 * Older chipsets need a reset to come out of this
2714 * condition, but we treat it as RX for newer chips.
2715 * We don't know exactly which versions need a reset -
2716 * this guess is copied from the HAL.
2717 */
2718 sc->stats.rxorn_intr++;
2719 if (ah->ah_mac_srev < AR5K_SREV_AR5212)
2720 tasklet_schedule(&sc->restq);
2721 else
2722 tasklet_schedule(&sc->rxtq);
2657 } else { 2723 } else {
2658 if (status & AR5K_INT_SWBA) { 2724 if (status & AR5K_INT_SWBA) {
2659 tasklet_hi_schedule(&sc->beacontq); 2725 tasklet_hi_schedule(&sc->beacontq);
@@ -2678,15 +2744,10 @@ ath5k_intr(int irq, void *dev_id)
2678 if (status & AR5K_INT_BMISS) { 2744 if (status & AR5K_INT_BMISS) {
2679 /* TODO */ 2745 /* TODO */
2680 } 2746 }
2681 if (status & AR5K_INT_SWI) {
2682 tasklet_schedule(&sc->calib);
2683 }
2684 if (status & AR5K_INT_MIB) { 2747 if (status & AR5K_INT_MIB) {
2685 /* 2748 sc->stats.mib_intr++;
2686 * These stats are also used for ANI i think 2749 ath5k_hw_update_mib_counters(ah);
2687 * so how about updating them more often ? 2750 ath5k_ani_mib_intr(ah);
2688 */
2689 ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
2690 } 2751 }
2691 if (status & AR5K_INT_GPIO) 2752 if (status & AR5K_INT_GPIO)
2692 tasklet_schedule(&sc->rf_kill.toggleq); 2753 tasklet_schedule(&sc->rf_kill.toggleq);
@@ -2697,7 +2758,7 @@ ath5k_intr(int irq, void *dev_id)
2697 if (unlikely(!counter)) 2758 if (unlikely(!counter))
2698 ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); 2759 ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
2699 2760
2700 ath5k_hw_calibration_poll(ah); 2761 ath5k_intr_calibration_poll(ah);
2701 2762
2702 return IRQ_HANDLED; 2763 return IRQ_HANDLED;
2703} 2764}
@@ -2721,8 +2782,7 @@ ath5k_tasklet_calibrate(unsigned long data)
2721 struct ath5k_hw *ah = sc->ah; 2782 struct ath5k_hw *ah = sc->ah;
2722 2783
2723 /* Only full calibration for now */ 2784 /* Only full calibration for now */
2724 if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION) 2785 ah->ah_cal_mask |= AR5K_CALIBRATION_FULL;
2725 return;
2726 2786
2727 /* Stop queues so that calibration 2787 /* Stop queues so that calibration
2728 * doesn't interfere with tx */ 2788 * doesn't interfere with tx */
@@ -2738,18 +2798,29 @@ ath5k_tasklet_calibrate(unsigned long data)
2738 * to load new gain values. 2798 * to load new gain values.
2739 */ 2799 */
2740 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); 2800 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
2741 ath5k_reset_wake(sc); 2801 ath5k_reset(sc, sc->curchan);
2742 } 2802 }
2743 if (ath5k_hw_phy_calibrate(ah, sc->curchan)) 2803 if (ath5k_hw_phy_calibrate(ah, sc->curchan))
2744 ATH5K_ERR(sc, "calibration of channel %u failed\n", 2804 ATH5K_ERR(sc, "calibration of channel %u failed\n",
2745 ieee80211_frequency_to_channel( 2805 ieee80211_frequency_to_channel(
2746 sc->curchan->center_freq)); 2806 sc->curchan->center_freq));
2747 2807
2748 ah->ah_swi_mask = 0;
2749
2750 /* Wake queues */ 2808 /* Wake queues */
2751 ieee80211_wake_queues(sc->hw); 2809 ieee80211_wake_queues(sc->hw);
2752 2810
2811 ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
2812}
2813
2814
2815static void
2816ath5k_tasklet_ani(unsigned long data)
2817{
2818 struct ath5k_softc *sc = (void *)data;
2819 struct ath5k_hw *ah = sc->ah;
2820
2821 ah->ah_cal_mask |= AR5K_CALIBRATION_ANI;
2822 ath5k_ani_calibration(ah);
2823 ah->ah_cal_mask &= ~AR5K_CALIBRATION_ANI;
2753} 2824}
2754 2825
2755 2826
@@ -2852,6 +2923,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
2852 goto err; 2923 goto err;
2853 } 2924 }
2854 2925
2926 ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode);
2927
2855 /* 2928 /*
2856 * Change channels and update the h/w rate map if we're switching; 2929 * Change channels and update the h/w rate map if we're switching;
2857 * e.g. 11a to 11b/g. 2930 * e.g. 11a to 11b/g.
@@ -3207,12 +3280,14 @@ ath5k_get_stats(struct ieee80211_hw *hw,
3207 struct ieee80211_low_level_stats *stats) 3280 struct ieee80211_low_level_stats *stats)
3208{ 3281{
3209 struct ath5k_softc *sc = hw->priv; 3282 struct ath5k_softc *sc = hw->priv;
3210 struct ath5k_hw *ah = sc->ah;
3211 3283
3212 /* Force update */ 3284 /* Force update */
3213 ath5k_hw_update_mib_counters(ah, &sc->ll_stats); 3285 ath5k_hw_update_mib_counters(sc->ah);
3214 3286
3215 memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); 3287 stats->dot11ACKFailureCount = sc->stats.ack_fail;
3288 stats->dot11RTSFailureCount = sc->stats.rts_fail;
3289 stats->dot11RTSSuccessCount = sc->stats.rts_ok;
3290 stats->dot11FCSErrorCount = sc->stats.fcs_error;
3216 3291
3217 return 0; 3292 return 0;
3218} 3293}