FreeBSD/sys/dev/iwn/if_iwn.c
/* Process an incoming Compressed BlockAck. */
Process an incoming Compressed BlockAck.
Process an incoming Compressed BlockAck .
static void
iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
    struct iwn_rx_data *data)
{
	struct iwn_ops *ops = &sc->ops;
	struct iwn_node *wn;
	struct ieee80211_node *ni;
	struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1);
	struct iwn_tx_ring *txq;
	struct iwn_tx_data *txdata;
	struct ieee80211_tx_ampdu *tap;
	struct mbuf *m;
	uint64_t bitmap;
	uint16_t ssn;
	uint8_t tid;
	int ackfailcnt = 0, i, lastidx, qid, *res, shift;
	int tx_ok = 0, tx_err = 0;
	DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__);
	bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
	qid = le16toh(ba->qid);
	txq = &sc->txq[ba->qid];
	tap = sc->qid2tap[ba->qid];
	tid = tap->txa_tid;
	wn = (void *)tap->txa_ni;
	res = NULL;
	ssn = 0;
	if (!IEEE80211_AMPDU_RUNNING(tap)) {
		res = tap->txa_private;
		ssn = tap->txa_start & 0xfff;
	}
	for (lastidx = le16toh(ba->ssn) & 0xff; txq->read != lastidx;) {
		txdata = &txq->data[txq->read];
		bus_dmamap_sync(txq->data_dmat, txdata->map,
		    BUS_DMASYNC_POSTWRITE);
		bus_dmamap_unload(txq->data_dmat, txdata->map);
		m = txdata->m, txdata->m = NULL;
		ni = txdata->ni, txdata->ni = NULL;
		KASSERT(ni != NULL, ("no node"));
		KASSERT(m != NULL, ("no mbuf"));
		DPRINTF(sc, IWN_DEBUG_XMIT, "%s: freeing m=%p\n", __func__, m);
		ieee80211_tx_complete(ni, m, 1);
		txq->queued--;
		txq->read = (txq->read + 1) % IWN_TX_RING_COUNT;
	}
	if (txq->queued == 0 && res != NULL) {
		iwn_nic_lock(sc);
		ops->ampdu_tx_stop(sc, qid, tid, ssn);
		iwn_nic_unlock(sc);
		sc->qid2tap[qid] = NULL;
		free(res, M_DEVBUF);
		return;
	}
	if (wn->agg[tid].bitmap == 0)
		return;
	shift = wn->agg[tid].startidx - ((le16toh(ba->seq) >> 4) & 0xff);
	if (shift < 0)
		shift += 0x100;
	if (wn->agg[tid].nframes > (64 - shift))
		return;
	ni = tap->txa_ni;
	bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap;
	for (i = 0; bitmap; i++) {
		if ((bitmap & 1) == 0) {
			tx_err ++;
			ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
			    IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
		} else {
			tx_ok ++;
			ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
			    IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
		}
		bitmap >>= 1;
	}
	DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT,
	    "->%s: end; %d ok; %d err\n",__func__, tx_ok, tx_err);
}
static void iwn_rx_compressed_ba ( struct iwn_softc * sc , struct iwn_rx_desc * desc , struct iwn_rx_data * data ) { struct iwn_ops * ops = & sc -> ops ; struct iwn_node * wn ; struct ieee80211_node * ni ; struct iwn_compressed_ba * ba = ( struct iwn_compressed_ba * ) ( desc + 1 ) ; struct iwn_tx_ring * txq ; struct iwn_tx_data * txdata ; struct ieee80211_tx_ampdu * tap ; struct mbuf * m ; uint64_t bitmap ; uint16_t ssn ; uint8_t tid ; int ackfailcnt = 0 , i , lastidx , qid , * res , shift ; int tx_ok = 0 , tx_err = 0 ; DPRINTF ( sc , IWN_DEBUG_TRACE | IWN_DEBUG_XMIT , " \n " , __func__ ) ; bus_dmamap_sync ( sc -> rxq . data_dmat , data -> map , BUS_DMASYNC_POSTREAD ) ; qid = le16toh ( ba -> qid ) ; txq = & sc -> txq [ ba -> qid ] ; tap = sc -> qid2tap [ ba -> qid ] ; tid = tap -> txa_tid ; wn = ( void * ) tap -> txa_ni ; res = NULL ; ssn = 0 ; if ( ! IEEE80211_AMPDU_RUNNING ( tap ) ) { res = tap -> txa_private ; ssn = tap -> txa_start & 0xfff ; } for ( lastidx = le16toh ( ba -> ssn ) & 0xff ; txq -> read != lastidx ; ) { txdata = & txq -> data [ txq -> read ] ; bus_dmamap_sync ( txq -> data_dmat , txdata -> map , BUS_DMASYNC_POSTWRITE ) ; bus_dmamap_unload ( txq -> data_dmat , txdata -> map ) ; m = txdata -> m , txdata -> m = NULL ; ni = txdata -> ni , txdata -> ni = NULL ; KASSERT ( ni != NULL , ( " " ) ) ; KASSERT ( m != NULL , ( " " ) ) ; DPRINTF ( sc , IWN_DEBUG_XMIT , " \n " , __func__ , m ) ; ieee80211_tx_complete ( ni , m , 1 ) ; txq -> queued -- ; txq -> read = ( txq -> read + 1 ) % IWN_TX_RING_COUNT ; } if ( txq -> queued == 0 && res != NULL ) { iwn_nic_lock ( sc ) ; ops -> ampdu_tx_stop ( sc , qid , tid , ssn ) ; iwn_nic_unlock ( sc ) ; sc -> qid2tap [ qid ] = NULL ; free ( res , M_DEVBUF ) ; return ; } if ( wn -> agg [ tid ] . bitmap == 0 ) return ; shift = wn -> agg [ tid ] . startidx - ( ( le16toh ( ba -> seq ) >> 4 ) & 0xff ) ; if ( shift < 0 ) shift += 0x100 ; if ( wn -> agg [ tid ] . nframes > ( 64 - shift ) ) return ; ni = tap -> txa_ni ; bitmap = ( le64toh ( ba -> bitmap ) >> shift ) & wn -> agg [ tid ] . bitmap ; for ( i = 0 ; bitmap ; i ++ ) { if ( ( bitmap & 1 ) == 0 ) { tx_err ++ ; ieee80211_ratectl_tx_complete ( ni -> ni_vap , ni , IEEE80211_RATECTL_TX_FAILURE , & ackfailcnt , NULL ) ; } else { tx_ok ++ ; ieee80211_ratectl_tx_complete ( ni -> ni_vap , ni , IEEE80211_RATECTL_TX_SUCCESS , & ackfailcnt , NULL ) ; } bitmap >>= 1 ; } DPRINTF ( sc , IWN_DEBUG_TRACE | IWN_DEBUG_XMIT , " \n " , __func__ , tx_ok , tx_err ) ; }
Process an incoming Compressed BlockAck.
Process an incoming Compressed BlockAck .
/* Unmap and free mbuf. */ /*
	 * Walk the bitmap and calculate how many successful and failed
	 * attempts are made.
	 *
	 * Yes, the rate control code doesn't know these are A-MPDU
	 * subframes and that it's okay to fail some of these.
	 */