예제 #1
0
/*
 * Clear any frames queued on a node's power save queue.
 * The number of frames that were present is returned.
 */
int
ath_node_pwrsaveq_drain(ath_node_t node)
{
    struct ath_node *an = ATH_NODE(node);
    int qlen;
    struct ath_node_pwrsaveq *dataq,*mgtq;
    ath_wbuf_t athwbuf;

    dataq = ATH_NODE_PWRSAVEQ_DATAQ(an); 
    mgtq  = ATH_NODE_PWRSAVEQ_MGMTQ(an); 

    qlen = ATH_NODE_PWRSAVEQ_QLEN(dataq);
    qlen += ATH_NODE_PWRSAVEQ_QLEN(mgtq);

    /*
     * free all the frames.
     */
    ATH_NODE_PWRSAVEQ_LOCK(dataq);
    ATH_NODE_PWRSAVEQ_DEQUEUE(dataq, athwbuf);
    while(athwbuf) {
        ath_node_pwrsaveq_complete_athwbuf(an, athwbuf);
        ATH_NODE_PWRSAVEQ_DEQUEUE(dataq, athwbuf);
    }
    ATH_NODE_PWRSAVEQ_UNLOCK(dataq);

    ATH_NODE_PWRSAVEQ_LOCK(mgtq);
    ATH_NODE_PWRSAVEQ_DEQUEUE(mgtq, athwbuf);
    while(athwbuf) {
        ath_node_pwrsaveq_complete_athwbuf(an, athwbuf);
        ATH_NODE_PWRSAVEQ_DEQUEUE(mgtq, athwbuf);
    }
    ATH_NODE_PWRSAVEQ_UNLOCK(mgtq);

    return qlen;
}
예제 #2
0
static void
rate_cb(void *arg, struct ieee80211_node *ni)
{
	struct ath_softc *sc = arg;

	ath_rate_newassoc(sc, ATH_NODE(ni), 1);
}
예제 #3
0
/*
 * Age frames on the power save queue. The aging interval is
 * 4 times the listen interval specified by the station.  This
 * number is factored into the age calculations when the frame
 * is placed on the queue.  We store ages as time differences
 * so we can check and/or adjust only the head of the list.
 * If a frame's age exceeds the threshold then discard it.
 * The number of frames discarded is returned so the caller
 * can check if it needs to adjust the tim.
 */
int ath_node_pwrsaveq_age(ath_node_t node)
{
    struct ath_node *an = ATH_NODE(node);
    struct ath_softc *sc = an->an_sc;
    int discard = 0;
    struct ath_node_pwrsaveq *dataq,*mgtq;

    dataq = ATH_NODE_PWRSAVEQ_DATAQ(an);
    mgtq  = ATH_NODE_PWRSAVEQ_MGMTQ(an);

    if ((ATH_NODE_PWRSAVEQ_QLEN(dataq) != 0) ||
        (ATH_NODE_PWRSAVEQ_QLEN(mgtq) != 0)) {
        ath_wbuf_t athwbuf;

        for (;;) {
            ATH_NODE_PWRSAVEQ_LOCK(dataq);
            ATH_NODE_PWRSAVEQ_POLL(dataq, athwbuf);
            if((athwbuf == NULL) || (wbuf_get_age(athwbuf->wbuf) >= ATH_NODE_INACT_WAIT)) {
                if (athwbuf != NULL)
                    wbuf_set_age(athwbuf->wbuf, wbuf_get_age(athwbuf->wbuf) - ATH_NODE_INACT_WAIT);
                ATH_NODE_PWRSAVEQ_UNLOCK(dataq);
                break;
            }
            DPRINTF(sc, ATH_DEBUG_PWR_SAVE,
                    "discard data frame, age %u \n", wbuf_get_age(athwbuf->wbuf));
            ATH_NODE_PWRSAVEQ_DEQUEUE(dataq, athwbuf);
            ATH_NODE_PWRSAVEQ_UNLOCK(dataq);
            ath_node_pwrsaveq_complete_athwbuf(an, athwbuf);
            discard++;
        }

        for (;;) {
            ATH_NODE_PWRSAVEQ_LOCK(mgtq);
            ATH_NODE_PWRSAVEQ_POLL(mgtq, athwbuf);
            if((athwbuf == NULL) || (wbuf_get_age(athwbuf->wbuf) >= ATH_NODE_INACT_WAIT)) {
                if (athwbuf != NULL)
                    wbuf_set_age(athwbuf->wbuf, wbuf_get_age(athwbuf->wbuf) - ATH_NODE_INACT_WAIT);
                ATH_NODE_PWRSAVEQ_UNLOCK(mgtq);
                break;
            }
            DPRINTF(sc, ATH_DEBUG_PWR_SAVE,
                    "discard mgt frame, age %u \n", wbuf_get_age(athwbuf->wbuf));
            ATH_NODE_PWRSAVEQ_DEQUEUE(mgtq, athwbuf);
            ATH_NODE_PWRSAVEQ_UNLOCK(mgtq);
            ath_node_pwrsaveq_complete_athwbuf(an, athwbuf);
            discard++;
        }

        DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "discard %u frames for age \n", discard);
    }
    return discard;
}
예제 #4
0
/*
 * Reset the rate control state for each 802.11 state transition.
 */
