From owner-p4-projects@FreeBSD.ORG Mon Mar 3 23:44:40 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id B29F41065674; Mon, 3 Mar 2008 23:44:40 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 72AA2106566B for ; Mon, 3 Mar 2008 23:44:40 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 4D1EA8FC2E for ; Mon, 3 Mar 2008 23:44:40 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m23Nie4I012136 for ; Mon, 3 Mar 2008 23:44:40 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m23NieOD012134 for perforce@freebsd.org; Mon, 3 Mar 2008 23:44:40 GMT (envelope-from sam@freebsd.org) Date: Mon, 3 Mar 2008 23:44:40 GMT Message-Id: <200803032344.m23NieOD012134@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Cc: Subject: PERFORCE change 136772 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Mar 2008 23:44:41 -0000 http://perforce.freebsd.org/chv.cgi?CH=136772 Change 136772 by sam@sam_ebb on 2008/03/03 23:44:02 Fix power save mcast frame handling: o mark per-vap mcastq w/ the proper qnum so it's handled correctly by ath_tx_handoff o mark frames with MORE_DATA as they are queued; this can result in 1 frame being wrongly marked in very pathological cases but is hard to avoid unless we want to calculate the air time coverage for q'd frames to figure out where the hardware will cutoff our bursting; in the case of a frame going out wrongly marked with MORE_DATA this should just result in PS stations staying awake for the remainder of the beacon interval (or less depending on their implementation) Affected files ... .. //depot/projects/vap/sys/dev/ath/if_ath.c#38 edit .. //depot/projects/vap/sys/dev/ath/if_athvar.h#18 edit Differences ... ==== //depot/projects/vap/sys/dev/ath/if_ath.c#38 (text+ko) ==== @@ -906,8 +906,7 @@ */ sc->sc_stagbeacons = 1; } - STAILQ_INIT(&avp->av_mcastq.axq_q); - ATH_TXQ_LOCK_INIT(sc, &avp->av_mcastq); + ath_txq_init(sc, &avp->av_mcastq, ATH_TXQ_SWQ); } ic->ic_opmode = ic_opmode; @@ -4407,8 +4406,8 @@ * to avoid possible races. */ ATH_TXQ_LOCK(txq); - ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); if (txq->axq_qnum != ATH_TXQ_SWQ) { + ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); if (txq->axq_link == NULL) { ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); DPRINTF(sc, ATH_DEBUG_XMIT, @@ -4425,8 +4424,20 @@ txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; ath_hal_txstart(ah, txq->axq_qnum); } else { - if (txq->axq_link != NULL) + if (txq->axq_link != NULL) { + struct ath_buf *last = ATH_TXQ_LAST(txq); + struct ieee80211_frame *wh; + + /* mark previous frame */ + wh = mtod(last->bf_m, struct ieee80211_frame *); + wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA; + bus_dmamap_sync(sc->sc_dmat, last->bf_dmamap, + BUS_DMASYNC_PREWRITE); + + /* link descriptor */ *txq->axq_link = bf->bf_daddr; + } + ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; } ATH_TXQ_UNLOCK(txq); @@ -4620,10 +4631,8 @@ * queue (to prevent out of order delivery) multicast * frames must be buffered until after the beacon. */ - if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth)) { + if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth)) txq = &avp->av_mcastq; - /* XXX? more bit in 802.11 frame header */ - } /* * Calculate miscellaneous flags. ==== //depot/projects/vap/sys/dev/ath/if_athvar.h#18 (text+ko) ==== @@ -180,6 +180,10 @@ STAILQ_REMOVE_HEAD(&(_tq)->axq_q, _field); \ (_tq)->axq_depth--; \ } while (0) +/* NB: this does not do the "head empty check" that STAILQ_LAST does */ +#define ATH_TXQ_LAST(_tq) \ + ((struct ath_buf *)(void *) \ + ((char *)((_tq)->axq_q.stqh_last) - __offsetof(struct ath_buf, bf_list))) struct ath_vap { struct ieee80211vap av_vap; /* base class */