/* * 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; }
/* * 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; }