void
ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state)
{
	struct ieee80211com *ic = &sc->sc_ic;

	if (state == IEEE80211_S_RUN) {
		if (ic->ic_opmode != IEEE80211_M_STA) {
			/*
			 * Sync rates for associated stations and neighbors.
			 */
			ieee80211_iterate_nodes(&ic->ic_sta, rate_cb, sc);
		}
		ath_rate_newassoc(sc, ATH_NODE(ic->ic_bss), 1);
	}
}
예제 #5
0
void ath_node_pwrsaveq_set_param(ath_node_t node, u_int8_t param, u_int32_t val)
{
    struct ath_node *an = ATH_NODE(node);

    switch((enum ath_node_pwrsaveq_param)param) {
    case ATH_NODE_PWRSAVEQ_DATA_Q_LEN:
        an->an_dataq.nsq_max_len = val;
        break;
    case ATH_NODE_PWRSAVEQ_MGMT_Q_LEN:
        an->an_mgmtq.nsq_max_len = val;
        break;
    default:
        break;
    }

}
예제 #6
0
void ath_node_pwrsaveq_get_info(ath_node_t node, void *info)
{
    struct ath_node *an = ATH_NODE(node);
    struct ath_node_pwrsaveq *dataq,*mgtq;

    dataq = ATH_NODE_PWRSAVEQ_DATAQ(an);
    mgtq  = ATH_NODE_PWRSAVEQ_MGMTQ(an);

    ATH_NODE_PWRSAVEQ_LOCK(dataq);
    ATH_NODE_PWRSAVEQ_LOCK(mgtq);
    ((ath_node_pwrsaveq_info *)info)->data_count = ATH_NODE_PWRSAVEQ_QLEN(dataq);
    ((ath_node_pwrsaveq_info *)info)->mgt_count = ATH_NODE_PWRSAVEQ_QLEN(mgtq);
    ((ath_node_pwrsaveq_info *)info)->data_len = ATH_NODE_PWRSAVEQ_BYTES(dataq);
    ((ath_node_pwrsaveq_info *)info)->mgt_len = ATH_NODE_PWRSAVEQ_BYTES(mgtq);
    ((ath_node_pwrsaveq_info *)info)->ps_frame_count = mgtq->nsq_num_ps_frames;
    ATH_NODE_PWRSAVEQ_UNLOCK(mgtq);
    ATH_NODE_PWRSAVEQ_UNLOCK(dataq);
}
예제 #7
0
static void
ath_rate_update_static_rix(struct ath_softc *sc, struct ieee80211_node *ni)
{
	struct ath_node *an = ATH_NODE(ni);
	const struct ieee80211_txparam *tp = ni->ni_txparms;
	struct sample_node *sn = ATH_NODE_SAMPLE(an);

	if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
		/*
		 * A fixed rate is to be used; ucastrate is the IEEE code
		 * for this rate (sans basic bit).  Check this against the
		 * negotiated rate set for the node.  Note the fixed rate
		 * may not be available for various reasons so we only
		 * setup the static rate index if the lookup is successful.
		 */
		sn->static_rix = ath_rate_get_static_rix(sc, ni);
	} else {
		sn->static_rix = -1;
	}
}
예제 #8
0
/*
 * Initialize the tables for a node.
 */
static void
ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
{
#define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
#define	DOT11RATE(_ix)	(rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
	struct ath_node *an = ATH_NODE(ni);
	const struct ieee80211_txparam *tp = ni->ni_txparms;
	struct sample_node *sn = ATH_NODE_SAMPLE(an);
	const HAL_RATE_TABLE *rt = sc->sc_currates;
#ifdef IEEE80211_DEBUG
	char ethstr[ETHER_ADDRSTRLEN + 1];
#endif
	int x, y, srate, rix;

	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));

	KASSERT(sc->sc_curmode < IEEE80211_MODE_MAX+2,
	    ("curmode %u", sc->sc_curmode));
	sn->sched = mrr_schedules[sc->sc_curmode];
	KASSERT(sn->sched != NULL,
	    ("no mrr schedule for mode %u", sc->sc_curmode));

        sn->static_rix = -1;
	if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
		/*
		 * A fixed rate is to be used; ucastrate is the IEEE code
		 * for this rate (sans basic bit).  Check this against the
		 * negotiated rate set for the node.  Note the fixed rate
		 * may not be available for various reasons so we only
		 * setup the static rate index if the lookup is successful.
		 * XXX handle MCS
		 */
		for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--)
			if (RATE(srate) == tp->ucastrate) {
				sn->static_rix = sc->sc_rixmap[tp->ucastrate];
				break;
			}
#ifdef IEEE80211_DEBUG
			if (sn->static_rix == -1) {
				IEEE80211_NOTE(ni->ni_vap,
				    IEEE80211_MSG_RATECTL, ni,
				    "%s: ucastrate %u not found, nrates %u",
				    __func__, tp->ucastrate,
				    ni->ni_rates.rs_nrates);
			}
#endif
	}

	/*
	 * Construct a bitmask of usable rates.  This has all
	 * negotiated rates minus those marked by the hal as
	 * to be ignored for doing rate control.
	 */
	sn->ratemask = 0;
	for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
		rix = sc->sc_rixmap[RATE(x)];
		if (rix == 0xff)
			continue;
		/* skip rates marked broken by hal */
		if (!rt->info[rix].valid)
			continue;
		KASSERT(rix < SAMPLE_MAXRATES,
		    ("rate %u has rix %d", RATE(x), rix));
		sn->ratemask |= 1<<rix;
	}
#ifdef IEEE80211_DEBUG
	if (ieee80211_msg(ni->ni_vap, IEEE80211_MSG_RATECTL)) {
		uint32_t mask;

		ieee80211_note(ni->ni_vap, "[%s] %s: size 1600 rate/tt",
		    kether_ntoa(ni->ni_macaddr, ethstr), __func__);
		for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
			if ((mask & 1) == 0)
				continue;
			kprintf(" %d/%d", DOT11RATE(rix) / 2,
			    calc_usecs_unicast_packet(sc, 1600, rix, 0,0));
		}
		kprintf("\n");
	}
