1218065Sadrian/*-
2218065Sadrian * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3218065Sadrian * All rights reserved.
4218065Sadrian *
5218065Sadrian * Redistribution and use in source and binary forms, with or without
6218065Sadrian * modification, are permitted provided that the following conditions
7218065Sadrian * are met:
8218065Sadrian * 1. Redistributions of source code must retain the above copyright
9218065Sadrian *    notice, this list of conditions and the following disclaimer,
10218065Sadrian *    without modification.
11218065Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12218065Sadrian *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13218065Sadrian *    redistribution must be conditioned upon including a substantially
14218065Sadrian *    similar Disclaimer requirement for further binary redistribution.
15218065Sadrian *
16218065Sadrian * NO WARRANTY
17218065Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18218065Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19218065Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20218065Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21218065Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22218065Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23218065Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24218065Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25218065Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26218065Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27218065Sadrian * THE POSSIBILITY OF SUCH DAMAGES.
28218065Sadrian */
29218065Sadrian
30218065Sadrian#include <sys/cdefs.h>
31218065Sadrian__FBSDID("$FreeBSD$");
32218065Sadrian
33218065Sadrian/*
34218065Sadrian * Driver for the Atheros Wireless LAN controller.
35218065Sadrian *
36218065Sadrian * This software is derived from work of Atsushi Onoe; his contribution
37218065Sadrian * is greatly appreciated.
38218065Sadrian */
39218065Sadrian
40218065Sadrian#include "opt_inet.h"
41218065Sadrian#include "opt_ath.h"
42218065Sadrian#include "opt_wlan.h"
43218065Sadrian
44218065Sadrian#include <sys/param.h>
45218065Sadrian#include <sys/systm.h>
46218065Sadrian#include <sys/sysctl.h>
47218065Sadrian#include <sys/mbuf.h>
48218065Sadrian#include <sys/malloc.h>
49218065Sadrian#include <sys/lock.h>
50218065Sadrian#include <sys/mutex.h>
51218065Sadrian#include <sys/kernel.h>
52218065Sadrian#include <sys/socket.h>
53218065Sadrian#include <sys/sockio.h>
54218065Sadrian#include <sys/errno.h>
55218065Sadrian#include <sys/callout.h>
56218065Sadrian#include <sys/bus.h>
57218065Sadrian#include <sys/endian.h>
58218065Sadrian#include <sys/kthread.h>
59218065Sadrian#include <sys/taskqueue.h>
60218065Sadrian#include <sys/priv.h>
61218065Sadrian
62218065Sadrian#include <machine/bus.h>
63218065Sadrian
64218065Sadrian#include <net/if.h>
65218065Sadrian#include <net/if_dl.h>
66218065Sadrian#include <net/if_media.h>
67218065Sadrian#include <net/if_types.h>
68218065Sadrian#include <net/if_arp.h>
69218065Sadrian#include <net/ethernet.h>
70218065Sadrian#include <net/if_llc.h>
71218065Sadrian
72218065Sadrian#include <net80211/ieee80211_var.h>
73218065Sadrian#include <net80211/ieee80211_regdomain.h>
74218065Sadrian#ifdef IEEE80211_SUPPORT_SUPERG
75218065Sadrian#include <net80211/ieee80211_superg.h>
76218065Sadrian#endif
77218065Sadrian#ifdef IEEE80211_SUPPORT_TDMA
78218065Sadrian#include <net80211/ieee80211_tdma.h>
79218065Sadrian#endif
80218065Sadrian
81218065Sadrian#include <net/bpf.h>
82218065Sadrian
83218065Sadrian#ifdef INET
84218065Sadrian#include <netinet/in.h>
85218065Sadrian#include <netinet/if_ether.h>
86218065Sadrian#endif
87218065Sadrian
88218065Sadrian#include <dev/ath/if_athvar.h>
89218065Sadrian#include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
90218065Sadrian#include <dev/ath/ath_hal/ah_diagcodes.h>
91218065Sadrian
92218065Sadrian#include <dev/ath/if_ath_debug.h>
93218065Sadrian
94218065Sadrian#ifdef ATH_TX99_DIAG
95218065Sadrian#include <dev/ath/ath_tx99/ath_tx99.h>
96218065Sadrian#endif
97218065Sadrian
98218065Sadrian#include <dev/ath/if_ath_misc.h>
99218065Sadrian#include <dev/ath/if_ath_tx.h>
100218240Sadrian#include <dev/ath/if_ath_tx_ht.h>
101218065Sadrian
102218154Sadrian/*
103218154Sadrian * Whether to use the 11n rate scenario functions or not
104218154Sadrian */
105218154Sadrianstatic inline int
106218154Sadrianath_tx_is_11n(struct ath_softc *sc)
107218154Sadrian{
108218154Sadrian	return (sc->sc_ah->ah_magic == 0x20065416);
109218154Sadrian}
110218154Sadrian
111218065Sadrianvoid
112218065Sadrianath_txfrag_cleanup(struct ath_softc *sc,
113218065Sadrian	ath_bufhead *frags, struct ieee80211_node *ni)
114218065Sadrian{
115218065Sadrian	struct ath_buf *bf, *next;
116218065Sadrian
117218065Sadrian	ATH_TXBUF_LOCK_ASSERT(sc);
118218065Sadrian
119218065Sadrian	STAILQ_FOREACH_SAFE(bf, frags, bf_list, next) {
120218065Sadrian		/* NB: bf assumed clean */
121218065Sadrian		STAILQ_REMOVE_HEAD(frags, bf_list);
122218065Sadrian		STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
123218065Sadrian		ieee80211_node_decref(ni);
124218065Sadrian	}
125218065Sadrian}
126218065Sadrian
127218065Sadrian/*
128218065Sadrian * Setup xmit of a fragmented frame.  Allocate a buffer
129218065Sadrian * for each frag and bump the node reference count to
130218065Sadrian * reflect the held reference to be setup by ath_tx_start.
131218065Sadrian */
132218065Sadrianint
133218065Sadrianath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags,
134218065Sadrian	struct mbuf *m0, struct ieee80211_node *ni)
135218065Sadrian{
136218065Sadrian	struct mbuf *m;
137218065Sadrian	struct ath_buf *bf;
138218065Sadrian
139218065Sadrian	ATH_TXBUF_LOCK(sc);
140218065Sadrian	for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) {
141218065Sadrian		bf = _ath_getbuf_locked(sc);
142218065Sadrian		if (bf == NULL) {	/* out of buffers, cleanup */
143218065Sadrian			ath_txfrag_cleanup(sc, frags, ni);
144218065Sadrian			break;
145218065Sadrian		}
146218065Sadrian		ieee80211_node_incref(ni);
147218065Sadrian		STAILQ_INSERT_TAIL(frags, bf, bf_list);
148218065Sadrian	}
149218065Sadrian	ATH_TXBUF_UNLOCK(sc);
150218065Sadrian
151218065Sadrian	return !STAILQ_EMPTY(frags);
152218065Sadrian}
153218065Sadrian
154218065Sadrian/*
155218065Sadrian * Reclaim mbuf resources.  For fragmented frames we
156218065Sadrian * need to claim each frag chained with m_nextpkt.
157218065Sadrian */
158218065Sadrianvoid
159218065Sadrianath_freetx(struct mbuf *m)
160218065Sadrian{
161218065Sadrian	struct mbuf *next;
162218065Sadrian
163218065Sadrian	do {
164218065Sadrian		next = m->m_nextpkt;
165218065Sadrian		m->m_nextpkt = NULL;
166218065Sadrian		m_freem(m);
167218065Sadrian	} while ((m = next) != NULL);
168218065Sadrian}
169218065Sadrian
170218065Sadrianstatic int
171218065Sadrianath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0)
172218065Sadrian{
173218065Sadrian	struct mbuf *m;
174218065Sadrian	int error;
175218065Sadrian
176218065Sadrian	/*
177218065Sadrian	 * Load the DMA map so any coalescing is done.  This
178218065Sadrian	 * also calculates the number of descriptors we need.
179218065Sadrian	 */
180218065Sadrian	error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
181218065Sadrian				     bf->bf_segs, &bf->bf_nseg,
182218065Sadrian				     BUS_DMA_NOWAIT);
183218065Sadrian	if (error == EFBIG) {
184218065Sadrian		/* XXX packet requires too many descriptors */
185218065Sadrian		bf->bf_nseg = ATH_TXDESC+1;
186218065Sadrian	} else if (error != 0) {
187218065Sadrian		sc->sc_stats.ast_tx_busdma++;
188218065Sadrian		ath_freetx(m0);
189218065Sadrian		return error;
190218065Sadrian	}
191218065Sadrian	/*
192218065Sadrian	 * Discard null packets and check for packets that
193218065Sadrian	 * require too many TX descriptors.  We try to convert
194218065Sadrian	 * the latter to a cluster.
195218065Sadrian	 */
196218065Sadrian	if (bf->bf_nseg > ATH_TXDESC) {		/* too many desc's, linearize */
197218065Sadrian		sc->sc_stats.ast_tx_linear++;
198248078Smarius		m = m_collapse(m0, M_NOWAIT, ATH_TXDESC);
199218065Sadrian		if (m == NULL) {
200218065Sadrian			ath_freetx(m0);
201218065Sadrian			sc->sc_stats.ast_tx_nombuf++;
202218065Sadrian			return ENOMEM;
203218065Sadrian		}
204218065Sadrian		m0 = m;
205218065Sadrian		error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
206218065Sadrian					     bf->bf_segs, &bf->bf_nseg,
207218065Sadrian					     BUS_DMA_NOWAIT);
208218065Sadrian		if (error != 0) {
209218065Sadrian			sc->sc_stats.ast_tx_busdma++;
210218065Sadrian			ath_freetx(m0);
211218065Sadrian			return error;
212218065Sadrian		}
213218065Sadrian		KASSERT(bf->bf_nseg <= ATH_TXDESC,
214218065Sadrian		    ("too many segments after defrag; nseg %u", bf->bf_nseg));
215218065Sadrian	} else if (bf->bf_nseg == 0) {		/* null packet, discard */
216218065Sadrian		sc->sc_stats.ast_tx_nodata++;
217218065Sadrian		ath_freetx(m0);
218218065Sadrian		return EIO;
219218065Sadrian	}
220218065Sadrian	DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n",
221218065Sadrian		__func__, m0, m0->m_pkthdr.len);
222218065Sadrian	bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
223218065Sadrian	bf->bf_m = m0;
224218065Sadrian
225218065Sadrian	return 0;
226218065Sadrian}
227218065Sadrian
228218065Sadrianstatic void
229218154Sadrianath_tx_chaindesclist(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf)
230218065Sadrian{
231218065Sadrian	struct ath_hal *ah = sc->sc_ah;
232218065Sadrian	struct ath_desc *ds, *ds0;
233218065Sadrian	int i;
234218065Sadrian
235218065Sadrian	/*
236218065Sadrian	 * Fillin the remainder of the descriptor info.
237218065Sadrian	 */
238218065Sadrian	ds0 = ds = bf->bf_desc;
239218065Sadrian	for (i = 0; i < bf->bf_nseg; i++, ds++) {
240218065Sadrian		ds->ds_data = bf->bf_segs[i].ds_addr;
241218065Sadrian		if (i == bf->bf_nseg - 1)
242218065Sadrian			ds->ds_link = 0;
243218065Sadrian		else
244218065Sadrian			ds->ds_link = bf->bf_daddr + sizeof(*ds) * (i + 1);
245218065Sadrian		ath_hal_filltxdesc(ah, ds
246218065Sadrian			, bf->bf_segs[i].ds_len	/* segment length */
247218065Sadrian			, i == 0		/* first segment */
248218065Sadrian			, i == bf->bf_nseg - 1	/* last segment */
249218065Sadrian			, ds0			/* first descriptor */
250218065Sadrian		);
251218065Sadrian		DPRINTF(sc, ATH_DEBUG_XMIT,
252218065Sadrian			"%s: %d: %08x %08x %08x %08x %08x %08x\n",
253218065Sadrian			__func__, i, ds->ds_link, ds->ds_data,
254218065Sadrian			ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]);
255218065Sadrian	}
256218154Sadrian
257218154Sadrian}
258218154Sadrian
259218154Sadrianstatic void
260218154Sadrianath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf)
261218154Sadrian{
262218154Sadrian	struct ath_hal *ah = sc->sc_ah;
263218154Sadrian
264218154Sadrian	/* Fill in the details in the descriptor list */
265218154Sadrian	ath_tx_chaindesclist(sc, txq, bf);
266218154Sadrian
267218065Sadrian	/*
268218065Sadrian	 * Insert the frame on the outbound list and pass it on
269218065Sadrian	 * to the hardware.  Multicast frames buffered for power
270218065Sadrian	 * save stations and transmit from the CAB queue are stored
271218065Sadrian	 * on a s/w only queue and loaded on to the CAB queue in
272218065Sadrian	 * the SWBA handler since frames only go out on DTIM and
273218065Sadrian	 * to avoid possible races.
274218065Sadrian	 */
275218065Sadrian	ATH_TXQ_LOCK(txq);
276218065Sadrian	KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0,
277218065Sadrian	     ("busy status 0x%x", bf->bf_flags));
278218065Sadrian	if (txq->axq_qnum != ATH_TXQ_SWQ) {
279218065Sadrian#ifdef IEEE80211_SUPPORT_TDMA
280218065Sadrian		int qbusy;
281218065Sadrian
282218065Sadrian		ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
283218065Sadrian		qbusy = ath_hal_txqenabled(ah, txq->axq_qnum);
284218065Sadrian		if (txq->axq_link == NULL) {
285218065Sadrian			/*
286218065Sadrian			 * Be careful writing the address to TXDP.  If
287218065Sadrian			 * the tx q is enabled then this write will be
288218065Sadrian			 * ignored.  Normally this is not an issue but
289218065Sadrian			 * when tdma is in use and the q is beacon gated
290218065Sadrian			 * this race can occur.  If the q is busy then
291218065Sadrian			 * defer the work to later--either when another
292218065Sadrian			 * packet comes along or when we prepare a beacon
293218065Sadrian			 * frame at SWBA.
294218065Sadrian			 */
295218065Sadrian			if (!qbusy) {
296218065Sadrian				ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
297218065Sadrian				txq->axq_flags &= ~ATH_TXQ_PUTPENDING;
298218065Sadrian				DPRINTF(sc, ATH_DEBUG_XMIT,
299218065Sadrian				    "%s: TXDP[%u] = %p (%p) depth %d\n",
300218065Sadrian				    __func__, txq->axq_qnum,
301218065Sadrian				    (caddr_t)bf->bf_daddr, bf->bf_desc,
302218065Sadrian				    txq->axq_depth);
303218065Sadrian			} else {
304218065Sadrian				txq->axq_flags |= ATH_TXQ_PUTPENDING;
305218065Sadrian				DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT,
306218065Sadrian				    "%s: Q%u busy, defer enable\n", __func__,
307218065Sadrian				    txq->axq_qnum);
308218065Sadrian			}
309218065Sadrian		} else {
310218065Sadrian			*txq->axq_link = bf->bf_daddr;
311218065Sadrian			DPRINTF(sc, ATH_DEBUG_XMIT,
312218065Sadrian			    "%s: link[%u](%p)=%p (%p) depth %d\n", __func__,
313218065Sadrian			    txq->axq_qnum, txq->axq_link,
314218065Sadrian			    (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth);
315218065Sadrian			if ((txq->axq_flags & ATH_TXQ_PUTPENDING) && !qbusy) {
316218065Sadrian				/*
317218065Sadrian				 * The q was busy when we previously tried
318218065Sadrian				 * to write the address of the first buffer
319218065Sadrian				 * in the chain.  Since it's not busy now
320218065Sadrian				 * handle this chore.  We are certain the
321218065Sadrian				 * buffer at the front is the right one since
322218065Sadrian				 * axq_link is NULL only when the buffer list
323218065Sadrian				 * is/was empty.
324218065Sadrian				 */
325218065Sadrian				ath_hal_puttxbuf(ah, txq->axq_qnum,
326218065Sadrian					STAILQ_FIRST(&txq->axq_q)->bf_daddr);
327218065Sadrian				txq->axq_flags &= ~ATH_TXQ_PUTPENDING;
328218065Sadrian				DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT,
329218065Sadrian				    "%s: Q%u restarted\n", __func__,
330218065Sadrian				    txq->axq_qnum);
331218065Sadrian			}
332218065Sadrian		}
333218065Sadrian#else
334218065Sadrian		ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
335218065Sadrian		if (txq->axq_link == NULL) {
336218065Sadrian			ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
337218065Sadrian			DPRINTF(sc, ATH_DEBUG_XMIT,
338218065Sadrian			    "%s: TXDP[%u] = %p (%p) depth %d\n",
339218065Sadrian			    __func__, txq->axq_qnum,
340218065Sadrian			    (caddr_t)bf->bf_daddr, bf->bf_desc,
341218065Sadrian			    txq->axq_depth);
342218065Sadrian		} else {
343218065Sadrian			*txq->axq_link = bf->bf_daddr;
344218065Sadrian			DPRINTF(sc, ATH_DEBUG_XMIT,
345218065Sadrian			    "%s: link[%u](%p)=%p (%p) depth %d\n", __func__,
346218065Sadrian			    txq->axq_qnum, txq->axq_link,
347218065Sadrian			    (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth);
348218065Sadrian		}
349218065Sadrian#endif /* IEEE80211_SUPPORT_TDMA */
350218065Sadrian		txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
351218065Sadrian		ath_hal_txstart(ah, txq->axq_qnum);
352218065Sadrian	} else {
353218065Sadrian		if (txq->axq_link != NULL) {
354218065Sadrian			struct ath_buf *last = ATH_TXQ_LAST(txq);
355218065Sadrian			struct ieee80211_frame *wh;
356218065Sadrian
357218065Sadrian			/* mark previous frame */
358218065Sadrian			wh = mtod(last->bf_m, struct ieee80211_frame *);
359218065Sadrian			wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
360218065Sadrian			bus_dmamap_sync(sc->sc_dmat, last->bf_dmamap,
361218065Sadrian			    BUS_DMASYNC_PREWRITE);
362218065Sadrian
363218065Sadrian			/* link descriptor */
364218065Sadrian			*txq->axq_link = bf->bf_daddr;
365218065Sadrian		}
366218065Sadrian		ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
367218065Sadrian		txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
368218065Sadrian	}
369218065Sadrian	ATH_TXQ_UNLOCK(txq);
370218065Sadrian}
371218065Sadrian
372218154Sadrianstatic int
373218154Sadrianath_tx_tag_crypto(struct ath_softc *sc, struct ieee80211_node *ni,
374218154Sadrian    struct mbuf *m0, int iswep, int isfrag, int *hdrlen, int *pktlen, int *keyix)
375218154Sadrian{
376218154Sadrian	if (iswep) {
377218154Sadrian		const struct ieee80211_cipher *cip;
378218154Sadrian		struct ieee80211_key *k;
379218154Sadrian
380218154Sadrian		/*
381218154Sadrian		 * Construct the 802.11 header+trailer for an encrypted
382218154Sadrian		 * frame. The only reason this can fail is because of an
383218154Sadrian		 * unknown or unsupported cipher/key type.
384218154Sadrian		 */
385218154Sadrian		k = ieee80211_crypto_encap(ni, m0);
386218154Sadrian		if (k == NULL) {
387218154Sadrian			/*
388218154Sadrian			 * This can happen when the key is yanked after the
389218154Sadrian			 * frame was queued.  Just discard the frame; the
390218154Sadrian			 * 802.11 layer counts failures and provides
391218154Sadrian			 * debugging/diagnostics.
392218154Sadrian			 */
393218154Sadrian			return 0;
394218154Sadrian		}
395218154Sadrian		/*
396218154Sadrian		 * Adjust the packet + header lengths for the crypto
397218154Sadrian		 * additions and calculate the h/w key index.  When
398218154Sadrian		 * a s/w mic is done the frame will have had any mic
399218154Sadrian		 * added to it prior to entry so m0->m_pkthdr.len will
400218154Sadrian		 * account for it. Otherwise we need to add it to the
401218154Sadrian		 * packet length.
402218154Sadrian		 */
403218154Sadrian		cip = k->wk_cipher;
404218154Sadrian		(*hdrlen) += cip->ic_header;
405218154Sadrian		(*pktlen) += cip->ic_header + cip->ic_trailer;
406218154Sadrian		/* NB: frags always have any TKIP MIC done in s/w */
407218154Sadrian		if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && !isfrag)
408218154Sadrian			(*pktlen) += cip->ic_miclen;
409218154Sadrian		(*keyix) = k->wk_keyix;
410218154Sadrian	} else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
411218154Sadrian		/*
412218154Sadrian		 * Use station key cache slot, if assigned.
413218154Sadrian		 */
414218154Sadrian		(*keyix) = ni->ni_ucastkey.wk_keyix;
415218154Sadrian		if ((*keyix) == IEEE80211_KEYIX_NONE)
416218154Sadrian			(*keyix) = HAL_TXKEYIX_INVALID;
417218154Sadrian	} else
418218154Sadrian		(*keyix) = HAL_TXKEYIX_INVALID;
419218154Sadrian
420218154Sadrian	return 1;
421218154Sadrian}
422218154Sadrian
423218932Sadrianstatic uint8_t
424218932Sadrianath_tx_get_rtscts_rate(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
425218932Sadrian    int rix, int cix, int shortPreamble)
426218157Sadrian{
427218932Sadrian	uint8_t ctsrate;
428218932Sadrian
429218157Sadrian	/*
430218157Sadrian	 * CTS transmit rate is derived from the transmit rate
431218157Sadrian	 * by looking in the h/w rate table.  We must also factor
432218157Sadrian	 * in whether or not a short preamble is to be used.
433218157Sadrian	 */
434218157Sadrian	/* NB: cix is set above where RTS/CTS is enabled */
435218157Sadrian	KASSERT(cix != 0xff, ("cix not setup"));
436218932Sadrian	ctsrate = rt->info[cix].rateCode;
437218932Sadrian
438218932Sadrian	/* XXX this should only matter for legacy rates */
439218932Sadrian	if (shortPreamble)
440218932Sadrian		ctsrate |= rt->info[cix].shortPreamble;
441218932Sadrian
442218932Sadrian	return ctsrate;
443218932Sadrian}
444218932Sadrian
445218932Sadrian
446218932Sadrian/*
447218932Sadrian * Calculate the RTS/CTS duration for legacy frames.
448218932Sadrian */
449218932Sadrianstatic int
450218932Sadrianath_tx_calc_ctsduration(struct ath_hal *ah, int rix, int cix,
451218932Sadrian    int shortPreamble, int pktlen, const HAL_RATE_TABLE *rt,
452218932Sadrian    int flags)
453218932Sadrian{
454218932Sadrian	int ctsduration = 0;
455218932Sadrian
456218932Sadrian	/* This mustn't be called for HT modes */
457218932Sadrian	if (rt->info[cix].phy == IEEE80211_T_HT) {
458218932Sadrian		printf("%s: HT rate where it shouldn't be (0x%x)\n",
459218932Sadrian		    __func__, rt->info[cix].rateCode);
460218932Sadrian		return -1;
461218932Sadrian	}
462218932Sadrian
463218157Sadrian	/*
464218157Sadrian	 * Compute the transmit duration based on the frame
465218157Sadrian	 * size and the size of an ACK frame.  We call into the
466218157Sadrian	 * HAL to do the computation since it depends on the
467218157Sadrian	 * characteristics of the actual PHY being used.
468218157Sadrian	 *
469218157Sadrian	 * NB: CTS is assumed the same size as an ACK so we can
470218157Sadrian	 *     use the precalculated ACK durations.
471218157Sadrian	 */
472218157Sadrian	if (shortPreamble) {
473218157Sadrian		if (flags & HAL_TXDESC_RTSENA)		/* SIFS + CTS */
474218932Sadrian			ctsduration += rt->info[cix].spAckDuration;
475218932Sadrian		ctsduration += ath_hal_computetxtime(ah,
476218157Sadrian			rt, pktlen, rix, AH_TRUE);
477218157Sadrian		if ((flags & HAL_TXDESC_NOACK) == 0)	/* SIFS + ACK */
478218932Sadrian			ctsduration += rt->info[rix].spAckDuration;
479218157Sadrian	} else {
480218157Sadrian		if (flags & HAL_TXDESC_RTSENA)		/* SIFS + CTS */
481218932Sadrian			ctsduration += rt->info[cix].lpAckDuration;
482218932Sadrian		ctsduration += ath_hal_computetxtime(ah,
483218157Sadrian			rt, pktlen, rix, AH_FALSE);
484218157Sadrian		if ((flags & HAL_TXDESC_NOACK) == 0)	/* SIFS + ACK */
485218932Sadrian			ctsduration += rt->info[rix].lpAckDuration;
486218157Sadrian	}
487218932Sadrian
488218932Sadrian	return ctsduration;
489218157Sadrian}
490218157Sadrian
491218065Sadrianint
492218065Sadrianath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
493218065Sadrian    struct mbuf *m0)
494218065Sadrian{
495218065Sadrian	struct ieee80211vap *vap = ni->ni_vap;
496218065Sadrian	struct ath_vap *avp = ATH_VAP(vap);
497218065Sadrian	struct ath_hal *ah = sc->sc_ah;
498218065Sadrian	struct ifnet *ifp = sc->sc_ifp;
499218065Sadrian	struct ieee80211com *ic = ifp->if_l2com;
500218065Sadrian	const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams;
501218065Sadrian	int error, iswep, ismcast, isfrag, ismrr;
502218065Sadrian	int keyix, hdrlen, pktlen, try0;
503218065Sadrian	u_int8_t rix, txrate, ctsrate;
504218065Sadrian	u_int8_t cix = 0xff;		/* NB: silence compiler */
505218065Sadrian	struct ath_desc *ds;
506218065Sadrian	struct ath_txq *txq;
507218065Sadrian	struct ieee80211_frame *wh;
508218065Sadrian	u_int subtype, flags, ctsduration;
509218065Sadrian	HAL_PKT_TYPE atype;
510218065Sadrian	const HAL_RATE_TABLE *rt;
511218065Sadrian	HAL_BOOL shortPreamble;
512218065Sadrian	struct ath_node *an;
513218065Sadrian	u_int pri;
514218240Sadrian	uint8_t try[4], rate[4];
515218065Sadrian
516218240Sadrian	bzero(try, sizeof(try));
517218240Sadrian	bzero(rate, sizeof(rate));
518218240Sadrian
519218065Sadrian	wh = mtod(m0, struct ieee80211_frame *);
520218065Sadrian	iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
521218065Sadrian	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
522218065Sadrian	isfrag = m0->m_flags & M_FRAG;
523218065Sadrian	hdrlen = ieee80211_anyhdrsize(wh);
524218065Sadrian	/*
525218065Sadrian	 * Packet length must not include any
526218065Sadrian	 * pad bytes; deduct them here.
527218065Sadrian	 */
528218065Sadrian	pktlen = m0->m_pkthdr.len - (hdrlen & 3);
529218065Sadrian
530218154Sadrian	/* Handle encryption twiddling if needed */
531218154Sadrian	if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen, &pktlen, &keyix)) {
532218154Sadrian		ath_freetx(m0);
533218154Sadrian		return EIO;
534218154Sadrian	}
535218065Sadrian
536218154Sadrian	/* packet header may have moved, reset our local pointer */
537218154Sadrian	wh = mtod(m0, struct ieee80211_frame *);
538218065Sadrian
539218065Sadrian	pktlen += IEEE80211_CRC_LEN;
540218065Sadrian
541218065Sadrian	/*
542218065Sadrian	 * Load the DMA map so any coalescing is done.  This
543218065Sadrian	 * also calculates the number of descriptors we need.
544218065Sadrian	 */
545218065Sadrian	error = ath_tx_dmasetup(sc, bf, m0);
546218065Sadrian	if (error != 0)
547218065Sadrian		return error;
548218065Sadrian	bf->bf_node = ni;			/* NB: held reference */
549218065Sadrian	m0 = bf->bf_m;				/* NB: may have changed */
550218065Sadrian	wh = mtod(m0, struct ieee80211_frame *);
551218065Sadrian
552218065Sadrian	/* setup descriptors */
553218065Sadrian	ds = bf->bf_desc;
554218065Sadrian	rt = sc->sc_currates;
555218065Sadrian	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
556218065Sadrian
557218065Sadrian	/*
558218065Sadrian	 * NB: the 802.11 layer marks whether or not we should
559218065Sadrian	 * use short preamble based on the current mode and
560218065Sadrian	 * negotiated parameters.
561218065Sadrian	 */
562218065Sadrian	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
563218065Sadrian	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
564218065Sadrian		shortPreamble = AH_TRUE;
565218065Sadrian		sc->sc_stats.ast_tx_shortpre++;
566218065Sadrian	} else {
567218065Sadrian		shortPreamble = AH_FALSE;
568218065Sadrian	}
569218065Sadrian
570218065Sadrian	an = ATH_NODE(ni);
571218065Sadrian	flags = HAL_TXDESC_CLRDMASK;		/* XXX needed for crypto errs */
572218065Sadrian	ismrr = 0;				/* default no multi-rate retry*/
573218065Sadrian	pri = M_WME_GETAC(m0);			/* honor classification */
574218065Sadrian	/* XXX use txparams instead of fixed values */
575218065Sadrian	/*
576218065Sadrian	 * Calculate Atheros packet type from IEEE80211 packet header,
577218065Sadrian	 * setup for rate calculations, and select h/w transmit queue.
578218065Sadrian	 */
579218065Sadrian	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
580218065Sadrian	case IEEE80211_FC0_TYPE_MGT:
581218065Sadrian		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
582218065Sadrian		if (subtype == IEEE80211_FC0_SUBTYPE_BEACON)
583218065Sadrian			atype = HAL_PKT_TYPE_BEACON;
584218065Sadrian		else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
585218065Sadrian			atype = HAL_PKT_TYPE_PROBE_RESP;
586218065Sadrian		else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM)
587218065Sadrian			atype = HAL_PKT_TYPE_ATIM;
588218065Sadrian		else
589218065Sadrian			atype = HAL_PKT_TYPE_NORMAL;	/* XXX */
590218065Sadrian		rix = an->an_mgmtrix;
591218065Sadrian		txrate = rt->info[rix].rateCode;
592218065Sadrian		if (shortPreamble)
593218065Sadrian			txrate |= rt->info[rix].shortPreamble;
594218065Sadrian		try0 = ATH_TXMGTTRY;
595218065Sadrian		flags |= HAL_TXDESC_INTREQ;	/* force interrupt */
596218065Sadrian		break;
597218065Sadrian	case IEEE80211_FC0_TYPE_CTL:
598218065Sadrian		atype = HAL_PKT_TYPE_PSPOLL;	/* stop setting of duration */
599218065Sadrian		rix = an->an_mgmtrix;
600218065Sadrian		txrate = rt->info[rix].rateCode;
601218065Sadrian		if (shortPreamble)
602218065Sadrian			txrate |= rt->info[rix].shortPreamble;
603218065Sadrian		try0 = ATH_TXMGTTRY;
604218065Sadrian		flags |= HAL_TXDESC_INTREQ;	/* force interrupt */
605218065Sadrian		break;
606218065Sadrian	case IEEE80211_FC0_TYPE_DATA:
607218065Sadrian		atype = HAL_PKT_TYPE_NORMAL;		/* default */
608218065Sadrian		/*
609218065Sadrian		 * Data frames: multicast frames go out at a fixed rate,
610218065Sadrian		 * EAPOL frames use the mgmt frame rate; otherwise consult
611218065Sadrian		 * the rate control module for the rate to use.
612218065Sadrian		 */
613218065Sadrian		if (ismcast) {
614218065Sadrian			rix = an->an_mcastrix;
615218065Sadrian			txrate = rt->info[rix].rateCode;
616218065Sadrian			if (shortPreamble)
617218065Sadrian				txrate |= rt->info[rix].shortPreamble;
618218065Sadrian			try0 = 1;
619218065Sadrian		} else if (m0->m_flags & M_EAPOL) {
620218065Sadrian			/* XXX? maybe always use long preamble? */
621218065Sadrian			rix = an->an_mgmtrix;
622218065Sadrian			txrate = rt->info[rix].rateCode;
623218065Sadrian			if (shortPreamble)
624218065Sadrian				txrate |= rt->info[rix].shortPreamble;
625218065Sadrian			try0 = ATH_TXMAXTRY;	/* XXX?too many? */
626218065Sadrian		} else {
627218065Sadrian			ath_rate_findrate(sc, an, shortPreamble, pktlen,
628218065Sadrian				&rix, &try0, &txrate);
629218065Sadrian			sc->sc_txrix = rix;		/* for LED blinking */
630218065Sadrian			sc->sc_lastdatarix = rix;	/* for fast frames */
631218065Sadrian			if (try0 != ATH_TXMAXTRY)
632218065Sadrian				ismrr = 1;
633218065Sadrian		}
634218065Sadrian		if (cap->cap_wmeParams[pri].wmep_noackPolicy)
635218065Sadrian			flags |= HAL_TXDESC_NOACK;
636218065Sadrian		break;
637218065Sadrian	default:
638218065Sadrian		if_printf(ifp, "bogus frame type 0x%x (%s)\n",
639218065Sadrian			wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
640218065Sadrian		/* XXX statistic */
641218065Sadrian		ath_freetx(m0);
642218065Sadrian		return EIO;
643218065Sadrian	}
644218065Sadrian	txq = sc->sc_ac2q[pri];
645218065Sadrian
646218065Sadrian	/*
647218065Sadrian	 * When servicing one or more stations in power-save mode
648218065Sadrian	 * (or) if there is some mcast data waiting on the mcast
649218065Sadrian	 * queue (to prevent out of order delivery) multicast
650218065Sadrian	 * frames must be buffered until after the beacon.
651218065Sadrian	 */
652218065Sadrian	if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth))
653218065Sadrian		txq = &avp->av_mcastq;
654218065Sadrian
655218065Sadrian	/*
656218065Sadrian	 * Calculate miscellaneous flags.
657218065Sadrian	 */
658218065Sadrian	if (ismcast) {
659218065Sadrian		flags |= HAL_TXDESC_NOACK;	/* no ack on broad/multicast */
660218065Sadrian	} else if (pktlen > vap->iv_rtsthreshold &&
661218065Sadrian	    (ni->ni_ath_flags & IEEE80211_NODE_FF) == 0) {
662218065Sadrian		flags |= HAL_TXDESC_RTSENA;	/* RTS based on frame length */
663218065Sadrian		cix = rt->info[rix].controlRate;
664218065Sadrian		sc->sc_stats.ast_tx_rts++;
665218065Sadrian	}
666218065Sadrian	if (flags & HAL_TXDESC_NOACK)		/* NB: avoid double counting */
667218065Sadrian		sc->sc_stats.ast_tx_noack++;
668218065Sadrian#ifdef IEEE80211_SUPPORT_TDMA
669218065Sadrian	if (sc->sc_tdma && (flags & HAL_TXDESC_NOACK) == 0) {
670218065Sadrian		DPRINTF(sc, ATH_DEBUG_TDMA,
671218065Sadrian		    "%s: discard frame, ACK required w/ TDMA\n", __func__);
672218065Sadrian		sc->sc_stats.ast_tdma_ack++;
673218065Sadrian		ath_freetx(m0);
674218065Sadrian		return EIO;
675218065Sadrian	}
676218065Sadrian#endif
677218065Sadrian
678218065Sadrian	/*
679218065Sadrian	 * If 802.11g protection is enabled, determine whether
680218065Sadrian	 * to use RTS/CTS or just CTS.  Note that this is only
681218065Sadrian	 * done for OFDM unicast frames.
682218065Sadrian	 */
683218065Sadrian	if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
684218065Sadrian	    rt->info[rix].phy == IEEE80211_T_OFDM &&
685218065Sadrian	    (flags & HAL_TXDESC_NOACK) == 0) {
686218065Sadrian		/* XXX fragments must use CCK rates w/ protection */
687218065Sadrian		if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
688218065Sadrian			flags |= HAL_TXDESC_RTSENA;
689218065Sadrian		else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
690218065Sadrian			flags |= HAL_TXDESC_CTSENA;
691218065Sadrian		if (isfrag) {
692218065Sadrian			/*
693218065Sadrian			 * For frags it would be desirable to use the
694218065Sadrian			 * highest CCK rate for RTS/CTS.  But stations
695218065Sadrian			 * farther away may detect it at a lower CCK rate
696218065Sadrian			 * so use the configured protection rate instead
697218065Sadrian			 * (for now).
698218065Sadrian			 */
699218065Sadrian			cix = rt->info[sc->sc_protrix].controlRate;
700218065Sadrian		} else
701218065Sadrian			cix = rt->info[sc->sc_protrix].controlRate;
702218065Sadrian		sc->sc_stats.ast_tx_protect++;
703218065Sadrian	}
704218065Sadrian
705220098Sadrian#if 0
706218065Sadrian	/*
707220098Sadrian	 * If 11n protection is enabled and it's a HT frame,
708220098Sadrian	 * enable RTS.
709220098Sadrian	 *
710220098Sadrian	 * XXX ic_htprotmode or ic_curhtprotmode?
711220098Sadrian	 * XXX should it_htprotmode only matter if ic_curhtprotmode
712220098Sadrian	 * XXX indicates it's not a HT pure environment?
713220098Sadrian	 */
714220098Sadrian	if ((ic->ic_htprotmode == IEEE80211_PROT_RTSCTS) &&
715220098Sadrian	    rt->info[rix].phy == IEEE80211_T_HT &&
716220098Sadrian	    (flags & HAL_TXDESC_NOACK) == 0) {
717220098Sadrian		cix = rt->info[sc->sc_protrix].controlRate;
718220098Sadrian	    	flags |= HAL_TXDESC_RTSENA;
719220098Sadrian		sc->sc_stats.ast_tx_htprotect++;
720220098Sadrian	}
721220098Sadrian#endif
722220098Sadrian
723220098Sadrian	/*
724218065Sadrian	 * Calculate duration.  This logically belongs in the 802.11
725218065Sadrian	 * layer but it lacks sufficient information to calculate it.
726218065Sadrian	 */
727218065Sadrian	if ((flags & HAL_TXDESC_NOACK) == 0 &&
728218065Sadrian	    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) {
729218065Sadrian		u_int16_t dur;
730218065Sadrian		if (shortPreamble)
731218065Sadrian			dur = rt->info[rix].spAckDuration;
732218065Sadrian		else
733218065Sadrian			dur = rt->info[rix].lpAckDuration;
734218065Sadrian		if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) {
735218065Sadrian			dur += dur;		/* additional SIFS+ACK */
736218065Sadrian			KASSERT(m0->m_nextpkt != NULL, ("no fragment"));
737218065Sadrian			/*
738218065Sadrian			 * Include the size of next fragment so NAV is
739218065Sadrian			 * updated properly.  The last fragment uses only
740218065Sadrian			 * the ACK duration
741218065Sadrian			 */
742218065Sadrian			dur += ath_hal_computetxtime(ah, rt,
743218065Sadrian					m0->m_nextpkt->m_pkthdr.len,
744218065Sadrian					rix, shortPreamble);
745218065Sadrian		}
746218065Sadrian		if (isfrag) {
747218065Sadrian			/*
748218065Sadrian			 * Force hardware to use computed duration for next
749218065Sadrian			 * fragment by disabling multi-rate retry which updates
750218065Sadrian			 * duration based on the multi-rate duration table.
751218065Sadrian			 */
752218065Sadrian			ismrr = 0;
753218065Sadrian			try0 = ATH_TXMGTTRY;	/* XXX? */
754218065Sadrian		}
755218065Sadrian		*(u_int16_t *)wh->i_dur = htole16(dur);
756218065Sadrian	}
757218065Sadrian
758218065Sadrian	/*
759218065Sadrian	 * Calculate RTS/CTS rate and duration if needed.
760218065Sadrian	 */
761218065Sadrian	ctsduration = 0;
762218065Sadrian	if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) {
763218932Sadrian		ctsrate = ath_tx_get_rtscts_rate(ah, rt, rix, cix, shortPreamble);
764218932Sadrian
765218932Sadrian		/* The 11n chipsets do ctsduration calculations for you */
766218932Sadrian		if (! ath_tx_is_11n(sc))
767218932Sadrian			ctsduration = ath_tx_calc_ctsduration(ah, rix, cix, shortPreamble,
768218932Sadrian			    pktlen, rt, flags);
769218065Sadrian		/*
770218065Sadrian		 * Must disable multi-rate retry when using RTS/CTS.
771218065Sadrian		 */
772218065Sadrian		ismrr = 0;
773218065Sadrian		try0 = ATH_TXMGTTRY;		/* XXX */
774218065Sadrian	} else
775218065Sadrian		ctsrate = 0;
776218065Sadrian
777218065Sadrian	/*
778218065Sadrian	 * At this point we are committed to sending the frame
779218065Sadrian	 * and we don't need to look at m_nextpkt; clear it in
780218065Sadrian	 * case this frame is part of frag chain.
781218065Sadrian	 */
782218065Sadrian	m0->m_nextpkt = NULL;
783218065Sadrian
784218065Sadrian	if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT))
785218065Sadrian		ieee80211_dump_pkt(ic, mtod(m0, const uint8_t *), m0->m_len,
786218065Sadrian		    sc->sc_hwmap[rix].ieeerate, -1);
787218065Sadrian
788218065Sadrian	if (ieee80211_radiotap_active_vap(vap)) {
789218065Sadrian		u_int64_t tsf = ath_hal_gettsf64(ah);
790218065Sadrian
791218065Sadrian		sc->sc_tx_th.wt_tsf = htole64(tsf);
792218065Sadrian		sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags;
793218065Sadrian		if (iswep)
794218065Sadrian			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
795218065Sadrian		if (isfrag)
796218065Sadrian			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG;
797218065Sadrian		sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate;
798218065Sadrian		sc->sc_tx_th.wt_txpower = ni->ni_txpower;
799218065Sadrian		sc->sc_tx_th.wt_antenna = sc->sc_txantenna;
800218065Sadrian
801218065Sadrian		ieee80211_radiotap_tx(vap, m0);
802218065Sadrian	}
803218065Sadrian
804218065Sadrian	/*
805218065Sadrian	 * Determine if a tx interrupt should be generated for
806218065Sadrian	 * this descriptor.  We take a tx interrupt to reap
807218065Sadrian	 * descriptors when the h/w hits an EOL condition or
808218065Sadrian	 * when the descriptor is specifically marked to generate
809218065Sadrian	 * an interrupt.  We periodically mark descriptors in this
810218065Sadrian	 * way to insure timely replenishing of the supply needed
811218065Sadrian	 * for sending frames.  Defering interrupts reduces system
812218065Sadrian	 * load and potentially allows more concurrent work to be
813218065Sadrian	 * done but if done to aggressively can cause senders to
814218065Sadrian	 * backup.
815218065Sadrian	 *
816218065Sadrian	 * NB: use >= to deal with sc_txintrperiod changing
817218065Sadrian	 *     dynamically through sysctl.
818218065Sadrian	 */
819218065Sadrian	if (flags & HAL_TXDESC_INTREQ) {
820218065Sadrian		txq->axq_intrcnt = 0;
821218065Sadrian	} else if (++txq->axq_intrcnt >= sc->sc_txintrperiod) {
822218065Sadrian		flags |= HAL_TXDESC_INTREQ;
823218065Sadrian		txq->axq_intrcnt = 0;
824218065Sadrian	}
825218065Sadrian
826218240Sadrian	if (ath_tx_is_11n(sc)) {
827218240Sadrian		rate[0] = rix;
828218240Sadrian		try[0] = try0;
829218240Sadrian	}
830218240Sadrian
831218065Sadrian	/*
832218065Sadrian	 * Formulate first tx descriptor with tx controls.
833218065Sadrian	 */
834218065Sadrian	/* XXX check return value? */
835218240Sadrian	/* XXX is this ok to call for 11n descriptors? */
836218240Sadrian	/* XXX or should it go through the first, next, last 11n calls? */
837218065Sadrian	ath_hal_setuptxdesc(ah, ds
838218065Sadrian		, pktlen		/* packet length */
839218065Sadrian		, hdrlen		/* header length */
840218065Sadrian		, atype			/* Atheros packet type */
841218065Sadrian		, ni->ni_txpower	/* txpower */
842218065Sadrian		, txrate, try0		/* series 0 rate/tries */
843218065Sadrian		, keyix			/* key cache index */
844218065Sadrian		, sc->sc_txantenna	/* antenna mode */
845218065Sadrian		, flags			/* flags */
846218065Sadrian		, ctsrate		/* rts/cts rate */
847218065Sadrian		, ctsduration		/* rts/cts duration */
848218065Sadrian	);
849218065Sadrian	bf->bf_txflags = flags;
850218065Sadrian	/*
851218065Sadrian	 * Setup the multi-rate retry state only when we're
852218065Sadrian	 * going to use it.  This assumes ath_hal_setuptxdesc
853218065Sadrian	 * initializes the descriptors (so we don't have to)
854218065Sadrian	 * when the hardware supports multi-rate retry and
855218065Sadrian	 * we don't use it.
856218065Sadrian	 */
857218240Sadrian        if (ismrr) {
858218240Sadrian                if (ath_tx_is_11n(sc))
859218240Sadrian                        ath_rate_getxtxrates(sc, an, rix, rate, try);
860218240Sadrian                else
861218240Sadrian                        ath_rate_setupxtxdesc(sc, an, ds, shortPreamble, rix);
862218240Sadrian        }
863218065Sadrian
864218240Sadrian        if (ath_tx_is_11n(sc)) {
865218593Sadrian                ath_buf_set_rate(sc, ni, bf, pktlen, flags, ctsrate, (atype == HAL_PKT_TYPE_PSPOLL), rate, try);
866218240Sadrian        }
867218240Sadrian
868218065Sadrian	ath_tx_handoff(sc, txq, bf);
869218065Sadrian	return 0;
870218065Sadrian}
871218065Sadrian
872218065Sadrianstatic int
873218065Sadrianath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
874218065Sadrian	struct ath_buf *bf, struct mbuf *m0,
875218065Sadrian	const struct ieee80211_bpf_params *params)
876218065Sadrian{
877218065Sadrian	struct ifnet *ifp = sc->sc_ifp;
878218065Sadrian	struct ieee80211com *ic = ifp->if_l2com;
879218065Sadrian	struct ath_hal *ah = sc->sc_ah;
880218065Sadrian	struct ieee80211vap *vap = ni->ni_vap;
881218065Sadrian	int error, ismcast, ismrr;
882218065Sadrian	int keyix, hdrlen, pktlen, try0, txantenna;
883218065Sadrian	u_int8_t rix, cix, txrate, ctsrate, rate1, rate2, rate3;
884218065Sadrian	struct ieee80211_frame *wh;
885218065Sadrian	u_int flags, ctsduration;
886218065Sadrian	HAL_PKT_TYPE atype;
887218065Sadrian	const HAL_RATE_TABLE *rt;
888218065Sadrian	struct ath_desc *ds;
889218065Sadrian	u_int pri;
890218240Sadrian	uint8_t try[4], rate[4];
891218065Sadrian
892218240Sadrian	bzero(try, sizeof(try));
893218240Sadrian	bzero(rate, sizeof(rate));
894218240Sadrian
895218065Sadrian	wh = mtod(m0, struct ieee80211_frame *);
896218065Sadrian	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
897218065Sadrian	hdrlen = ieee80211_anyhdrsize(wh);
898218065Sadrian	/*
899218065Sadrian	 * Packet length must not include any
900218065Sadrian	 * pad bytes; deduct them here.
901218065Sadrian	 */
902218065Sadrian	/* XXX honor IEEE80211_BPF_DATAPAD */
903218065Sadrian	pktlen = m0->m_pkthdr.len - (hdrlen & 3) + IEEE80211_CRC_LEN;
904218065Sadrian
905218154Sadrian	/* Handle encryption twiddling if needed */
906218154Sadrian	if (! ath_tx_tag_crypto(sc, ni, m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0, &hdrlen, &pktlen, &keyix)) {
907218154Sadrian		ath_freetx(m0);
908218154Sadrian		return EIO;
909218154Sadrian	}
910218154Sadrian	/* packet header may have moved, reset our local pointer */
911218154Sadrian	wh = mtod(m0, struct ieee80211_frame *);
912218065Sadrian
913218065Sadrian	error = ath_tx_dmasetup(sc, bf, m0);
914218065Sadrian	if (error != 0)
915218065Sadrian		return error;
916218065Sadrian	m0 = bf->bf_m;				/* NB: may have changed */
917218065Sadrian	wh = mtod(m0, struct ieee80211_frame *);
918218065Sadrian	bf->bf_node = ni;			/* NB: held reference */
919218065Sadrian
920218065Sadrian	flags = HAL_TXDESC_CLRDMASK;		/* XXX needed for crypto errs */
921218065Sadrian	flags |= HAL_TXDESC_INTREQ;		/* force interrupt */
922218065Sadrian	if (params->ibp_flags & IEEE80211_BPF_RTS)
923218065Sadrian		flags |= HAL_TXDESC_RTSENA;
924218065Sadrian	else if (params->ibp_flags & IEEE80211_BPF_CTS)
925218065Sadrian		flags |= HAL_TXDESC_CTSENA;
926218065Sadrian	/* XXX leave ismcast to injector? */
927218065Sadrian	if ((params->ibp_flags & IEEE80211_BPF_NOACK) || ismcast)
928218065Sadrian		flags |= HAL_TXDESC_NOACK;
929218065Sadrian
930218065Sadrian	rt = sc->sc_currates;
931218065Sadrian	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
932218065Sadrian	rix = ath_tx_findrix(sc, params->ibp_rate0);
933218065Sadrian	txrate = rt->info[rix].rateCode;
934218065Sadrian	if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
935218065Sadrian		txrate |= rt->info[rix].shortPreamble;
936218065Sadrian	sc->sc_txrix = rix;
937218065Sadrian	try0 = params->ibp_try0;
938218065Sadrian	ismrr = (params->ibp_try1 != 0);
939218065Sadrian	txantenna = params->ibp_pri >> 2;
940218065Sadrian	if (txantenna == 0)			/* XXX? */
941218065Sadrian		txantenna = sc->sc_txantenna;
942218157Sadrian
943218065Sadrian	ctsduration = 0;
944218157Sadrian	if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) {
945218065Sadrian		cix = ath_tx_findrix(sc, params->ibp_ctsrate);
946218932Sadrian		ctsrate = ath_tx_get_rtscts_rate(ah, rt, rix, cix, params->ibp_flags & IEEE80211_BPF_SHORTPRE);
947218932Sadrian		/* The 11n chipsets do ctsduration calculations for you */
948218932Sadrian		if (! ath_tx_is_11n(sc))
949218932Sadrian			ctsduration = ath_tx_calc_ctsduration(ah, rix, cix,
950218932Sadrian			    params->ibp_flags & IEEE80211_BPF_SHORTPRE, pktlen,
951218932Sadrian			    rt, flags);
952218157Sadrian		/*
953218157Sadrian		 * Must disable multi-rate retry when using RTS/CTS.
954218157Sadrian		 */
955218065Sadrian		ismrr = 0;			/* XXX */
956218065Sadrian	} else
957218065Sadrian		ctsrate = 0;
958218157Sadrian
959218065Sadrian	pri = params->ibp_pri & 3;
960218065Sadrian	/*
961218065Sadrian	 * NB: we mark all packets as type PSPOLL so the h/w won't
962218065Sadrian	 * set the sequence number, duration, etc.
963218065Sadrian	 */
964218065Sadrian	atype = HAL_PKT_TYPE_PSPOLL;
965218065Sadrian
966218065Sadrian	if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT))
967218065Sadrian		ieee80211_dump_pkt(ic, mtod(m0, caddr_t), m0->m_len,
968218065Sadrian		    sc->sc_hwmap[rix].ieeerate, -1);
969218065Sadrian
970218065Sadrian	if (ieee80211_radiotap_active_vap(vap)) {
971218065Sadrian		u_int64_t tsf = ath_hal_gettsf64(ah);
972218065Sadrian
973218065Sadrian		sc->sc_tx_th.wt_tsf = htole64(tsf);
974218065Sadrian		sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags;
975218065Sadrian		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
976218065Sadrian			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
977218065Sadrian		if (m0->m_flags & M_FRAG)
978218065Sadrian			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG;
979218065Sadrian		sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate;
980218065Sadrian		sc->sc_tx_th.wt_txpower = ni->ni_txpower;
981218065Sadrian		sc->sc_tx_th.wt_antenna = sc->sc_txantenna;
982218065Sadrian
983218065Sadrian		ieee80211_radiotap_tx(vap, m0);
984218065Sadrian	}
985218065Sadrian
986218065Sadrian	/*
987218065Sadrian	 * Formulate first tx descriptor with tx controls.
988218065Sadrian	 */
989218065Sadrian	ds = bf->bf_desc;
990218065Sadrian	/* XXX check return value? */
991218065Sadrian	ath_hal_setuptxdesc(ah, ds
992218065Sadrian		, pktlen		/* packet length */
993218065Sadrian		, hdrlen		/* header length */
994218065Sadrian		, atype			/* Atheros packet type */
995218065Sadrian		, params->ibp_power	/* txpower */
996218065Sadrian		, txrate, try0		/* series 0 rate/tries */
997218065Sadrian		, keyix			/* key cache index */
998218065Sadrian		, txantenna		/* antenna mode */
999218065Sadrian		, flags			/* flags */
1000218065Sadrian		, ctsrate		/* rts/cts rate */
1001218065Sadrian		, ctsduration		/* rts/cts duration */
1002218065Sadrian	);
1003218065Sadrian	bf->bf_txflags = flags;
1004218065Sadrian
1005218240Sadrian	if (ath_tx_is_11n(sc)) {
1006218240Sadrian		rate[0] = ath_tx_findrix(sc, params->ibp_rate0);
1007218240Sadrian		try[0] = params->ibp_try0;
1008218240Sadrian
1009218240Sadrian		if (ismrr) {
1010218240Sadrian			/* Remember, rate[] is actually an array of rix's -adrian */
1011218240Sadrian			rate[0] = ath_tx_findrix(sc, params->ibp_rate0);
1012218240Sadrian			rate[1] = ath_tx_findrix(sc, params->ibp_rate1);
1013218240Sadrian			rate[2] = ath_tx_findrix(sc, params->ibp_rate2);
1014218240Sadrian			rate[3] = ath_tx_findrix(sc, params->ibp_rate3);
1015218240Sadrian
1016218240Sadrian			try[0] = params->ibp_try0;
1017218240Sadrian			try[1] = params->ibp_try1;
1018218240Sadrian			try[2] = params->ibp_try2;
1019218240Sadrian			try[3] = params->ibp_try3;
1020218240Sadrian		}
1021218240Sadrian	} else {
1022218240Sadrian		if (ismrr) {
1023218240Sadrian			rix = ath_tx_findrix(sc, params->ibp_rate1);
1024218240Sadrian			rate1 = rt->info[rix].rateCode;
1025218065Sadrian			if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
1026218240Sadrian				rate1 |= rt->info[rix].shortPreamble;
1027218240Sadrian			if (params->ibp_try2) {
1028218240Sadrian				rix = ath_tx_findrix(sc, params->ibp_rate2);
1029218240Sadrian				rate2 = rt->info[rix].rateCode;
1030218240Sadrian				if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
1031218240Sadrian					rate2 |= rt->info[rix].shortPreamble;
1032218240Sadrian			} else
1033218240Sadrian				rate2 = 0;
1034218240Sadrian			if (params->ibp_try3) {
1035218240Sadrian				rix = ath_tx_findrix(sc, params->ibp_rate3);
1036218240Sadrian				rate3 = rt->info[rix].rateCode;
1037218240Sadrian				if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
1038218240Sadrian					rate3 |= rt->info[rix].shortPreamble;
1039218240Sadrian			} else
1040218240Sadrian				rate3 = 0;
1041218240Sadrian			ath_hal_setupxtxdesc(ah, ds
1042218240Sadrian				, rate1, params->ibp_try1	/* series 1 */
1043218240Sadrian				, rate2, params->ibp_try2	/* series 2 */
1044218240Sadrian				, rate3, params->ibp_try3	/* series 3 */
1045218240Sadrian			);
1046218240Sadrian		}
1047218065Sadrian	}
1048218065Sadrian
1049218240Sadrian	if (ath_tx_is_11n(sc)) {
1050218240Sadrian		/*
1051218240Sadrian		 * notice that rix doesn't include any of the "magic" flags txrate
1052218240Sadrian		 * does for communicating "other stuff" to the HAL.
1053218240Sadrian		 */
1054218593Sadrian		ath_buf_set_rate(sc, ni, bf, pktlen, flags, ctsrate, (atype == HAL_PKT_TYPE_PSPOLL), rate, try);
1055218240Sadrian	}
1056218240Sadrian
1057218065Sadrian	/* NB: no buffered multicast in power save support */
1058218065Sadrian	ath_tx_handoff(sc, sc->sc_ac2q[pri], bf);
1059218065Sadrian	return 0;
1060218065Sadrian}
1061218065Sadrian
1062218065Sadrianint
1063218065Sadrianath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
1064218065Sadrian	const struct ieee80211_bpf_params *params)
1065218065Sadrian{
1066218065Sadrian	struct ieee80211com *ic = ni->ni_ic;
1067218065Sadrian	struct ifnet *ifp = ic->ic_ifp;
1068218065Sadrian	struct ath_softc *sc = ifp->if_softc;
1069218065Sadrian	struct ath_buf *bf;
1070218065Sadrian	int error;
1071218065Sadrian
1072218065Sadrian	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) {
1073218065Sadrian		DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__,
1074218065Sadrian		    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ?
1075218065Sadrian			"!running" : "invalid");
1076218065Sadrian		m_freem(m);
1077218065Sadrian		error = ENETDOWN;
1078218065Sadrian		goto bad;
1079218065Sadrian	}
1080218065Sadrian	/*
1081218065Sadrian	 * Grab a TX buffer and associated resources.
1082218065Sadrian	 */
1083218065Sadrian	bf = ath_getbuf(sc);
1084218065Sadrian	if (bf == NULL) {
1085218065Sadrian		sc->sc_stats.ast_tx_nobuf++;
1086218065Sadrian		m_freem(m);
1087218065Sadrian		error = ENOBUFS;
1088218065Sadrian		goto bad;
1089218065Sadrian	}
1090218065Sadrian
1091218065Sadrian	if (params == NULL) {
1092218065Sadrian		/*
1093218065Sadrian		 * Legacy path; interpret frame contents to decide
1094218065Sadrian		 * precisely how to send the frame.
1095218065Sadrian		 */
1096218065Sadrian		if (ath_tx_start(sc, ni, bf, m)) {
1097218065Sadrian			error = EIO;		/* XXX */
1098218065Sadrian			goto bad2;
1099218065Sadrian		}
1100218065Sadrian	} else {
1101218065Sadrian		/*
1102218065Sadrian		 * Caller supplied explicit parameters to use in
1103218065Sadrian		 * sending the frame.
1104218065Sadrian		 */
1105218065Sadrian		if (ath_tx_raw_start(sc, ni, bf, m, params)) {
1106218065Sadrian			error = EIO;		/* XXX */
1107218065Sadrian			goto bad2;
1108218065Sadrian		}
1109218065Sadrian	}
1110218065Sadrian	sc->sc_wd_timer = 5;
1111218065Sadrian	ifp->if_opackets++;
1112218065Sadrian	sc->sc_stats.ast_tx_raw++;
1113218065Sadrian
1114218065Sadrian	return 0;
1115218065Sadrianbad2:
1116218065Sadrian	ATH_TXBUF_LOCK(sc);
1117218065Sadrian	STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
1118218065Sadrian	ATH_TXBUF_UNLOCK(sc);
1119218065Sadrianbad:
1120218065Sadrian	ifp->if_oerrors++;
1121218065Sadrian	sc->sc_stats.ast_tx_raw_fail++;
1122218065Sadrian	ieee80211_free_node(ni);
1123218065Sadrian	return error;
1124218065Sadrian}
1125