コード例 #1
0
ファイル: if_ath_rx.c プロジェクト: mihaicarabas/dragonfly
/*
 * Intercept management frames to collect beacon rssi data
 * and to do ibss merges.
 */
void
ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
	int subtype, int rssi, int nf)
{
	struct ieee80211vap *vap = ni->ni_vap;
	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;

	/*
	 * Call up first so subsequent work can use information
	 * potentially stored in the node (e.g. for ibss merge).
	 */
	ATH_VAP(vap)->av_recv_mgmt(ni, m, subtype, rssi, nf);
	switch (subtype) {
	case IEEE80211_FC0_SUBTYPE_BEACON:
		/* update rssi statistics for use by the hal */
		/* XXX unlocked check against vap->iv_bss? */
		ATH_RSSI_LPF(sc->sc_halstats.ns_avgbrssi, rssi);
		if (sc->sc_syncbeacon &&
		    ni == vap->iv_bss && vap->iv_state == IEEE80211_S_RUN) {
			/*
			 * Resync beacon timers using the tsf of the beacon
			 * frame we just received.
			 */
			ath_beacon_config(sc, vap);
		}
		/* fall thru... */
	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
		if (vap->iv_opmode == IEEE80211_M_IBSS &&
		    vap->iv_state == IEEE80211_S_RUN) {
			uint32_t rstamp = sc->sc_lastrs->rs_tstamp;
			uint64_t tsf = ath_extend_tsf(sc, rstamp,
				ath_hal_gettsf64(sc->sc_ah));
			/*
			 * Handle ibss merge as needed; check the tsf on the
			 * frame before attempting the merge.  The 802.11 spec
			 * says the station should change it's bssid to match
			 * the oldest station with the same ssid, where oldest
			 * is determined by the tsf.  Note that hardware
			 * reconfiguration happens through callback to
			 * ath_newstate as the state machine will go from
			 * RUN -> RUN when this happens.
			 */
			if (le64toh(ni->ni_tstamp.tsf) >= tsf) {
				DPRINTF(sc, ATH_DEBUG_STATE,
				    "ibss merge, rstamp %u tsf %ju "
				    "tstamp %ju\n", rstamp, (uintmax_t)tsf,
				    (uintmax_t)ni->ni_tstamp.tsf);
				(void) ieee80211_ibss_merge(ni);
			}
		}
		break;
	}
}
コード例 #2
0
ファイル: common.c プロジェクト: KroMignon/linux-emcraft
static void ath9k_process_rssi(struct ath_common *common,
                               struct ieee80211_hw *hw,
                               struct sk_buff *skb,
                               struct ath_rx_status *rx_stats)
{
    struct ath_hw *ah = common->ah;
    struct ieee80211_sta *sta;
    struct ieee80211_hdr *hdr;
    struct ath_node *an;
    int last_rssi = ATH_RSSI_DUMMY_MARKER;
    __le16 fc;

    hdr = (struct ieee80211_hdr *)skb->data;
    fc = hdr->frame_control;

    rcu_read_lock();
    /*
     * XXX: use ieee80211_find_sta! This requires quite a bit of work
     * under the current ath9k virtual wiphy implementation as we have
     * no way of tying a vif to wiphy. Typically vifs are attached to
     * at least one sdata of a wiphy on mac80211 but with ath9k virtual
     * wiphy you'd have to iterate over every wiphy and each sdata.
     */
    sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
    if (sta) {
        an = (struct ath_node *) sta->drv_priv;
        if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
                !rx_stats->rs_moreaggr)
            ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
        last_rssi = an->last_rssi;
    }
    rcu_read_unlock();

    if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
        rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
                                       ATH_RSSI_EP_MULTIPLIER);
    if (rx_stats->rs_rssi < 0)
        rx_stats->rs_rssi = 0;

    /* Update Beacon RSSI, this is used by ANI. */
    if (ieee80211_is_beacon(fc))
        ah->stats.avgbrssi = rx_stats->rs_rssi;
}
コード例 #3
0
ファイル: if_ath_rx.c プロジェクト: hmatyschok/MeshBSD
/*
 * Intercept management frames to collect beacon rssi data
 * and to do ibss merges.
 */