예제 #9
0
static void
ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
{
	struct ath_node *an = ATH_NODE(ni);
	struct onoe_node *on = ATH_NODE_ONOE(an);
	const HAL_RATE_TABLE *rt = sc->sc_currates;
	u_int8_t rix;

	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));

	DPRINTF(sc, "%s: set xmit rate for %s to %dM\n",
	    __func__, ether_sprintf(ni->ni_macaddr),
	    ni->ni_rates.rs_nrates > 0 ?
		(ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);

	ni->ni_txrate = rate;
	/*
	 * Before associating a node has no rate set setup
	 * so we can't calculate any transmit codes to use.
	 * This is ok since we should never be sending anything
	 * but management frames and those always go at the
	 * lowest hardware rate.
	 */
	if (ni->ni_rates.rs_nrates == 0)
		goto done;
	on->on_tx_rix0 = sc->sc_rixmap[
		ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL];
	on->on_tx_rate0 = rt->info[on->on_tx_rix0].rateCode;
	
	on->on_tx_rate0sp = on->on_tx_rate0 |
		rt->info[on->on_tx_rix0].shortPreamble;
	if (sc->sc_mrretry) {
		/*
		 * Hardware supports multi-rate retry; setup two
		 * step-down retry rates and make the lowest rate
		 * be the ``last chance''.  We use 4, 2, 2, 2 tries
		 * respectively (4 is set here, the rest are fixed
		 * in the xmit routine).
		 */
		on->on_tx_try0 = 1 + 3;		/* 4 tries at rate 0 */
		if (--rate >= 0) {
			rix = sc->sc_rixmap[
				ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
			on->on_tx_rate1 = rt->info[rix].rateCode;
			on->on_tx_rate1sp = on->on_tx_rate1 |
				rt->info[rix].shortPreamble;
		} else {
			on->on_tx_rate1 = on->on_tx_rate1sp = 0;
		}
		if (--rate >= 0) {
			rix = sc->sc_rixmap[
				ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
			on->on_tx_rate2 = rt->info[rix].rateCode;
			on->on_tx_rate2sp = on->on_tx_rate2 |
				rt->info[rix].shortPreamble;
		} else {
			on->on_tx_rate2 = on->on_tx_rate2sp = 0;
		}
		if (rate > 0) {
			/* NB: only do this if we didn't already do it above */
			on->on_tx_rate3 = rt->info[0].rateCode;
			on->on_tx_rate3sp =
				on->on_tx_rate3 | rt->info[0].shortPreamble;
		} else {
			on->on_tx_rate3 = on->on_tx_rate3sp = 0;
		}
	} else {
		on->on_tx_try0 = ATH_TXMAXTRY;	/* max tries at rate 0 */
		on->on_tx_rate1 = on->on_tx_rate1sp = 0;
		on->on_tx_rate2 = on->on_tx_rate2sp = 0;
		on->on_tx_rate3 = on->on_tx_rate3sp = 0;
	}
done:
	on->on_tx_ok = on->on_tx_err = on->on_tx_retr = on->on_tx_upper = 0;
}
예제 #10
0
/* 
 * Examine and potentially adjust the transmit rate.
 */
static void
ath_rate_ctl(void *arg, struct ieee80211_node *ni)
{
	struct ath_softc *sc = arg;
	struct onoe_node *on = ATH_NODE_ONOE(ATH_NODE(ni));
	struct ieee80211_rateset *rs = &ni->ni_rates;
	int dir = 0, nrate, enough;

	/*
	 * Rate control
	 * XXX: very primitive version.
	 */
	enough = (on->on_tx_ok + on->on_tx_err >= 10);

	/* no packet reached -> down */
	if (on->on_tx_err > 0 && on->on_tx_ok == 0)
		dir = -1;

	/* all packets needs retry in average -> down */
	if (enough && on->on_tx_ok < on->on_tx_retr)
		dir = -1;

	/* no error and less than rate_raise% of packets need retry -> up */
	if (enough && on->on_tx_err == 0 &&
	    on->on_tx_retr < (on->on_tx_ok * ath_rate_raise) / 100)
		dir = 1;

	DPRINTF(sc, "%s: ok %d err %d retr %d upper %d dir %d\n",
		ether_sprintf(ni->ni_macaddr),
		on->on_tx_ok, on->on_tx_err, on->on_tx_retr,
		on->on_tx_upper, dir);

	nrate = ni->ni_txrate;
	switch (dir) {
	case 0:
		if (enough && on->on_tx_upper > 0)
			on->on_tx_upper--;
		break;
	case -1:
		if (nrate > 0) {
			nrate--;
			sc->sc_stats.ast_rate_drop++;
		}
		on->on_tx_upper = 0;
		break;
	case 1:
		/* raise rate if we hit rate_raise_threshold */
		if (++on->on_tx_upper < ath_rate_raise_threshold)
			break;
		on->on_tx_upper = 0;
		if (nrate + 1 < rs->rs_nrates) {
			nrate++;
			sc->sc_stats.ast_rate_raise++;
		}
		break;
	}

	if (nrate != ni->ni_txrate) {
		DPRINTF(sc, "%s: %dM -> %dM (%d ok, %d err, %d retr)\n",
		    __func__,
		    (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL) / 2,
		    (rs->rs_rates[nrate] & IEEE80211_RATE_VAL) / 2,
		    on->on_tx_ok, on->on_tx_err, on->on_tx_retr);
		ath_rate_update(sc, ni, nrate);
	} else if (enough)
		on->on_tx_ok = on->on_tx_err = on->on_tx_retr = 0;
}
예제 #11
0
파일: ath_ald.c 프로젝트: KHATEEBNSIT/AP
int ath_ald_collect_ni_data(ath_dev_t dev, ath_node_t an, ath_ald_t ald_data, ath_ni_ald_t ald_ni_data)
{
    u_int32_t ccf;
    u_int32_t myCcf = 0;
    u_int32_t aggrAverage = 0;
    struct ath_softc *sc = ATH_DEV_TO_SC(dev);
    struct atheros_softc  *asc = (struct atheros_softc*)sc->sc_rc;
    struct ath_node *ant = ATH_NODE(an);
    struct atheros_node *pSib;
    TX_RATE_CTRL *pRc;
    const RATE_TABLE_11N  *pRateTable = (const RATE_TABLE_11N *)asc->hwRateTable[sc->sc_curmode];

    //an = ATH_NODE(ATH_NODE_NET80211(ni)->an_sta);
    pSib = ATH_NODE_ATHEROS(ant);
    pRc = (TX_RATE_CTRL *)(pSib);

    ald_ni_data->ald_lastper = pRc->state[pRc->lastRateIndex].per;

    if(pRc->TxRateCount != 0) {
        ald_ni_data->ald_avgtxrate = pRc->TxRateInMbps / pRc->TxRateCount;
        ald_ni_data->ald_avgmax4msaggr = pRc->Max4msFrameLen / (pRc->TxRateCount * ald_data->msdu_size);
    }
    
    pRc->TxRateInMbps = 0;
    pRc->Max4msFrameLen = 0;
    pRc->TxRateCount = 0;

    if (ald_ni_data->ald_avgmax4msaggr > 32)
        ald_ni_data->ald_avgmax4msaggr = 32;

    if(sc->sc_ald.sc_ald_txairtime != 0){
        //ccf = (ald_data->msdu_size/(sc->sc_ald.sc_ald_txairtime/ald_ni_data->ald_pktnum))*8;
        ccf = ald_ni_data->ald_avgtxrate;
        myCcf = sc->sc_ald.sc_ald_pktlen*8/sc->sc_ald.sc_ald_txairtime;
        aggrAverage = sc->sc_ald.sc_ald_pktnum/sc->sc_ald.sc_ald_counter;
    }
    else {
        if(ald_ni_data->ald_avgtxrate) {
            ccf = ald_ni_data->ald_avgtxrate;
            aggrAverage = ald_ni_data->ald_avgmax4msaggr/2;
        }
        else {
            ccf = pRateTable->info[INIT_RATE_MAX_40-4].rateKbps/1000;
            aggrAverage = MAX_AGGR_LIMIT/2;
        }
    }
    if (sc->sc_ald.sc_ald_counter) {
        ald_data->ald_txbuf_used = sc->sc_ald.sc_ald_bfused/sc->sc_ald.sc_ald_counter;
    } else {
        ald_data->ald_txbuf_used = 0;
    }
    ald_data->ald_curThroughput = sc->sc_ald.sc_ald_pktnum * ald_data->msdu_size * 8 / 1000000;
    if (ald_data->ald_curThroughput < 1) {
        aggrAverage = MAX_AGGR_LIMIT/2;
    }
    
    if (ccf != 0) {
        ald_ni_data->ald_capacity = ccf;
        ald_ni_data->ald_aggr = aggrAverage;
        ald_ni_data->ald_phyerr = ald_data->phyerr_rate;
        if (ald_data->msdu_size < DEFAULT_MSDU_SIZE) {
            ald_ni_data->ald_msdusize = ALD_MSDU_SIZE;
        } else {
            ald_ni_data->ald_msdusize = ald_data->msdu_size;
        }
    }
    sc->sc_ald.sc_ald_txairtime = 0;
    sc->sc_ald.sc_ald_pktnum = 0;
    sc->sc_ald.sc_ald_pktlen = 0;
    sc->sc_ald.sc_ald_bfused = 0;
    sc->sc_ald.sc_ald_counter = 0;
    ald_ni_data->ald_txrate = 0;
    ald_ni_data->ald_max4msframelen = 0;
    ald_ni_data->ald_txcount = 0;
    ald_ni_data->ald_avgtxrate = 0;
    ald_ni_data->ald_avgmax4msaggr = 0;
    return 0;
}
예제 #12
0
/*
 * Initialize the tables for a node.
 */
static void
ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
{
#define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
	struct ieee80211com *ic = &sc->sc_ic;
	struct ath_node *an = ATH_NODE(ni);
	struct sample_node *sn = ATH_NODE_SAMPLE(an);
	const HAL_RATE_TABLE *rt = sc->sc_currates;
	int x, y, srate;

	KASSERTMSG(rt != NULL, "no rate table, mode %u", sc->sc_curmode);
        sn->static_rate_ndx = -1;
	if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
		/*
		 * A fixed rate is to be used; ic_fixed_rate is an
		 * index into the supported rate set.  Convert this
		 * to the index into the negotiated rate set for
		 * the node.  We know the rate is there because the
		 * rate set is checked when the station associates.
		 */
		const struct ieee80211_rateset *rs =
			&ic->ic_sup_rates[ic->ic_curmode];
		int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
		/* NB: the rate set is assumed sorted */
		srate = ni->ni_rates.rs_nrates - 1;
		for (; srate >= 0 && RATE(srate) != r; srate--)
			;
		KASSERTMSG(srate >= 0,
			"fixed rate %d not in rate set", ic->ic_fixed_rate);
                sn->static_rate_ndx = srate;
	}

        DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr));

	sn->num_rates = ni->ni_rates.rs_nrates;
        for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
		sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
		sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
		sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
		sn->rates[x].shortPreambleRateCode = 
			rt->info[sn->rates[x].rix].rateCode | 
			rt->info[sn->rates[x].rix].shortPreamble;

		DPRINTF(sc, " %d/%d", sn->rates[x].rate,
			calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix, 
						  0,0));
	}
	DPRINTF(sc, "%s\n", "");
	
	/* set the visible bit-rate to the lowest one available */
	ni->ni_txrate = 0;
	sn->num_rates = ni->ni_rates.rs_nrates;
	
	for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
		int size = bin_to_size(y);
		int ndx = 0;
		sn->packets_sent[y] = 0;
		sn->current_sample_ndx[y] = -1;
		sn->last_sample_ndx[y] = 0;
		
		for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
			sn->stats[y][x].successive_failures = 0;
			sn->stats[y][x].tries = 0;
			sn->stats[y][x].total_packets = 0;
			sn->stats[y][x].packets_acked = 0;
			sn->stats[y][x].last_tx = 0;
			
			sn->stats[y][x].perfect_tx_time = 
				calc_usecs_unicast_packet(sc, size, 
							  sn->rates[x].rix,
							  0, 0);
			sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time;
		}

		/* set the initial rate */
		for (ndx = sn->num_rates-1; ndx > 0; ndx--) {
			if (sn->rates[ndx].rate <= 72) {
				break;
			}
		}
		sn->current_rate[y] = ndx;
	}

	DPRINTF(sc, "%s: %s %d rates %d%sMbps (%dus)- %d%sMbps (%dus)\n",
		__func__, ether_sprintf(ni->ni_macaddr), 
		sn->num_rates,
		sn->rates[0].rate/2, sn->rates[0].rate % 0x1 ? ".5" : "",
		sn->stats[1][0].perfect_tx_time,
		sn->rates[sn->num_rates-1].rate/2,
			sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "",
		sn->stats[1][sn->num_rates-1].perfect_tx_time
	);

	ni->ni_txrate = sn->current_rate[0];
