/* * Copyright (c) 2012 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include"ath9k.h"
/* * TX polling - checks if the TX engine is stuck somewhere * and issues a chip reset if so.
*/ staticbool ath_tx_complete_check(struct ath_softc *sc)
{ struct ath_txq *txq; int i;
if (sc->tx99_state) returntrue;
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
txq = sc->tx.txq_map[i];
ath_txq_lock(sc, txq); if (txq->axq_depth) { if (txq->axq_tx_inprogress) {
ath_txq_unlock(sc, txq); goto reset;
}
/* Need at least one interrupt per second, and we should only react if * we are within a factor two of the expected interval
*/ if (interval > RX_INACTIVE_CHECK_INTERVAL * 2 ||
count >= interval / MSEC_PER_SEC) returntrue;
if (pll_sqsum >= 0x40000) {
count++; if (count == 3) {
ath_dbg(common, RESET, "PLL WAR, resetting the chip\n");
ath9k_queue_reset(sc, RESET_TYPE_PLL_HANG);
count = 0; returntrue;
}
} else {
count = 0;
}
returnfalse;
}
void ath_hw_pll_work(struct work_struct *work)
{
u32 pll_sqsum; struct ath_softc *sc = container_of(work, struct ath_softc,
hw_pll_work.work); struct ath_common *common = ath9k_hw_common(sc->sc_ah); /* * ensure that the PLL WAR is executed only * after the STA is associated (or) if the * beaconing had started in interfaces that * uses beacons.
*/ if (!test_bit(ATH_OP_BEACONS, &common->op_flags)) return;
if (sc->tx99_state) return;
ath9k_ps_wakeup(sc);
pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
ath9k_ps_restore(sc); if (ath_hw_pll_rx_hang_check(sc, pll_sqsum)) return;
set_timer: /* * Set timer interval based on previous results. * The interval must be the shortest necessary to satisfy ANI, * short calibration and long calibration.
*/
cal_interval = ATH_LONG_CALINTERVAL;
cal_interval = min(cal_interval, (u32)ah->config.ani_poll_interval); if (!common->ani.caldone)
cal_interval = min(cal_interval, (u32)short_cal_interval);
/* * Check for the various conditions in which ANI has to * be stopped.
*/ if (ah->opmode == NL80211_IFTYPE_ADHOC) { if (!cur_conf->enable_beacon) goto stop_ani;
} elseif (ah->opmode == NL80211_IFTYPE_AP) { if (!cur_conf->enable_beacon) { /* * Disable ANI only when there are no * associated stations.
*/ if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) goto stop_ani;
}
} elseif (ah->opmode == NL80211_IFTYPE_STATION) { if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) goto stop_ani;
}
if (!test_bit(ATH_OP_ANI_RUN, &common->op_flags)) {
set_bit(ATH_OP_ANI_RUN, &common->op_flags);
ath_start_ani(sc);
}
/* * Updates the survey statistics and returns the busy time since last * update in %, if the measurement duration was long enough for the * result to be useful, -1 otherwise.
*/ int ath_update_survey_stats(struct ath_softc *sc)
{ struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); int pos = ah->curchan - &ah->channels[0]; struct survey_info *survey = &sc->survey[pos]; struct ath_cycle_counters *cc = &common->cc_survey; unsignedint div = common->clockrate * 1000; int ret = 0;
if (!ah->curchan) return -1;
if (ah->power_mode == ATH9K_PM_AWAKE)
ath_hw_cycle_counters_update(common);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.