Пример #1
0
/**
 * ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters
 * @ah: The &struct ath5k_hw
 *
 * Just read & reset the registers quickly, so they don't generate more
 * interrupts, save the counters and schedule the tasklet to decide whether
 * to raise immunity or not.
 *
 * We just need to handle PHY error counters, ath5k_hw_update_mib_counters()
 * should take care of all "normal" MIB interrupts.
 */
void
ath5k_ani_mib_intr(struct ath5k_hw *ah)
{
    struct ath5k_ani_state *as = &ah->ani_state;

    /* nothing to do here if HW does not have PHY error counters - they
     * can't be the reason for the MIB interrupt then */
    if (!ah->ah_capabilities.cap_has_phyerr_counters)
        return;

    /* not in use but clear anyways */
    ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT);
    ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT);

    if (ah->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
        return;

    /* If one of the errors triggered, we can get a superfluous second
     * interrupt, even though we have already reset the register. The
     * function detects that so we can return early. */
    if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0)
        return;

    if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH ||
            as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH)
        tasklet_schedule(&ah->ani_tasklet);
}
Пример #2
0
/**
 * ath5k_ani_calibration() - The main ANI calibration function
 * @ah: The &struct ath5k_hw
 *
 * We count OFDM and CCK errors relative to the time where we did not send or
 * receive ("listen" time) and raise or lower immunity accordingly.
 * This is called regularly (every second) from the calibration timer, but also
 * when an error threshold has been reached.
 *
 * In order to synchronize access from different contexts, this should be
 * called only indirectly by scheduling the ANI tasklet!
 */
void
ath5k_ani_calibration(struct ath5k_hw *ah)
{
    struct ath5k_ani_state *as = &ah->ani_state;
    int listen, ofdm_high, ofdm_low, cck_high, cck_low;

    /* get listen time since last call and add it to the counter because we
     * might not have restarted the "ani period" last time.
     * always do this to calculate the busy time also in manual mode */
    listen = ath5k_hw_ani_get_listen_time(ah, as);
    as->listen_time += listen;

    if (as->ani_mode != ATH5K_ANI_MODE_AUTO)
        return;

    ath5k_ani_save_and_clear_phy_errors(ah, as);

    ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000;
    cck_high = as->listen_time * ATH5K_ANI_CCK_TRIG_HIGH / 1000;
    ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000;
    cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000;

    ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
                      "listen %d (now %d)", as->listen_time, listen);
    ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
                      "check high ofdm %d/%d cck %d/%d",
                      as->ofdm_errors, ofdm_high, as->cck_errors, cck_high);

    if (as->ofdm_errors > ofdm_high || as->cck_errors > cck_high) {
        /* too many PHY errors - we have to raise immunity */
        bool ofdm_flag = as->ofdm_errors > ofdm_high ? true : false;
        ath5k_ani_raise_immunity(ah, as, ofdm_flag);
        ath5k_ani_period_restart(as);

    } else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) {
        /* If more than 5 (TODO: why 5?) periods have passed and we got
         * relatively little errors we can try to lower immunity */
        ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
                          "check low ofdm %d/%d cck %d/%d",
                          as->ofdm_errors, ofdm_low, as->cck_errors, cck_low);

        if (as->ofdm_errors <= ofdm_low && as->cck_errors <= cck_low)
            ath5k_ani_lower_immunity(ah, as);

        ath5k_ani_period_restart(as);
    }
}
Пример #3
0
void
ath5k_ani_calibration(struct ath5k_hw *ah)
{
	struct ath5k_ani_state *as = &ah->ani_state;
	int listen, ofdm_high, ofdm_low, cck_high, cck_low;

	listen = ath5k_hw_ani_get_listen_time(ah, as);
	as->listen_time += listen;

	if (as->ani_mode != ATH5K_ANI_MODE_AUTO)
		return;

	ath5k_ani_save_and_clear_phy_errors(ah, as);

	ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000;
	cck_high = as->listen_time * ATH5K_ANI_CCK_TRIG_HIGH / 1000;
	ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000;
	cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000;

	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
		"listen %d (now %d)", as->listen_time, listen);
	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
		"check high ofdm %d/%d cck %d/%d",
		as->ofdm_errors, ofdm_high, as->cck_errors, cck_high);

	if (as->ofdm_errors > ofdm_high || as->cck_errors > cck_high) {
		
		bool ofdm_flag = as->ofdm_errors > ofdm_high ? true : false;
		ath5k_ani_raise_immunity(ah, as, ofdm_flag);
		ath5k_ani_period_restart(as);

	} else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) {
		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
			"check low ofdm %d/%d cck %d/%d",
			as->ofdm_errors, ofdm_low, as->cck_errors, cck_low);

		if (as->ofdm_errors <= ofdm_low && as->cck_errors <= cck_low)
			ath5k_ani_lower_immunity(ah, as);

		ath5k_ani_period_restart(as);
	}
}
Пример #4
0
void
ath5k_ani_mib_intr(struct ath5k_hw *ah)
{
	struct ath5k_ani_state *as = &ah->ani_state;

	if (!ah->ah_capabilities.cap_has_phyerr_counters)
		return;

	
	ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT);
	ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT);

	if (ah->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
		return;

	if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0)
		return;

	if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH ||
	    as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH)
		tasklet_schedule(&ah->ani_tasklet);
}