#undef RATE
}
예제 #13
0
/*
 * Initialize the tables for a node.
 */
static void
ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
{
#define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
	struct ieee80211com *ic = &sc->sc_ic;
	struct ath_node *an = ATH_NODE(ni);
	struct sample_node *sn = ATH_NODE_SAMPLE(an);
	const HAL_RATE_TABLE *rt = sc->sc_currates;
	int x, y, srate;

	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
        sn->static_rate_ndx = -1;
	if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
		/*
		 * A fixed rate is to be used; ic_fixed_rate is the
		 * IEEE code for this rate (sans basic bit).  Convert this
		 * to the index into the negotiated rate set for
		 * the node.
		 */
		/* NB: the rate set is assumed sorted */
		srate = ni->ni_rates.rs_nrates - 1;
		for (; srate >= 0 && RATE(srate) != ic->ic_fixed_rate; srate--)
			;
		/*
		 * The fixed rate may not be available due to races
		 * and mode settings.  Also orphaned nodes created in
		 * adhoc mode may not have any rate set so this lookup
		 * can fail.
		 */
		if (srate >= 0)
			sn->static_rate_ndx = srate;
	}

        DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s size 1600 rate/tt",
	    __func__, ether_sprintf(ni->ni_macaddr));

	sn->num_rates = ni->ni_rates.rs_nrates;
        for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
		sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
		sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
		if (sn->rates[x].rix == 0xff) {
			DPRINTF(sc, ATH_DEBUG_RATE,
			    "%s: ignore bogus rix at %d\n", __func__, x);
			continue;
		}
		sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
		sn->rates[x].shortPreambleRateCode = 
			rt->info[sn->rates[x].rix].rateCode | 
			rt->info[sn->rates[x].rix].shortPreamble;

		DPRINTF(sc, ATH_DEBUG_RATE, " %d/%d", sn->rates[x].rate,
		    calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix, 0,0));
	}
	DPRINTF(sc, ATH_DEBUG_RATE, "%s\n", "");
	
	/* set the visible bit-rate to the lowest one available */
	ni->ni_txrate = 0;
	sn->num_rates = ni->ni_rates.rs_nrates;
	
	for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
		int size = bin_to_size(y);
		int ndx = 0;
		sn->packets_sent[y] = 0;
		sn->current_sample_ndx[y] = -1;
		sn->last_sample_ndx[y] = 0;
		
		for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
			sn->stats[y][x].successive_failures = 0;
			sn->stats[y][x].tries = 0;
			sn->stats[y][x].total_packets = 0;
			sn->stats[y][x].packets_acked = 0;
			sn->stats[y][x].last_tx = 0;
			
			sn->stats[y][x].perfect_tx_time = 
				calc_usecs_unicast_packet(sc, size, 
							  sn->rates[x].rix,
							  0, 0);
			sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time;
		}

		/* set the initial rate */
		for (ndx = sn->num_rates-1; ndx > 0; ndx--) {
			if (sn->rates[ndx].rate <= 72) {
				break;
			}
		}
		sn->current_rate[y] = ndx;
	}

	DPRINTF(sc, ATH_DEBUG_RATE,
	    "%s: %s %d rates %d%sMbps (%dus)- %d%sMbps (%dus)\n",
	    __func__, ether_sprintf(ni->ni_macaddr), 
	    sn->num_rates,
	    sn->rates[0].rate/2, sn->rates[0].rate % 0x1 ? ".5" : "",
	    sn->stats[1][0].perfect_tx_time,
	    sn->rates[sn->num_rates-1].rate/2,
		sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "",
	    sn->stats[1][sn->num_rates-1].perfect_tx_time
	);

        if (sn->static_rate_ndx != -1)
		ni->ni_txrate = sn->static_rate_ndx;
	else
		ni->ni_txrate = sn->current_rate[0];