void
ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
	int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
{
	struct ieee80211vap *vap = ni->ni_vap;
	struct ath_softc *sc = vap->iv_ic->ic_softc;
	uint64_t tsf_beacon_old, tsf_beacon;
	uint64_t nexttbtt;
	int64_t tsf_delta;
	int32_t tsf_delta_bmiss;
	int32_t tsf_remainder;
	uint64_t tsf_beacon_target;
	int tsf_intval;

	tsf_beacon_old = ((uint64_t) le32dec(ni->ni_tstamp.data + 4)) << 32;
	tsf_beacon_old |= le32dec(ni->ni_tstamp.data);

#define	TU_TO_TSF(_tu)	(((u_int64_t)(_tu)) << 10)
	tsf_intval = 1;
	if (ni->ni_intval > 0) {
		tsf_intval = TU_TO_TSF(ni->ni_intval);
	}
#undef	TU_TO_TSF

	/*
	 * Call up first so subsequent work can use information
	 * potentially stored in the node (e.g. for ibss merge).
	 */
	ATH_VAP(vap)->av_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
	switch (subtype) {
	case IEEE80211_FC0_SUBTYPE_BEACON:

		/*
		 * Only do the following processing if it's for
		 * the current BSS.
		 *
		 * In scan and IBSS mode we receive all beacons,
		 * which means we need to filter out stuff
		 * that isn't for us or we'll end up constantly
		 * trying to sync / merge to BSSes that aren't
		 * actually us.
		 */
		if (IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) {
			/* update rssi statistics for use by the hal */
			/* XXX unlocked check against vap->iv_bss? */
			ATH_RSSI_LPF(sc->sc_halstats.ns_avgbrssi, rssi);


			tsf_beacon = ((uint64_t) le32dec(ni->ni_tstamp.data + 4)) << 32;
			tsf_beacon |= le32dec(ni->ni_tstamp.data);

			nexttbtt = ath_hal_getnexttbtt(sc->sc_ah);

			/*
			 * Let's calculate the delta and remainder, so we can see
			 * if the beacon timer from the AP is varying by more than
			 * a few TU.  (Which would be a huge, huge problem.)
			 */
			tsf_delta = (long long) tsf_beacon - (long long) tsf_beacon_old;

			tsf_delta_bmiss = tsf_delta / tsf_intval;

			/*
			 * If our delta is greater than half the beacon interval,
			 * let's round the bmiss value up to the next beacon
			 * interval.  Ie, we're running really, really early
			 * on the next beacon.
			 */
			if (tsf_delta % tsf_intval > (tsf_intval / 2))
				tsf_delta_bmiss ++;

			tsf_beacon_target = tsf_beacon_old +
			    (((unsigned long long) tsf_delta_bmiss) * (long long) tsf_intval);

			/*
			 * The remainder using '%' is between 0 .. intval-1.
			 * If we're actually running too fast, then the remainder
			 * will be some large number just under intval-1.
			 * So we need to look at whether we're running
			 * before or after the target beacon interval
			 * and if we are, modify how we do the remainder
			 * calculation.
			 */
			if (tsf_beacon < tsf_beacon_target) {
				tsf_remainder =
				    -(tsf_intval - ((tsf_beacon - tsf_beacon_old) % tsf_intval));
			} else {
				tsf_remainder = (tsf_beacon - tsf_beacon_old) % tsf_intval;
			}

			DPRINTF(sc, ATH_DEBUG_BEACON, "%s: old_tsf=%llu, new_tsf=%llu, target_tsf=%llu, delta=%lld, bmiss=%d, remainder=%d\n",
			    __func__,
			    (unsigned long long) tsf_beacon_old,
			    (unsigned long long) tsf_beacon,
			    (unsigned long long) tsf_beacon_target,
			    (long long) tsf_delta,
			    tsf_delta_bmiss,
			    tsf_remainder);

			DPRINTF(sc, ATH_DEBUG_BEACON, "%s: tsf=%llu, nexttbtt=%llu, delta=%d\n",
			    __func__,
			    (unsigned long long) tsf_beacon,
			    (unsigned long long) nexttbtt,
			    (int32_t) tsf_beacon - (int32_t) nexttbtt + tsf_intval);

			/* We only do syncbeacon on STA VAPs; not on IBSS */
			if (vap->iv_opmode == IEEE80211_M_STA &&
			    sc->sc_syncbeacon &&
			    ni == vap->iv_bss &&
			    (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) {
				DPRINTF(sc, ATH_DEBUG_BEACON,
				    "%s: syncbeacon=1; syncing\n",
				    __func__);
				/*
				 * Resync beacon timers using the tsf of the beacon
				 * frame we just received.
				 */
				ath_beacon_config(sc, vap);
				sc->sc_syncbeacon = 0;
			}
		}

		/* fall thru... */
	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
		if (vap->iv_opmode == IEEE80211_M_IBSS &&
		    vap->iv_state == IEEE80211_S_RUN &&
		    ieee80211_ibss_merge_check(ni)) {
			uint32_t rstamp = sc->sc_lastrs->rs_tstamp;
			uint64_t tsf = ath_extend_tsf(sc, rstamp,
				ath_hal_gettsf64(sc->sc_ah));
			/*
			 * Handle ibss merge as needed; check the tsf on the
			 * frame before attempting the merge.  The 802.11 spec
			 * says the station should change it's bssid to match
			 * the oldest station with the same ssid, where oldest
			 * is determined by the tsf.  Note that hardware
			 * reconfiguration happens through callback to
			 * ath_newstate as the state machine will go from
			 * RUN -> RUN when this happens.
			 */
			if (le64toh(ni->ni_tstamp.tsf) >= tsf) {
				DPRINTF(sc, ATH_DEBUG_STATE,
				    "ibss merge, rstamp %u tsf %ju "
				    "tstamp %ju\n", rstamp, (uintmax_t)tsf,
				    (uintmax_t)ni->ni_tstamp.tsf);
				(void) ieee80211_ibss_merge(ni);
			}
		}
		break;
	}
}
コード例 #4
0
ファイル: if_athrate.c プロジェクト: jorneytu/wlan
void
ath_rate_tx_complete_11n(struct ath_softc *sc,
                         struct ath_node *an,
                         struct ath_tx_status *ts,
                         struct ath_rc_series rcs[],
                         u_int8_t ac,
                         int nframes,
                         int nbad,
                         int rts_retry_limit)
#endif
{
    int    finalTSIdx = ts->ts_rateindex;
    int    tx_status = 0, is_underrun = 0;
    struct atheros_node    *oan = ATH_NODE_ATHEROS(an);
    struct ath_vap         *avp = oan->avp->athdev_vap;

#ifdef ATH_SUPPORT_TxBF
    if (rcs[0].flags & ATH_RC_SOUNDING_FLAG) {
      /* indicate sounding sent*/ 
      ts->ts_txbfstatus |= TxBF_STATUS_Sounding_Complete;
    }
    if (oan->lastTxmcs0cnt > MCS0_80_PERCENT ){
        /* clear TxBF HW status to avoid trigger sounding*/
        ts->ts_txbfstatus &= ~(AR_TxBF_Valid_HW_Status);
    }
#endif

    if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE)
            || ts->ts_status & HAL_TXERR_FILT) {
        return;
    }

