/*
 * 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
ieee80211_node_saveq_age(struct ieee80211_node *ni)
{
    int discard = 0;
    struct node_powersave_queue *dataq,*mgtq;
    struct ieee80211vap *vap=ni->ni_vap;

    dataq = IEEE80211_NODE_SAVEQ_DATAQ(ni); 
    mgtq  = IEEE80211_NODE_SAVEQ_MGMTQ(ni); 

    /* XXX racey but good 'nuf? */
	if ((IEEE80211_NODE_SAVEQ_QLEN(dataq) != 0) ||
	    (IEEE80211_NODE_SAVEQ_QLEN(mgtq) != 0)) {
        wbuf_t wbuf;

        IEEE80211_NODE_SAVEQ_LOCK(dataq);
        while (IEEE80211_NODE_SAVEQ_POLL(dataq, wbuf) != NULL &&
             wbuf_get_age(wbuf) < IEEE80211_INACT_WAIT) {
            struct ieee80211_tx_status ts;
            ts.ts_flags = IEEE80211_TX_ERROR;
            IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                "discard frame, age %u \n", wbuf_get_age(wbuf));

            IEEE80211_NODE_SAVEQ_DEQUEUE(dataq, wbuf);
            ieee80211_release_wbuf(ni,wbuf, &ts);
            discard++;
        }
        if (wbuf != NULL)
            wbuf_set_age(wbuf, wbuf_get_age(wbuf) - IEEE80211_INACT_WAIT);
        IEEE80211_NODE_SAVEQ_UNLOCK(dataq);

        IEEE80211_NODE_SAVEQ_LOCK(mgtq);
        while (IEEE80211_NODE_SAVEQ_POLL(mgtq, wbuf) != NULL &&
             wbuf_get_age(wbuf) < IEEE80211_INACT_WAIT) {
            struct ieee80211_tx_status ts;
            ts.ts_flags = IEEE80211_TX_ERROR;
            IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                           "discard mgt frame, age %u \n", wbuf_get_age(wbuf));

            IEEE80211_NODE_SAVEQ_DEQUEUE(mgtq, wbuf);
            ieee80211_release_wbuf(ni,wbuf, &ts);
			discard++;
		}
        if (wbuf != NULL)
            wbuf_set_age(wbuf, wbuf_get_age(wbuf) - IEEE80211_INACT_WAIT);
        IEEE80211_NODE_SAVEQ_UNLOCK(mgtq);

        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
            "discard %u frames for age \n", discard);
        IEEE80211_NODE_STAT_ADD(ni, ps_discard, discard);
    }
    if ((IEEE80211_NODE_SAVEQ_QLEN(dataq) == 0) && 
        (IEEE80211_NODE_SAVEQ_QLEN(mgtq) == 0)) {
        if (vap->iv_set_tim != NULL)
            vap->iv_set_tim(ni, 0);
    }
    return discard;
}
示例#2
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;
}
示例#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
ieee80211_node_saveq_age(struct ieee80211_node *ni)
{
    int discard = 0;
    struct node_powersave_queue *dataq,*mgtq;
    struct ieee80211vap *vap=ni->ni_vap;

#if LMAC_SUPPORT_POWERSAVE_QUEUE
    struct ieee80211com *ic = ni->ni_ic;

    ic->ic_node_pwrsaveq_age(ic, ni);
    if (ic->ic_get_lmac_pwrsaveq_len(ic, ni, 0) == 0 && vap->iv_set_tim != NULL) {
        vap->iv_set_tim(ni, 0, false);
    }

    return 0;
#endif

    dataq = IEEE80211_NODE_SAVEQ_DATAQ(ni);
    mgtq  = IEEE80211_NODE_SAVEQ_MGMTQ(ni);

    /* XXX racey but good 'nuf? */
    if ((IEEE80211_NODE_SAVEQ_QLEN(dataq) != 0) ||
            (IEEE80211_NODE_SAVEQ_QLEN(mgtq) != 0)) {
        wbuf_t wbuf;

        IEEE80211_NODE_SAVEQ_LOCK(dataq);
        while (IEEE80211_NODE_SAVEQ_POLL(dataq, wbuf) != NULL &&
                wbuf_get_age(wbuf) < IEEE80211_INACT_WAIT) {
            struct ieee80211_tx_status ts;
            ts.ts_flags = IEEE80211_TX_ERROR;
            IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                           "discard frame, age %u \n", wbuf_get_age(wbuf));

            IEEE80211_NODE_SAVEQ_DEQUEUE(dataq, wbuf);
            ieee80211_release_wbuf(ni,wbuf, &ts);
            discard++;
        }
        if (wbuf != NULL)
            wbuf_set_age(wbuf, wbuf_get_age(wbuf) - IEEE80211_INACT_WAIT);
        IEEE80211_NODE_SAVEQ_UNLOCK(dataq);

        IEEE80211_NODE_SAVEQ_LOCK(mgtq);
        while (IEEE80211_NODE_SAVEQ_POLL(mgtq, wbuf) != NULL &&
                wbuf_get_age(wbuf) < IEEE80211_INACT_WAIT) {
            struct ieee80211_tx_status ts;
            ts.ts_flags = IEEE80211_TX_ERROR;
            IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                           "discard mgt frame, age %u \n", wbuf_get_age(wbuf));

            IEEE80211_NODE_SAVEQ_DEQUEUE(mgtq, wbuf);
            ieee80211_release_wbuf(ni,wbuf, &ts);
            discard++;
        }
        if (wbuf != NULL)
            wbuf_set_age(wbuf, wbuf_get_age(wbuf) - IEEE80211_INACT_WAIT);
        IEEE80211_NODE_SAVEQ_UNLOCK(mgtq);

        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                       "discard %u frames for age \n", discard);
        IEEE80211_NODE_STAT_ADD(ni, ps_discard, discard);
    }
    if ((IEEE80211_NODE_SAVEQ_QLEN(dataq) == 0) &&
            (IEEE80211_NODE_SAVEQ_QLEN(mgtq) == 0)) {
#ifdef ATH_SWRETRY
        /* also check whether there is frame in tid q */
        if (vap->iv_set_tim != NULL && (ni->ni_ic)->ic_exist_pendingfrm_tidq(ni->ni_ic, ni) !=0)
#else
        if (vap->iv_set_tim != NULL)
#endif
            vap->iv_set_tim(ni, 0, false);
    }
    return discard;
}