#undef RATE
}
예제 #14
0
/*
 * send one frme out of power save queue .
 * called in reponse to PS poll.
 * returns 1 if succesfully sends a frame. 0 other wise.
 */
int
ath_node_pwrsaveq_send(ath_node_t node, u_int8_t frame_type)
{
    struct ath_node *an = ATH_NODE(node);
    struct ath_softc *sc = an->an_sc;
    ath_wbuf_t athwbuf;
    wbuf_t wbuf = NULL;
    int qlen;
    struct ath_node_pwrsaveq *dataq, *mgtq;
    ieee80211_tx_control_t *txctl;
    struct ieee80211_frame *wh;
    u_int8_t more_frag;

    dataq = ATH_NODE_PWRSAVEQ_DATAQ(an); 
    mgtq  = ATH_NODE_PWRSAVEQ_MGMTQ(an); 

next_frag:

    ATH_NODE_PWRSAVEQ_LOCK(dataq);
    ATH_NODE_PWRSAVEQ_LOCK(mgtq);

    if (frame_type == IEEE80211_FC0_TYPE_MGT) {
        ATH_NODE_PWRSAVEQ_DEQUEUE(mgtq, athwbuf);
        if (athwbuf)
            wbuf = athwbuf->wbuf;
        if (wbuf && wbuf_is_pwrsaveframe(wbuf))  {
            /* ps frame (null (or) pspoll frame) */
            --mgtq->nsq_num_ps_frames;
        } 
    } else {
        ATH_NODE_PWRSAVEQ_DEQUEUE(dataq, athwbuf);
        if (athwbuf)
            wbuf = athwbuf->wbuf;
    }

    if (athwbuf == NULL || wbuf == NULL) {
        ATH_NODE_PWRSAVEQ_UNLOCK(mgtq);
        ATH_NODE_PWRSAVEQ_UNLOCK(dataq);
        return 0;
    }
        
    qlen = ATH_NODE_PWRSAVEQ_QLEN(dataq);
    qlen += ATH_NODE_PWRSAVEQ_QLEN(mgtq);

    ATH_NODE_PWRSAVEQ_UNLOCK(mgtq);
    ATH_NODE_PWRSAVEQ_UNLOCK(dataq);

    wh = (struct ieee80211_frame *)wbuf_header(wbuf);
    more_frag = wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG;

    /* 
     * If there are more packets, set the more packets bit
     * in the packet dispatched to the station; otherwise
     * turn off the TIM bit.
     */
    if (qlen != 0) {
        DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "send packet, %u still queued \n", qlen);
        /* 
         * encap will set more data bit.
         */
        wbuf_set_moredata(wbuf);
        if (wbuf_is_moredata(wbuf)) {
             wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
        } 
    } else {
        DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "%s", "send packet, queue empty \n");
        /* TIM bit will be set by UMAC caller */
    }

    wbuf_clear_legacy_ps(wbuf);
    txctl = &athwbuf->txctl;

    if (sc->sc_ath_ops.tx(sc, wbuf, txctl) != 0) {
        DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "%s: send error, comple the wbuf\n", __func__);
        ath_node_pwrsaveq_complete_athwbuf(an, athwbuf);
        /* process all fragment together */
        if (more_frag)
            goto next_frag;

        return 0;
    }

    if (athwbuf) {
        OS_FREE_PS(athwbuf);
    }

    /* process all fragments together */
    if (more_frag)
        goto next_frag;

    return 1;
}
예제 #15
0
/**
 * The code below assumes that we are dealing with hardware multi rate retry
 * I have no idea what will happen if you try to use this module with another
 * type of hardware. Your machine might catch fire or it might work with
 * horrible performance...
 */