#ifdef ATH_CHAINMASK_SELECT
    if (ts->ts_rssi > 0) {
        ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi,
                             ts->ts_rssi);
    }
#endif

    /*
     * If underrun error is seen assume it as an excessive retry only if prefetch
     * trigger level have reached the max (0x3f for 5416)
     * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY times. This
     * affects how ratectrl updates PER for the failed rate.
     */
    if ((HAL_IS_TX_UNDERRUN(ts)) &&
        (ath_hal_gettxtriglevel(sc->sc_ah) >= sc->sc_rc->txTrigLevelMax)) {
        tx_status = 1;
        is_underrun = 1;
    }

    if (ts->ts_status & (HAL_TXERR_XRETRY |HAL_TXERR_FIFO))
    {
        tx_status = 1;
    }

    RcUpdate_TxBF_STATS(sc, rcs, ts);

#ifdef ATH_SUPPORT_VOWEXT
#if ATH_SUPPORT_IQUE
    oan->rcFunc[ac].rcUpdate(sc, an, ts->ts_rssi, ac,
                        finalTSIdx, tx_status, rcs, nframes , nbad,
                        (is_underrun) ? ATH_11N_TXMAXTRY:ts->ts_longretry,
                        0 ,
                        nHeadFail, nTailFail);
#else
    rcUpdate_11n(sc, an, ts->ts_rssi , ac,
                    finalTSIdx, tx_status, rcs, nframes , nbad,
                    (is_underrun) ? ATH_11N_TXMAXTRY:ts->ts_longretry,
                    0 ,
                    nHeadFail, nTailFail);
#endif
#else
#if ATH_SUPPORT_IQUE
    oan->rcFunc[ac].rcUpdate(sc, an, ts->ts_rssi, ac,
                        finalTSIdx, tx_status, rcs, nframes , nbad,
                        (is_underrun) ? ATH_11N_TXMAXTRY:ts->ts_longretry,
                        0 );
#else
    rcUpdate_11n(sc, an, ts->ts_rssi , ac,
                    finalTSIdx, tx_status, rcs, nframes , nbad,
                    (is_underrun) ? ATH_11N_TXMAXTRY:ts->ts_longretry,
                    0 );
#endif

#ifdef ATH_SUPPORT_TxBF
    if (oan->txbf_sounding_request){
        ts->ts_txbfstatus |= TxBF_STATUS_Sounding_Request;
        oan->txbf_sounding_request = 0;
    } else {
        ts->ts_txbfstatus &= ~(TxBF_STATUS_Sounding_Request);
    }
#endif
#endif
}