Beispiel #1
0
static void ath_node_pwrsaveq_handle_ps_frames(struct ath_node *an,
                                            ath_wbuf_t athwbuf, u_int8_t frame_type)
{
#if ATH_DEBUG
    struct ath_softc *sc = an->an_sc;
#endif
    struct ath_node_pwrsaveq *mgtq;
    ath_wbuf_t tmpathwbuf;

    mgtq  = ATH_NODE_PWRSAVEQ_MGMTQ(an); 

    if (wbuf_is_pwrsaveframe(athwbuf->wbuf))  {
        /* ps frame (null (or) pspoll frame) */
        ++mgtq->nsq_num_ps_frames;
    } else {
        /* non ps frame*/
        if (mgtq->nsq_num_ps_frames) {
            struct ath_node_pwrsaveq *tmpq, temp_q;
            tmpq = &temp_q;

            ATH_NODE_PWRSAVEQ_INIT(tmpq);
            /*
             * go through the mgt queue and dump the frames with PS=1(pspoll,null).
             * accummulate the remaining frames into temp queue.
             */
            for (;;) {
                ATH_NODE_PWRSAVEQ_DEQUEUE(mgtq, tmpathwbuf);
                if (tmpathwbuf == NULL) {
                    break;
                }
                if (wbuf_is_pwrsaveframe(tmpathwbuf->wbuf))  {
                    /* complete the wbuf */
                    DPRINTF(sc, ATH_DEBUG_PWR_SAVE, "%s: send error, comple the wbuf\n", __func__);
                    ath_node_pwrsaveq_complete_athwbuf(an, tmpathwbuf);
                } else {
                    ATH_NODE_PWRSAVEQ_ADD(tmpq,tmpathwbuf);
                }
            }

            mgtq->nsq_num_ps_frames = 0;
            /*
             * move all the frames from temp queue to mgmt queue.
             */
            for (;;) {
                ATH_NODE_PWRSAVEQ_DEQUEUE(tmpq, tmpathwbuf);
                if (tmpathwbuf == NULL) {
                    break;
                }
                ATH_NODE_PWRSAVEQ_ADD(mgtq, tmpathwbuf);
            }
        }
    }
}
Beispiel #2
0
static void ieee80211_node_saveq_handle_ps_frames(struct ieee80211_node *ni, wbuf_t wbuf, u_int8_t frame_type)
{
    struct node_powersave_queue *mgtq;
    wbuf_t tmpwbuf;

    mgtq  = IEEE80211_NODE_SAVEQ_MGMTQ(ni);

    if (wbuf_is_pwrsaveframe(wbuf))  {
        /* ps frame (null (or) pspoll frame) */
        ++mgtq->nsq_num_ps_frames;
    } else {
        /* non ps frame*/
        if (mgtq->nsq_num_ps_frames) {
            struct ieee80211_tx_status ts;
            struct node_powersave_queue *tmpq, temp_q;
            tmpq = &temp_q;

            IEEE80211_NODE_SAVEQ_INIT(tmpq);
            /*
             * go through the mgt queue and dump the frames with PS=1(pspoll,null).
             * accummulate the remaining frames into temp queue.
             */
            for (;;) {
                IEEE80211_NODE_SAVEQ_DEQUEUE(mgtq, tmpwbuf);
                if (tmpwbuf == NULL) {
                    break;
                }
                if (wbuf_is_pwrsaveframe(tmpwbuf))  {
                    IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ANY, ni,
                                   "%s pwr save q: complete the PS frame with error \n", __func__);
                    ts.ts_flags = IEEE80211_TX_ERROR;
                    ieee80211_release_wbuf(ni,tmpwbuf, &ts);
                } else {
                    IEEE80211_NODE_SAVEQ_ADD(tmpq,tmpwbuf);
                }
            }

            mgtq->nsq_num_ps_frames = 0;
            /*
             * move all the frames from temp queue to mgmt queue.
             */
            for (;;) {
                IEEE80211_NODE_SAVEQ_DEQUEUE(tmpq, tmpwbuf);
                if (tmpwbuf == NULL) {
                    break;
                }
                IEEE80211_NODE_SAVEQ_ADD(mgtq, tmpwbuf);
            }
        }
    }

}
Beispiel #3
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;
}
Beispiel #4
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
ieee80211_node_saveq_send(struct ieee80211_node *ni, int frame_type)
{
    struct ieee80211vap *vap = ni->ni_vap;
    wbuf_t wbuf;
    int qlen;
    struct node_powersave_queue *dataq,*mgtq;

    /*
     * do not send any frames if the vap is paused.
     * wait until the vap is unpaused.
     */
    if (ieee80211_vap_is_paused(vap)) return 0;

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

    IEEE80211_NODE_SAVEQ_LOCK(dataq);
    IEEE80211_NODE_SAVEQ_LOCK(mgtq);

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

    if (wbuf == NULL) {
        IEEE80211_NODE_SAVEQ_UNLOCK(mgtq);
        IEEE80211_NODE_SAVEQ_UNLOCK(dataq);
        return 0;
    }

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

    IEEE80211_NODE_SAVEQ_UNLOCK(mgtq);
    IEEE80211_NODE_SAVEQ_UNLOCK(dataq);
    /*
     * 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) {
        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                       "send packet, %u still queued \n", qlen);
        /*
         * encap will set more data bit.
         */
        wbuf_set_moredata(wbuf);
    } else {
        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                       "%s", "send packet, queue empty \n");
#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);
    }

    if (frame_type == IEEE80211_FC0_TYPE_MGT) {
        /* send the management frame down to the ath  */
        ieee80211_send_mgmt(vap,ni,wbuf,true);
    } else {
        /* send the data down to the ath  */
        ieee80211_send_wbuf(vap,ni,wbuf);
    }

    return 1;

}