static void
ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
{
    struct ath_node *an = ATH_NODE(ni);
    struct amrr_node *amn = ATH_NODE_AMRR(an);
    struct ieee80211vap *vap = ni->ni_vap;
    const HAL_RATE_TABLE *rt = sc->sc_currates;
    u_int8_t rix;

    KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));

    IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni,
                   "%s: set xmit rate to %dM", __func__,
                   ni->ni_rates.rs_nrates > 0 ?
                   (ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);

    amn->amn_rix = rate;
    /*
     * Before associating a node has no rate set setup
     * so we can't calculate any transmit codes to use.
     * This is ok since we should never be sending anything
     * but management frames and those always go at the
     * lowest hardware rate.
     */
    if (ni->ni_rates.rs_nrates > 0) {
        ni->ni_txrate = ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL;
        amn->amn_tx_rix0 = sc->sc_rixmap[ni->ni_txrate];
        amn->amn_tx_rate0 = rt->info[amn->amn_tx_rix0].rateCode;
        amn->amn_tx_rate0sp = amn->amn_tx_rate0 |
                              rt->info[amn->amn_tx_rix0].shortPreamble;
        if (sc->sc_mrretry) {
            amn->amn_tx_try0 = 1;
            amn->amn_tx_try1 = 1;
            amn->amn_tx_try2 = 1;
            amn->amn_tx_try3 = 1;
            if (--rate >= 0) {
                rix = sc->sc_rixmap[
                          ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
                amn->amn_tx_rate1 = rt->info[rix].rateCode;
                amn->amn_tx_rate1sp = amn->amn_tx_rate1 |
                                      rt->info[rix].shortPreamble;
            } else {
                amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
            }
            if (--rate >= 0) {
                rix = sc->sc_rixmap[
                          ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
                amn->amn_tx_rate2 = rt->info[rix].rateCode;
                amn->amn_tx_rate2sp = amn->amn_tx_rate2 |
                                      rt->info[rix].shortPreamble;
            } else {
                amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
            }
            if (rate > 0) {
                /* NB: only do this if we didn't already do it above */
                amn->amn_tx_rate3 = rt->info[0].rateCode;
                amn->amn_tx_rate3sp =
                    amn->amn_tx_rate3 | rt->info[0].shortPreamble;
            } else {
                amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
            }
        } else {
            amn->amn_tx_try0 = ATH_TXMAXTRY;
            /* theorically, these statements are useless because
             *  the code which uses them tests for an_tx_try0 == ATH_TXMAXTRY
             */
            amn->amn_tx_try1 = 0;
            amn->amn_tx_try2 = 0;
            amn->amn_tx_try3 = 0;
            amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
            amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
            amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
        }
    }
    node_reset(amn);

    amn->amn_interval = ath_rateinterval;
    if (vap->iv_opmode == IEEE80211_M_STA)
        amn->amn_interval /= 2;
    amn->amn_interval = (amn->amn_interval * hz) / 1000;
}
예제 #16
0
/*
 * Initialize the tables for a node.
 */
static void
ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
{
#define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
#define	DOT11RATE(_ix)	(rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
#define	MCS(_ix)	(ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
	struct ath_node *an = ATH_NODE(ni);
	struct sample_node *sn = ATH_NODE_SAMPLE(an);
	const HAL_RATE_TABLE *rt = sc->sc_currates;
	int x, y, rix;

	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));

	KASSERT(sc->sc_curmode < IEEE80211_MODE_MAX+2,
	    ("curmode %u", sc->sc_curmode));
	sn->sched = mrr_schedules[sc->sc_curmode];
	KASSERT(sn->sched != NULL,
	    ("no mrr schedule for mode %u", sc->sc_curmode));

        sn->static_rix = -1;
	ath_rate_update_static_rix(sc, ni);

	/*
	 * Construct a bitmask of usable rates.  This has all
	 * negotiated rates minus those marked by the hal as
	 * to be ignored for doing rate control.
	 */
	sn->ratemask = 0;
	/* MCS rates */
	if (ni->ni_flags & IEEE80211_NODE_HT) {
		for (x = 0; x < ni->ni_htrates.rs_nrates; x++) {
			rix = sc->sc_rixmap[MCS(x)];
			if (rix == 0xff)
				continue;
			/* skip rates marked broken by hal */
			if (!rt->info[rix].valid)
				continue;
			KASSERT(rix < SAMPLE_MAXRATES,
			    ("mcs %u has rix %d", MCS(x), rix));
			sn->ratemask |= 1<<rix;
		}
	}

	/* Legacy rates */
	for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
		rix = sc->sc_rixmap[RATE(x)];
		if (rix == 0xff)
			continue;
		/* skip rates marked broken by hal */
		if (!rt->info[rix].valid)
			continue;
		KASSERT(rix < SAMPLE_MAXRATES,
		    ("rate %u has rix %d", RATE(x), rix));
		sn->ratemask |= 1<<rix;
	}
#ifdef IEEE80211_DEBUG
	if (ieee80211_msg(ni->ni_vap, IEEE80211_MSG_RATECTL)) {
		uint32_t mask;

		ieee80211_note(ni->ni_vap, "[%6D] %s: size 1600 rate/tt",
		    ni->ni_macaddr, ":", __func__);
		for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
			if ((mask & 1) == 0)
				continue;
			printf(" %d %s/%d", dot11rate(rt, rix), dot11rate_label(rt, rix),
			    calc_usecs_unicast_packet(sc, 1600, rix, 0,0,
			        (ni->ni_chw == 40)));
		}
		printf("\n");
	}
예제 #17
0
/*
 * node saveq flush.
 */
void
ath_node_pwrsaveq_flush(ath_node_t node)
{
    struct ath_node *an = ATH_NODE(node);
    struct ath_softc *sc = an->an_sc;
    ath_wbuf_t athwbuf;
    wbuf_t wbuf;
    struct ath_node_pwrsaveq *dataq,*mgtq;
    int dqlen, mqlen;
    ieee80211_tx_control_t *txctl;

    dataq = ATH_NODE_PWRSAVEQ_DATAQ(an); 
    mgtq  = ATH_NODE_PWRSAVEQ_MGMTQ(an); 

    /* XXX if no stations in ps mode, flush mc frames */
    dqlen = ATH_NODE_PWRSAVEQ_QLEN(dataq);

    /*
     * Flush queued mgmt frames.
     */
    ATH_NODE_PWRSAVEQ_LOCK(mgtq);
    if (ATH_NODE_PWRSAVEQ_QLEN(mgtq) != 0) {
        DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "flush mgt ps queue, %u packets queued \n",
                                         ATH_NODE_PWRSAVEQ_QLEN(mgtq));
        for (;;) {

            ATH_NODE_PWRSAVEQ_DEQUEUE(mgtq, athwbuf);
            if (athwbuf == NULL)
                break;
            wbuf = athwbuf->wbuf;
            ASSERT(wbuf);
            mqlen = ATH_NODE_PWRSAVEQ_QLEN(mgtq);
            DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "sendmgmt ps queue, %u packets remaining \n", mqlen);
            /*
             * For a Station node (non bss node) If this is the last packet, turn off the TIM bit,
             * Set the PWR_SAV bit on every frame but the last one
             * to allow encap to test for
             * adding more MORE_DATA bit to wh.
             */
            if (mqlen || dqlen) {
                wbuf_set_moredata(wbuf);
                if (wbuf_is_moredata(wbuf)) {
                    struct ieee80211_frame *wh = (struct ieee80211_frame *)wbuf_header(wbuf);
                    wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
                } 
            }

            wbuf_clear_legacy_ps(wbuf);
            txctl = &athwbuf->txctl;

            if (sc->sc_ath_ops.tx(sc, wbuf, txctl) != 0) {
                DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "%s: send error, comple the wbuf\n", __func__);
                ath_node_pwrsaveq_complete_athwbuf(an, athwbuf);
            } else {
                if (athwbuf) {
                    OS_FREE_PS(athwbuf);
                }
            }
        }
    }
    mgtq->nsq_num_ps_frames = 0;
    ATH_NODE_PWRSAVEQ_UNLOCK(mgtq);

    /*
     * Flush queued unicast frames.
     */
    ATH_NODE_PWRSAVEQ_LOCK(dataq);
    if (ATH_NODE_PWRSAVEQ_QLEN(dataq) != 0) {
        DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "flush data ps queue, %u packets queued \n",
            ATH_NODE_PWRSAVEQ_QLEN(dataq));
        for (;;) {

            ATH_NODE_PWRSAVEQ_DEQUEUE(dataq, athwbuf);
            if (athwbuf == NULL)
                break;
            wbuf = athwbuf->wbuf;
            ASSERT(wbuf);
            dqlen = ATH_NODE_PWRSAVEQ_QLEN(dataq);
            DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "senddata ps queue, %u packets remaining \n", dqlen);
            /*
             * For a Station node (non bss node) If this is the last packet, turn off the TIM bit,
             * Set the PWR_SAV bit on every frame but the last one
             * to allow encap to test for
             * adding more MORE_DATA bit to wh.
             */
            if (dqlen) {
                wbuf_set_moredata(wbuf);
                if (wbuf_is_moredata(wbuf)) {
                    struct ieee80211_frame *wh = (struct ieee80211_frame *)wbuf_header(wbuf);
                    wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
                } 
            }
            
            wbuf_clear_legacy_ps(wbuf);
            txctl = &athwbuf->txctl;

            if (sc->sc_ath_ops.tx(sc, wbuf, txctl) != 0) {
                DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "%s: send error, comple the wbuf\n", __func__);
                ath_node_pwrsaveq_complete_athwbuf(an, athwbuf);
            } else {
                if (athwbuf) {
                    OS_FREE_PS(athwbuf);
                }
            }
        }
    }
    ATH_NODE_PWRSAVEQ_UNLOCK(dataq);

    /* TIM will be set by UMAC caller */
}
예제 #18
0
/*
 * Save an outbound packet for a node in power-save sleep state.
 * The new packet is placed on the node's saved queue, and the TIM
 * is changed by UMAC caller.
 */
void
ath_node_pwrsaveq_queue(ath_node_t node, ath_wbuf_t athwbuf, u_int8_t frame_type)
{
    struct ath_node *an = ATH_NODE(node);
    struct ath_softc *sc = an->an_sc;
    int qlen, age;
    struct ath_node_pwrsaveq *dataq,*mgtq,*psq;

    dataq = ATH_NODE_PWRSAVEQ_DATAQ(an);
    mgtq  = ATH_NODE_PWRSAVEQ_MGMTQ(an);


    ATH_NODE_PWRSAVEQ_LOCK(dataq);
    ATH_NODE_PWRSAVEQ_LOCK(mgtq);

    if (frame_type == IEEE80211_FC0_TYPE_MGT) {
        psq = mgtq;
    } else {
        psq = dataq;
    }

    if (ATH_NODE_PWRSAVEQ_FULL(psq)) {
        ATH_NODE_PWRSAVEQ_UNLOCK(mgtq);
        ATH_NODE_PWRSAVEQ_UNLOCK(dataq);
        DPRINTF(sc, ATH_DEBUG_ANY,
                "%s pwr save q: overflow, drops (size %d) \n",
                (psq == dataq) ? "data" : "mgt",
                ATH_NODE_PWRSAVEQ_MAX_LEN);

        ath_node_pwrsaveq_complete_athwbuf(an, athwbuf);

        return;

    }

    /*
     * special handling of frames with PS = 1.
     */
    ath_node_pwrsaveq_handle_ps_frames(an, athwbuf, frame_type);


    /* By default use the 4 * beacon intval as the aging time */
    age = (ATH_NODE_AGE_INTVAL << 2) >> 10; /* TU -> secs */

    /*
     * Note: our aging algorithm is not working well. In fact, due to the long interval
     * when the aging algorithm is called (ATH_NODE_INACT_WAIT is 150 secs), we depend on
     * the associated station node to be disassociated to clear its stale frames. However,
     * as a temporary fix, I will make sure that the age is at least greater than 
     * ATH_NODE_INACT_WAIT. Otherwise, we will discard all frames in ps queue even though
     * it is just queued.
    */
    if (age < ATH_NODE_INACT_WAIT) {
        DPRINTF(sc, ATH_DEBUG_PWR_SAVE,
                "%s Note: increased age from %d to %d secs.\n",
                __func__, age, ATH_NODE_INACT_WAIT);
        age = ATH_NODE_INACT_WAIT;
    }

    ATH_NODE_PWRSAVEQ_ENQUEUE(psq, athwbuf, qlen, age);

    /*
     * calculate the combined queue length of management and data queues.
     */
    qlen = ATH_NODE_PWRSAVEQ_QLEN(dataq);
    qlen += ATH_NODE_PWRSAVEQ_QLEN(mgtq);

    ATH_NODE_PWRSAVEQ_UNLOCK(mgtq);
    ATH_NODE_PWRSAVEQ_UNLOCK(dataq);

    DPRINTF(sc, ATH_DEBUG_PWR_SAVE,
            "%s pwr queue:save frame, %u now queued \n",
            (psq == dataq) ? "data" : "mgt" ,qlen);
    /* TIM bit will be set by UMAC caller */
}
예제 #19
0
/* 
 * Examine and potentially adjust the transmit rate.
 */
static void
ath_rate_ctl(void *arg, struct ieee80211_node *ni)
{
	struct ath_softc *sc = arg;
	struct amrr_node *amn = ATH_NODE_AMRR(ATH_NODE (ni));
	int old_rate;

#define is_success(amn) \
(amn->amn_tx_try1_cnt  < (amn->amn_tx_try0_cnt/10))
#define is_enough(amn) \
(amn->amn_tx_try0_cnt > 10)
#define is_failure(amn) \
(amn->amn_tx_try1_cnt > (amn->amn_tx_try0_cnt/3))
#define is_max_rate(ni) \
((ni->ni_txrate + 1) >= ni->ni_rates.rs_nrates)
#define is_min_rate(ni) \
(ni->ni_txrate == 0)

	old_rate = ni->ni_txrate;
  
  	DPRINTF (sc, "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d\n",
		 amn->amn_tx_try0_cnt,
		 amn->amn_tx_try1_cnt,
		 amn->amn_tx_try2_cnt,
		 amn->amn_tx_try3_cnt,
		 amn->amn_success_threshold);
  	if (is_success (amn) && is_enough (amn)) {
		amn->amn_success++;
		if (amn->amn_success == amn->amn_success_threshold &&
  		    !is_max_rate (ni)) {
  			amn->amn_recovery = 1;
  			amn->amn_success = 0;
  			ni->ni_txrate++;
			DPRINTF (sc, "increase rate to %d\n", ni->ni_txrate);
  		} else {
			amn->amn_recovery = 0;
		}
  	} else if (is_failure (amn)) {
  		amn->amn_success = 0;
  		if (!is_min_rate (ni)) {
  			if (amn->amn_recovery) {
  				/* recovery failure. */
  				amn->amn_success_threshold *= 2;
  				amn->amn_success_threshold = min (amn->amn_success_threshold,
								  (u_int)ath_rate_max_success_threshold);
 				DPRINTF (sc, "decrease rate recovery thr: %d\n", amn->amn_success_threshold);
  			} else {
  				/* simple failure. */
 				amn->amn_success_threshold = ath_rate_min_success_threshold;
 				DPRINTF (sc, "decrease rate normal thr: %d\n", amn->amn_success_threshold);
  			}
			amn->amn_recovery = 0;
  			ni->ni_txrate--;
   		} else {
			amn->amn_recovery = 0;
		}

   	}
	if (is_enough (amn) || old_rate != ni->ni_txrate) {
		/* reset counters. */
		amn->amn_tx_try0_cnt = 0;
		amn->amn_tx_try1_cnt = 0;
		amn->amn_tx_try2_cnt = 0;
		amn->amn_tx_try3_cnt = 0;
		amn->amn_tx_failure_cnt = 0;
	}
	if (old_rate != ni->ni_txrate) {
		ath_rate_update(sc, ni, ni->ni_txrate);
	}
}
예제 #20
0
/*
 * Examine and potentially adjust the transmit rate.
 */
static void
ath_rate_ctl(void *arg, struct ieee80211_node *ni)
{
    struct ath_softc *sc = arg;
    struct amrr_node *amn = ATH_NODE_AMRR(ATH_NODE (ni));
    int rix;

#define is_success(amn) \
(amn->amn_tx_try1_cnt  < (amn->amn_tx_try0_cnt/10))
#define is_enough(amn) \
(amn->amn_tx_try0_cnt > 10)
#define is_failure(amn) \
(amn->amn_tx_try1_cnt > (amn->amn_tx_try0_cnt/3))

    rix = amn->amn_rix;

    IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
                   "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d",
                   amn->amn_tx_try0_cnt, amn->amn_tx_try1_cnt, amn->amn_tx_try2_cnt,
                   amn->amn_tx_try3_cnt, amn->amn_success_threshold);
    if (is_success (amn) && is_enough (amn)) {
        amn->amn_success++;
        if (amn->amn_success == amn->amn_success_threshold &&
                rix + 1 < ni->ni_rates.rs_nrates) {
            amn->amn_recovery = 1;
            amn->amn_success = 0;
            rix++;
            IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
                           "increase rate to %d", rix);
        } else {
            amn->amn_recovery = 0;
        }
    } else if (is_failure (amn)) {
        amn->amn_success = 0;
        if (rix > 0) {
            if (amn->amn_recovery) {
                /* recovery failure. */
                amn->amn_success_threshold *= 2;
                amn->amn_success_threshold = min (amn->amn_success_threshold,
                                                  (u_int)ath_rate_max_success_threshold);
                IEEE80211_NOTE(ni->ni_vap,
                               IEEE80211_MSG_RATECTL, ni,
                               "decrease rate recovery thr: %d",
                               amn->amn_success_threshold);
            } else {
                /* simple failure. */
                amn->amn_success_threshold = ath_rate_min_success_threshold;
                IEEE80211_NOTE(ni->ni_vap,
                               IEEE80211_MSG_RATECTL, ni,
                               "decrease rate normal thr: %d",
                               amn->amn_success_threshold);
            }
            amn->amn_recovery = 0;
            rix--;
        } else {
            amn->amn_recovery = 0;
        }

    }
    if (is_enough (amn) || rix != amn->amn_rix) {
        /* reset counters. */
        amn->amn_tx_try0_cnt = 0;
        amn->amn_tx_try1_cnt = 0;
        amn->amn_tx_try2_cnt = 0;
        amn->amn_tx_try3_cnt = 0;
        amn->amn_tx_failure_cnt = 0;
    }
    if (rix != amn->amn_rix) {
        ath_rate_update(sc, ni, rix);
    }
}
예제 #21
0
/**
 * The code below assumes that we are dealing with hardware multi rate retry
 * I have no idea what will happen if you try to use this module with another
 * type of hardware. Your machine might catch fire or it might work with
 * horrible performance...
 */
static void
ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
{
	struct ath_node *an = ATH_NODE(ni);
	struct amrr_node *amn = ATH_NODE_AMRR(an);
	const HAL_RATE_TABLE *rt = sc->sc_currates;
	u_int8_t rix;

	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));

	DPRINTF(sc, "%s: set xmit rate for %s to %dM\n",
	    __func__, ether_sprintf(ni->ni_macaddr),
	    ni->ni_rates.rs_nrates > 0 ?
		(ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);

	ni->ni_txrate = rate;
	/* XXX management/control frames always go at the lowest speed */
	an->an_tx_mgtrate = rt->info[0].rateCode;
	an->an_tx_mgtratesp = an->an_tx_mgtrate | rt->info[0].shortPreamble;
	/*
	 * Before associating a node has no rate set setup
	 * so we can't calculate any transmit codes to use.
	 * This is ok since we should never be sending anything
	 * but management frames and those always go at the
	 * lowest hardware rate.
	 */
	if (ni->ni_rates.rs_nrates > 0) {
		amn->amn_tx_rix0 = sc->sc_rixmap[
					       ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL];
		amn->amn_tx_rate0 = rt->info[amn->amn_tx_rix0].rateCode;
		amn->amn_tx_rate0sp = amn->amn_tx_rate0 |
			rt->info[amn->amn_tx_rix0].shortPreamble;
		if (sc->sc_mrretry) {
			amn->amn_tx_try0 = 1;
			amn->amn_tx_try1 = 1;
			amn->amn_tx_try2 = 1;
			amn->amn_tx_try3 = 1;
			if (--rate >= 0) {
				rix = sc->sc_rixmap[
						    ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
				amn->amn_tx_rate1 = rt->info[rix].rateCode;
				amn->amn_tx_rate1sp = amn->amn_tx_rate1 |
					rt->info[rix].shortPreamble;
			} else {
				amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
			}
			if (--rate >= 0) {
				rix = sc->sc_rixmap[
						    ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
				amn->amn_tx_rate2 = rt->info[rix].rateCode;
				amn->amn_tx_rate2sp = amn->amn_tx_rate2 |
					rt->info[rix].shortPreamble;
			} else {
				amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
			}
			if (rate > 0) {
				/* NB: only do this if we didn't already do it above */
				amn->amn_tx_rate3 = rt->info[0].rateCode;
				amn->amn_tx_rate3sp =
					an->an_tx_mgtrate | rt->info[0].shortPreamble;
			} else {
				amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
			}
		} else {
			amn->amn_tx_try0 = ATH_TXMAXTRY;
			/* theorically, these statements are useless because
			 *  the code which uses them tests for an_tx_try0 == ATH_TXMAXTRY
			 */
			amn->amn_tx_try1 = 0;
			amn->amn_tx_try2 = 0;
			amn->amn_tx_try3 = 0;
			amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
			amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
			amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
		}
	}
	node_reset (amn);
}