if_ath_tx.c revision 218157
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: head/sys/dev/ath/if_ath_tx.c 218157 2011-02-01 07:50:26Z adrian $"); 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> 100218065Sadrian 101218154Sadrian/* 102218154Sadrian * Whether to use the 11n rate scenario functions or not 103218154Sadrian */ 104218154Sadrianstatic inline int 105218154Sadrianath_tx_is_11n(struct ath_softc *sc) 106218154Sadrian{ 107218154Sadrian return (sc->sc_ah->ah_magic == 0x20065416); 108218154Sadrian} 109218154Sadrian 110218065Sadrianvoid 111218065Sadrianath_txfrag_cleanup(struct ath_softc *sc, 112218065Sadrian ath_bufhead *frags, struct ieee80211_node *ni) 113218065Sadrian{ 114218065Sadrian struct ath_buf *bf, *next; 115218065Sadrian 116218065Sadrian ATH_TXBUF_LOCK_ASSERT(sc); 117218065Sadrian 118218065Sadrian STAILQ_FOREACH_SAFE(bf, frags, bf_list, next) { 119218065Sadrian /* NB: bf assumed clean */ 120218065Sadrian STAILQ_REMOVE_HEAD(frags, bf_list); 121218065Sadrian STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); 122218065Sadrian ieee80211_node_decref(ni); 123218065Sadrian } 124218065Sadrian} 125218065Sadrian 126218065Sadrian/* 127218065Sadrian * Setup xmit of a fragmented frame. Allocate a buffer 128218065Sadrian * for each frag and bump the node reference count to 129218065Sadrian * reflect the held reference to be setup by ath_tx_start. 130218065Sadrian */ 131218065Sadrianint 132218065Sadrianath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags, 133218065Sadrian struct mbuf *m0, struct ieee80211_node *ni) 134218065Sadrian{ 135218065Sadrian struct mbuf *m; 136218065Sadrian struct ath_buf *bf; 137218065Sadrian 138218065Sadrian ATH_TXBUF_LOCK(sc); 139218065Sadrian for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) { 140218065Sadrian bf = _ath_getbuf_locked(sc); 141218065Sadrian if (bf == NULL) { /* out of buffers, cleanup */ 142218065Sadrian ath_txfrag_cleanup(sc, frags, ni); 143218065Sadrian break; 144218065Sadrian } 145218065Sadrian ieee80211_node_incref(ni); 146218065Sadrian STAILQ_INSERT_TAIL(frags, bf, bf_list); 147218065Sadrian } 148218065Sadrian ATH_TXBUF_UNLOCK(sc); 149218065Sadrian 150218065Sadrian return !STAILQ_EMPTY(frags); 151218065Sadrian} 152218065Sadrian 153218065Sadrian/* 154218065Sadrian * Reclaim mbuf resources. For fragmented frames we 155218065Sadrian * need to claim each frag chained with m_nextpkt. 156218065Sadrian */ 157218065Sadrianvoid 158218065Sadrianath_freetx(struct mbuf *m) 159218065Sadrian{ 160218065Sadrian struct mbuf *next; 161218065Sadrian 162218065Sadrian do { 163218065Sadrian next = m->m_nextpkt; 164218065Sadrian m->m_nextpkt = NULL; 165218065Sadrian m_freem(m); 166218065Sadrian } while ((m = next) != NULL); 167218065Sadrian} 168218065Sadrian 169218065Sadrianstatic int 170218065Sadrianath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) 171218065Sadrian{ 172218065Sadrian struct mbuf *m; 173218065Sadrian int error; 174218065Sadrian 175218065Sadrian /* 176218065Sadrian * Load the DMA map so any coalescing is done. This 177218065Sadrian * also calculates the number of descriptors we need. 178218065Sadrian */ 179218065Sadrian error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0, 180218065Sadrian bf->bf_segs, &bf->bf_nseg, 181218065Sadrian BUS_DMA_NOWAIT); 182218065Sadrian if (error == EFBIG) { 183218065Sadrian /* XXX packet requires too many descriptors */ 184218065Sadrian bf->bf_nseg = ATH_TXDESC+1; 185218065Sadrian } else if (error != 0) { 186218065Sadrian sc->sc_stats.ast_tx_busdma++; 187218065Sadrian ath_freetx(m0); 188218065Sadrian return error; 189218065Sadrian } 190218065Sadrian /* 191218065Sadrian * Discard null packets and check for packets that 192218065Sadrian * require too many TX descriptors. We try to convert 193218065Sadrian * the latter to a cluster. 194218065Sadrian */ 195218065Sadrian if (bf->bf_nseg > ATH_TXDESC) { /* too many desc's, linearize */ 196218065Sadrian sc->sc_stats.ast_tx_linear++; 197218065Sadrian m = m_collapse(m0, M_DONTWAIT, ATH_TXDESC); 198218065Sadrian if (m == NULL) { 199218065Sadrian ath_freetx(m0); 200218065Sadrian sc->sc_stats.ast_tx_nombuf++; 201218065Sadrian return ENOMEM; 202218065Sadrian } 203218065Sadrian m0 = m; 204218065Sadrian error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0, 205218065Sadrian bf->bf_segs, &bf->bf_nseg, 206218065Sadrian BUS_DMA_NOWAIT); 207218065Sadrian if (error != 0) { 208218065Sadrian sc->sc_stats.ast_tx_busdma++; 209218065Sadrian ath_freetx(m0); 210218065Sadrian return error; 211218065Sadrian } 212218065Sadrian KASSERT(bf->bf_nseg <= ATH_TXDESC, 213218065Sadrian ("too many segments after defrag; nseg %u", bf->bf_nseg)); 214218065Sadrian } else if (bf->bf_nseg == 0) { /* null packet, discard */ 215218065Sadrian sc->sc_stats.ast_tx_nodata++; 216218065Sadrian ath_freetx(m0); 217218065Sadrian return EIO; 218218065Sadrian } 219218065Sadrian DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n", 220218065Sadrian __func__, m0, m0->m_pkthdr.len); 221218065Sadrian bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE); 222218065Sadrian bf->bf_m = m0; 223218065Sadrian 224218065Sadrian return 0; 225218065Sadrian} 226218065Sadrian 227218065Sadrianstatic void 228218154Sadrianath_tx_chaindesclist(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf) 229218065Sadrian{ 230218065Sadrian struct ath_hal *ah = sc->sc_ah; 231218065Sadrian struct ath_desc *ds, *ds0; 232218065Sadrian int i; 233218065Sadrian 234218065Sadrian /* 235218065Sadrian * Fillin the remainder of the descriptor info. 236218065Sadrian */ 237218065Sadrian ds0 = ds = bf->bf_desc; 238218065Sadrian for (i = 0; i < bf->bf_nseg; i++, ds++) { 239218065Sadrian ds->ds_data = bf->bf_segs[i].ds_addr; 240218065Sadrian if (i == bf->bf_nseg - 1) 241218065Sadrian ds->ds_link = 0; 242218065Sadrian else 243218065Sadrian ds->ds_link = bf->bf_daddr + sizeof(*ds) * (i + 1); 244218065Sadrian ath_hal_filltxdesc(ah, ds 245218065Sadrian , bf->bf_segs[i].ds_len /* segment length */ 246218065Sadrian , i == 0 /* first segment */ 247218065Sadrian , i == bf->bf_nseg - 1 /* last segment */ 248218065Sadrian , ds0 /* first descriptor */ 249218065Sadrian ); 250218065Sadrian DPRINTF(sc, ATH_DEBUG_XMIT, 251218065Sadrian "%s: %d: %08x %08x %08x %08x %08x %08x\n", 252218065Sadrian __func__, i, ds->ds_link, ds->ds_data, 253218065Sadrian ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]); 254218065Sadrian } 255218154Sadrian 256218154Sadrian} 257218154Sadrian 258218154Sadrianstatic void 259218154Sadrianath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf) 260218154Sadrian{ 261218154Sadrian struct ath_hal *ah = sc->sc_ah; 262218154Sadrian 263218154Sadrian /* Fill in the details in the descriptor list */ 264218154Sadrian ath_tx_chaindesclist(sc, txq, bf); 265218154Sadrian 266218065Sadrian /* 267218065Sadrian * Insert the frame on the outbound list and pass it on 268218065Sadrian * to the hardware. Multicast frames buffered for power 269218065Sadrian * save stations and transmit from the CAB queue are stored 270218065Sadrian * on a s/w only queue and loaded on to the CAB queue in 271218065Sadrian * the SWBA handler since frames only go out on DTIM and 272218065Sadrian * to avoid possible races. 273218065Sadrian */ 274218065Sadrian ATH_TXQ_LOCK(txq); 275218065Sadrian KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0, 276218065Sadrian ("busy status 0x%x", bf->bf_flags)); 277218065Sadrian if (txq->axq_qnum != ATH_TXQ_SWQ) { 278218065Sadrian#ifdef IEEE80211_SUPPORT_TDMA 279218065Sadrian int qbusy; 280218065Sadrian 281218065Sadrian ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); 282218065Sadrian qbusy = ath_hal_txqenabled(ah, txq->axq_qnum); 283218065Sadrian if (txq->axq_link == NULL) { 284218065Sadrian /* 285218065Sadrian * Be careful writing the address to TXDP. If 286218065Sadrian * the tx q is enabled then this write will be 287218065Sadrian * ignored. Normally this is not an issue but 288218065Sadrian * when tdma is in use and the q is beacon gated 289218065Sadrian * this race can occur. If the q is busy then 290218065Sadrian * defer the work to later--either when another 291218065Sadrian * packet comes along or when we prepare a beacon 292218065Sadrian * frame at SWBA. 293218065Sadrian */ 294218065Sadrian if (!qbusy) { 295218065Sadrian ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); 296218065Sadrian txq->axq_flags &= ~ATH_TXQ_PUTPENDING; 297218065Sadrian DPRINTF(sc, ATH_DEBUG_XMIT, 298218065Sadrian "%s: TXDP[%u] = %p (%p) depth %d\n", 299218065Sadrian __func__, txq->axq_qnum, 300218065Sadrian (caddr_t)bf->bf_daddr, bf->bf_desc, 301218065Sadrian txq->axq_depth); 302218065Sadrian } else { 303218065Sadrian txq->axq_flags |= ATH_TXQ_PUTPENDING; 304218065Sadrian DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT, 305218065Sadrian "%s: Q%u busy, defer enable\n", __func__, 306218065Sadrian txq->axq_qnum); 307218065Sadrian } 308218065Sadrian } else { 309218065Sadrian *txq->axq_link = bf->bf_daddr; 310218065Sadrian DPRINTF(sc, ATH_DEBUG_XMIT, 311218065Sadrian "%s: link[%u](%p)=%p (%p) depth %d\n", __func__, 312218065Sadrian txq->axq_qnum, txq->axq_link, 313218065Sadrian (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth); 314218065Sadrian if ((txq->axq_flags & ATH_TXQ_PUTPENDING) && !qbusy) { 315218065Sadrian /* 316218065Sadrian * The q was busy when we previously tried 317218065Sadrian * to write the address of the first buffer 318218065Sadrian * in the chain. Since it's not busy now 319218065Sadrian * handle this chore. We are certain the 320218065Sadrian * buffer at the front is the right one since 321218065Sadrian * axq_link is NULL only when the buffer list 322218065Sadrian * is/was empty. 323218065Sadrian */ 324218065Sadrian ath_hal_puttxbuf(ah, txq->axq_qnum, 325218065Sadrian STAILQ_FIRST(&txq->axq_q)->bf_daddr); 326218065Sadrian txq->axq_flags &= ~ATH_TXQ_PUTPENDING; 327218065Sadrian DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT, 328218065Sadrian "%s: Q%u restarted\n", __func__, 329218065Sadrian txq->axq_qnum); 330218065Sadrian } 331218065Sadrian } 332218065Sadrian#else 333218065Sadrian ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); 334218065Sadrian if (txq->axq_link == NULL) { 335218065Sadrian ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); 336218065Sadrian DPRINTF(sc, ATH_DEBUG_XMIT, 337218065Sadrian "%s: TXDP[%u] = %p (%p) depth %d\n", 338218065Sadrian __func__, txq->axq_qnum, 339218065Sadrian (caddr_t)bf->bf_daddr, bf->bf_desc, 340218065Sadrian txq->axq_depth); 341218065Sadrian } else { 342218065Sadrian *txq->axq_link = bf->bf_daddr; 343218065Sadrian DPRINTF(sc, ATH_DEBUG_XMIT, 344218065Sadrian "%s: link[%u](%p)=%p (%p) depth %d\n", __func__, 345218065Sadrian txq->axq_qnum, txq->axq_link, 346218065Sadrian (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth); 347218065Sadrian } 348218065Sadrian#endif /* IEEE80211_SUPPORT_TDMA */ 349218065Sadrian txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; 350218065Sadrian ath_hal_txstart(ah, txq->axq_qnum); 351218065Sadrian } else { 352218065Sadrian if (txq->axq_link != NULL) { 353218065Sadrian struct ath_buf *last = ATH_TXQ_LAST(txq); 354218065Sadrian struct ieee80211_frame *wh; 355218065Sadrian 356218065Sadrian /* mark previous frame */ 357218065Sadrian wh = mtod(last->bf_m, struct ieee80211_frame *); 358218065Sadrian wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA; 359218065Sadrian bus_dmamap_sync(sc->sc_dmat, last->bf_dmamap, 360218065Sadrian BUS_DMASYNC_PREWRITE); 361218065Sadrian 362218065Sadrian /* link descriptor */ 363218065Sadrian *txq->axq_link = bf->bf_daddr; 364218065Sadrian } 365218065Sadrian ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); 366218065Sadrian txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; 367218065Sadrian } 368218065Sadrian ATH_TXQ_UNLOCK(txq); 369218065Sadrian} 370218065Sadrian 371218154Sadrianstatic int 372218154Sadrianath_tx_tag_crypto(struct ath_softc *sc, struct ieee80211_node *ni, 373218154Sadrian struct mbuf *m0, int iswep, int isfrag, int *hdrlen, int *pktlen, int *keyix) 374218154Sadrian{ 375218154Sadrian if (iswep) { 376218154Sadrian const struct ieee80211_cipher *cip; 377218154Sadrian struct ieee80211_key *k; 378218154Sadrian 379218154Sadrian /* 380218154Sadrian * Construct the 802.11 header+trailer for an encrypted 381218154Sadrian * frame. The only reason this can fail is because of an 382218154Sadrian * unknown or unsupported cipher/key type. 383218154Sadrian */ 384218154Sadrian k = ieee80211_crypto_encap(ni, m0); 385218154Sadrian if (k == NULL) { 386218154Sadrian /* 387218154Sadrian * This can happen when the key is yanked after the 388218154Sadrian * frame was queued. Just discard the frame; the 389218154Sadrian * 802.11 layer counts failures and provides 390218154Sadrian * debugging/diagnostics. 391218154Sadrian */ 392218154Sadrian return 0; 393218154Sadrian } 394218154Sadrian /* 395218154Sadrian * Adjust the packet + header lengths for the crypto 396218154Sadrian * additions and calculate the h/w key index. When 397218154Sadrian * a s/w mic is done the frame will have had any mic 398218154Sadrian * added to it prior to entry so m0->m_pkthdr.len will 399218154Sadrian * account for it. Otherwise we need to add it to the 400218154Sadrian * packet length. 401218154Sadrian */ 402218154Sadrian cip = k->wk_cipher; 403218154Sadrian (*hdrlen) += cip->ic_header; 404218154Sadrian (*pktlen) += cip->ic_header + cip->ic_trailer; 405218154Sadrian /* NB: frags always have any TKIP MIC done in s/w */ 406218154Sadrian if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && !isfrag) 407218154Sadrian (*pktlen) += cip->ic_miclen; 408218154Sadrian (*keyix) = k->wk_keyix; 409218154Sadrian } else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) { 410218154Sadrian /* 411218154Sadrian * Use station key cache slot, if assigned. 412218154Sadrian */ 413218154Sadrian (*keyix) = ni->ni_ucastkey.wk_keyix; 414218154Sadrian if ((*keyix) == IEEE80211_KEYIX_NONE) 415218154Sadrian (*keyix) = HAL_TXKEYIX_INVALID; 416218154Sadrian } else 417218154Sadrian (*keyix) = HAL_TXKEYIX_INVALID; 418218154Sadrian 419218154Sadrian return 1; 420218154Sadrian} 421218154Sadrian 422218157Sadrianstatic void 423218157Sadrianath_tx_calc_ctsduration(struct ath_hal *ah, int rix, int cix, 424218157Sadrian int shortPreamble, int pktlen, const HAL_RATE_TABLE *rt, 425218157Sadrian int flags, u_int8_t *ctsrate, int *ctsduration) 426218157Sadrian{ 427218157Sadrian /* 428218157Sadrian * CTS transmit rate is derived from the transmit rate 429218157Sadrian * by looking in the h/w rate table. We must also factor 430218157Sadrian * in whether or not a short preamble is to be used. 431218157Sadrian */ 432218157Sadrian /* NB: cix is set above where RTS/CTS is enabled */ 433218157Sadrian KASSERT(cix != 0xff, ("cix not setup")); 434218157Sadrian (*ctsrate) = rt->info[cix].rateCode; 435218157Sadrian /* 436218157Sadrian * Compute the transmit duration based on the frame 437218157Sadrian * size and the size of an ACK frame. We call into the 438218157Sadrian * HAL to do the computation since it depends on the 439218157Sadrian * characteristics of the actual PHY being used. 440218157Sadrian * 441218157Sadrian * NB: CTS is assumed the same size as an ACK so we can 442218157Sadrian * use the precalculated ACK durations. 443218157Sadrian */ 444218157Sadrian if (shortPreamble) { 445218157Sadrian (*ctsrate) |= rt->info[cix].shortPreamble; 446218157Sadrian if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ 447218157Sadrian (*ctsduration) += rt->info[cix].spAckDuration; 448218157Sadrian (*ctsduration) += ath_hal_computetxtime(ah, 449218157Sadrian rt, pktlen, rix, AH_TRUE); 450218157Sadrian if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ 451218157Sadrian (*ctsduration) += rt->info[rix].spAckDuration; 452218157Sadrian } else { 453218157Sadrian if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ 454218157Sadrian (*ctsduration) += rt->info[cix].lpAckDuration; 455218157Sadrian (*ctsduration) += ath_hal_computetxtime(ah, 456218157Sadrian rt, pktlen, rix, AH_FALSE); 457218157Sadrian if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ 458218157Sadrian (*ctsduration) += rt->info[rix].lpAckDuration; 459218157Sadrian } 460218157Sadrian} 461218157Sadrian 462218065Sadrianint 463218065Sadrianath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, 464218065Sadrian struct mbuf *m0) 465218065Sadrian{ 466218065Sadrian struct ieee80211vap *vap = ni->ni_vap; 467218065Sadrian struct ath_vap *avp = ATH_VAP(vap); 468218065Sadrian struct ath_hal *ah = sc->sc_ah; 469218065Sadrian struct ifnet *ifp = sc->sc_ifp; 470218065Sadrian struct ieee80211com *ic = ifp->if_l2com; 471218065Sadrian const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams; 472218065Sadrian int error, iswep, ismcast, isfrag, ismrr; 473218065Sadrian int keyix, hdrlen, pktlen, try0; 474218065Sadrian u_int8_t rix, txrate, ctsrate; 475218065Sadrian u_int8_t cix = 0xff; /* NB: silence compiler */ 476218065Sadrian struct ath_desc *ds; 477218065Sadrian struct ath_txq *txq; 478218065Sadrian struct ieee80211_frame *wh; 479218065Sadrian u_int subtype, flags, ctsduration; 480218065Sadrian HAL_PKT_TYPE atype; 481218065Sadrian const HAL_RATE_TABLE *rt; 482218065Sadrian HAL_BOOL shortPreamble; 483218065Sadrian struct ath_node *an; 484218065Sadrian u_int pri; 485218065Sadrian 486218065Sadrian wh = mtod(m0, struct ieee80211_frame *); 487218065Sadrian iswep = wh->i_fc[1] & IEEE80211_FC1_WEP; 488218065Sadrian ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); 489218065Sadrian isfrag = m0->m_flags & M_FRAG; 490218065Sadrian hdrlen = ieee80211_anyhdrsize(wh); 491218065Sadrian /* 492218065Sadrian * Packet length must not include any 493218065Sadrian * pad bytes; deduct them here. 494218065Sadrian */ 495218065Sadrian pktlen = m0->m_pkthdr.len - (hdrlen & 3); 496218065Sadrian 497218154Sadrian /* Handle encryption twiddling if needed */ 498218154Sadrian if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen, &pktlen, &keyix)) { 499218154Sadrian ath_freetx(m0); 500218154Sadrian return EIO; 501218154Sadrian } 502218065Sadrian 503218154Sadrian /* packet header may have moved, reset our local pointer */ 504218154Sadrian wh = mtod(m0, struct ieee80211_frame *); 505218065Sadrian 506218065Sadrian pktlen += IEEE80211_CRC_LEN; 507218065Sadrian 508218065Sadrian /* 509218065Sadrian * Load the DMA map so any coalescing is done. This 510218065Sadrian * also calculates the number of descriptors we need. 511218065Sadrian */ 512218065Sadrian error = ath_tx_dmasetup(sc, bf, m0); 513218065Sadrian if (error != 0) 514218065Sadrian return error; 515218065Sadrian bf->bf_node = ni; /* NB: held reference */ 516218065Sadrian m0 = bf->bf_m; /* NB: may have changed */ 517218065Sadrian wh = mtod(m0, struct ieee80211_frame *); 518218065Sadrian 519218065Sadrian /* setup descriptors */ 520218065Sadrian ds = bf->bf_desc; 521218065Sadrian rt = sc->sc_currates; 522218065Sadrian KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 523218065Sadrian 524218065Sadrian /* 525218065Sadrian * NB: the 802.11 layer marks whether or not we should 526218065Sadrian * use short preamble based on the current mode and 527218065Sadrian * negotiated parameters. 528218065Sadrian */ 529218065Sadrian if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 530218065Sadrian (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) { 531218065Sadrian shortPreamble = AH_TRUE; 532218065Sadrian sc->sc_stats.ast_tx_shortpre++; 533218065Sadrian } else { 534218065Sadrian shortPreamble = AH_FALSE; 535218065Sadrian } 536218065Sadrian 537218065Sadrian an = ATH_NODE(ni); 538218065Sadrian flags = HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ 539218065Sadrian ismrr = 0; /* default no multi-rate retry*/ 540218065Sadrian pri = M_WME_GETAC(m0); /* honor classification */ 541218065Sadrian /* XXX use txparams instead of fixed values */ 542218065Sadrian /* 543218065Sadrian * Calculate Atheros packet type from IEEE80211 packet header, 544218065Sadrian * setup for rate calculations, and select h/w transmit queue. 545218065Sadrian */ 546218065Sadrian switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 547218065Sadrian case IEEE80211_FC0_TYPE_MGT: 548218065Sadrian subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 549218065Sadrian if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) 550218065Sadrian atype = HAL_PKT_TYPE_BEACON; 551218065Sadrian else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) 552218065Sadrian atype = HAL_PKT_TYPE_PROBE_RESP; 553218065Sadrian else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM) 554218065Sadrian atype = HAL_PKT_TYPE_ATIM; 555218065Sadrian else 556218065Sadrian atype = HAL_PKT_TYPE_NORMAL; /* XXX */ 557218065Sadrian rix = an->an_mgmtrix; 558218065Sadrian txrate = rt->info[rix].rateCode; 559218065Sadrian if (shortPreamble) 560218065Sadrian txrate |= rt->info[rix].shortPreamble; 561218065Sadrian try0 = ATH_TXMGTTRY; 562218065Sadrian flags |= HAL_TXDESC_INTREQ; /* force interrupt */ 563218065Sadrian break; 564218065Sadrian case IEEE80211_FC0_TYPE_CTL: 565218065Sadrian atype = HAL_PKT_TYPE_PSPOLL; /* stop setting of duration */ 566218065Sadrian rix = an->an_mgmtrix; 567218065Sadrian txrate = rt->info[rix].rateCode; 568218065Sadrian if (shortPreamble) 569218065Sadrian txrate |= rt->info[rix].shortPreamble; 570218065Sadrian try0 = ATH_TXMGTTRY; 571218065Sadrian flags |= HAL_TXDESC_INTREQ; /* force interrupt */ 572218065Sadrian break; 573218065Sadrian case IEEE80211_FC0_TYPE_DATA: 574218065Sadrian atype = HAL_PKT_TYPE_NORMAL; /* default */ 575218065Sadrian /* 576218065Sadrian * Data frames: multicast frames go out at a fixed rate, 577218065Sadrian * EAPOL frames use the mgmt frame rate; otherwise consult 578218065Sadrian * the rate control module for the rate to use. 579218065Sadrian */ 580218065Sadrian if (ismcast) { 581218065Sadrian rix = an->an_mcastrix; 582218065Sadrian txrate = rt->info[rix].rateCode; 583218065Sadrian if (shortPreamble) 584218065Sadrian txrate |= rt->info[rix].shortPreamble; 585218065Sadrian try0 = 1; 586218065Sadrian } else if (m0->m_flags & M_EAPOL) { 587218065Sadrian /* XXX? maybe always use long preamble? */ 588218065Sadrian rix = an->an_mgmtrix; 589218065Sadrian txrate = rt->info[rix].rateCode; 590218065Sadrian if (shortPreamble) 591218065Sadrian txrate |= rt->info[rix].shortPreamble; 592218065Sadrian try0 = ATH_TXMAXTRY; /* XXX?too many? */ 593218065Sadrian } else { 594218065Sadrian ath_rate_findrate(sc, an, shortPreamble, pktlen, 595218065Sadrian &rix, &try0, &txrate); 596218065Sadrian sc->sc_txrix = rix; /* for LED blinking */ 597218065Sadrian sc->sc_lastdatarix = rix; /* for fast frames */ 598218065Sadrian if (try0 != ATH_TXMAXTRY) 599218065Sadrian ismrr = 1; 600218065Sadrian } 601218065Sadrian if (cap->cap_wmeParams[pri].wmep_noackPolicy) 602218065Sadrian flags |= HAL_TXDESC_NOACK; 603218065Sadrian break; 604218065Sadrian default: 605218065Sadrian if_printf(ifp, "bogus frame type 0x%x (%s)\n", 606218065Sadrian wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); 607218065Sadrian /* XXX statistic */ 608218065Sadrian ath_freetx(m0); 609218065Sadrian return EIO; 610218065Sadrian } 611218065Sadrian txq = sc->sc_ac2q[pri]; 612218065Sadrian 613218065Sadrian /* 614218065Sadrian * When servicing one or more stations in power-save mode 615218065Sadrian * (or) if there is some mcast data waiting on the mcast 616218065Sadrian * queue (to prevent out of order delivery) multicast 617218065Sadrian * frames must be buffered until after the beacon. 618218065Sadrian */ 619218065Sadrian if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth)) 620218065Sadrian txq = &avp->av_mcastq; 621218065Sadrian 622218065Sadrian /* 623218065Sadrian * Calculate miscellaneous flags. 624218065Sadrian */ 625218065Sadrian if (ismcast) { 626218065Sadrian flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */ 627218065Sadrian } else if (pktlen > vap->iv_rtsthreshold && 628218065Sadrian (ni->ni_ath_flags & IEEE80211_NODE_FF) == 0) { 629218065Sadrian flags |= HAL_TXDESC_RTSENA; /* RTS based on frame length */ 630218065Sadrian cix = rt->info[rix].controlRate; 631218065Sadrian sc->sc_stats.ast_tx_rts++; 632218065Sadrian } 633218065Sadrian if (flags & HAL_TXDESC_NOACK) /* NB: avoid double counting */ 634218065Sadrian sc->sc_stats.ast_tx_noack++; 635218065Sadrian#ifdef IEEE80211_SUPPORT_TDMA 636218065Sadrian if (sc->sc_tdma && (flags & HAL_TXDESC_NOACK) == 0) { 637218065Sadrian DPRINTF(sc, ATH_DEBUG_TDMA, 638218065Sadrian "%s: discard frame, ACK required w/ TDMA\n", __func__); 639218065Sadrian sc->sc_stats.ast_tdma_ack++; 640218065Sadrian ath_freetx(m0); 641218065Sadrian return EIO; 642218065Sadrian } 643218065Sadrian#endif 644218065Sadrian 645218065Sadrian /* 646218065Sadrian * If 802.11g protection is enabled, determine whether 647218065Sadrian * to use RTS/CTS or just CTS. Note that this is only 648218065Sadrian * done for OFDM unicast frames. 649218065Sadrian */ 650218065Sadrian if ((ic->ic_flags & IEEE80211_F_USEPROT) && 651218065Sadrian rt->info[rix].phy == IEEE80211_T_OFDM && 652218065Sadrian (flags & HAL_TXDESC_NOACK) == 0) { 653218065Sadrian /* XXX fragments must use CCK rates w/ protection */ 654218065Sadrian if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 655218065Sadrian flags |= HAL_TXDESC_RTSENA; 656218065Sadrian else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 657218065Sadrian flags |= HAL_TXDESC_CTSENA; 658218065Sadrian if (isfrag) { 659218065Sadrian /* 660218065Sadrian * For frags it would be desirable to use the 661218065Sadrian * highest CCK rate for RTS/CTS. But stations 662218065Sadrian * farther away may detect it at a lower CCK rate 663218065Sadrian * so use the configured protection rate instead 664218065Sadrian * (for now). 665218065Sadrian */ 666218065Sadrian cix = rt->info[sc->sc_protrix].controlRate; 667218065Sadrian } else 668218065Sadrian cix = rt->info[sc->sc_protrix].controlRate; 669218065Sadrian sc->sc_stats.ast_tx_protect++; 670218065Sadrian } 671218065Sadrian 672218065Sadrian /* 673218065Sadrian * Calculate duration. This logically belongs in the 802.11 674218065Sadrian * layer but it lacks sufficient information to calculate it. 675218065Sadrian */ 676218065Sadrian if ((flags & HAL_TXDESC_NOACK) == 0 && 677218065Sadrian (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) { 678218065Sadrian u_int16_t dur; 679218065Sadrian if (shortPreamble) 680218065Sadrian dur = rt->info[rix].spAckDuration; 681218065Sadrian else 682218065Sadrian dur = rt->info[rix].lpAckDuration; 683218065Sadrian if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) { 684218065Sadrian dur += dur; /* additional SIFS+ACK */ 685218065Sadrian KASSERT(m0->m_nextpkt != NULL, ("no fragment")); 686218065Sadrian /* 687218065Sadrian * Include the size of next fragment so NAV is 688218065Sadrian * updated properly. The last fragment uses only 689218065Sadrian * the ACK duration 690218065Sadrian */ 691218065Sadrian dur += ath_hal_computetxtime(ah, rt, 692218065Sadrian m0->m_nextpkt->m_pkthdr.len, 693218065Sadrian rix, shortPreamble); 694218065Sadrian } 695218065Sadrian if (isfrag) { 696218065Sadrian /* 697218065Sadrian * Force hardware to use computed duration for next 698218065Sadrian * fragment by disabling multi-rate retry which updates 699218065Sadrian * duration based on the multi-rate duration table. 700218065Sadrian */ 701218065Sadrian ismrr = 0; 702218065Sadrian try0 = ATH_TXMGTTRY; /* XXX? */ 703218065Sadrian } 704218065Sadrian *(u_int16_t *)wh->i_dur = htole16(dur); 705218065Sadrian } 706218065Sadrian 707218065Sadrian /* 708218065Sadrian * Calculate RTS/CTS rate and duration if needed. 709218065Sadrian */ 710218065Sadrian ctsduration = 0; 711218065Sadrian if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) { 712218157Sadrian (void) ath_tx_calc_ctsduration(ah, rix, cix, shortPreamble, pktlen, 713218157Sadrian rt, flags, &ctsrate, &ctsduration); 714218065Sadrian /* 715218065Sadrian * Must disable multi-rate retry when using RTS/CTS. 716218065Sadrian */ 717218065Sadrian ismrr = 0; 718218065Sadrian try0 = ATH_TXMGTTRY; /* XXX */ 719218065Sadrian } else 720218065Sadrian ctsrate = 0; 721218065Sadrian 722218065Sadrian /* 723218065Sadrian * At this point we are committed to sending the frame 724218065Sadrian * and we don't need to look at m_nextpkt; clear it in 725218065Sadrian * case this frame is part of frag chain. 726218065Sadrian */ 727218065Sadrian m0->m_nextpkt = NULL; 728218065Sadrian 729218065Sadrian if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) 730218065Sadrian ieee80211_dump_pkt(ic, mtod(m0, const uint8_t *), m0->m_len, 731218065Sadrian sc->sc_hwmap[rix].ieeerate, -1); 732218065Sadrian 733218065Sadrian if (ieee80211_radiotap_active_vap(vap)) { 734218065Sadrian u_int64_t tsf = ath_hal_gettsf64(ah); 735218065Sadrian 736218065Sadrian sc->sc_tx_th.wt_tsf = htole64(tsf); 737218065Sadrian sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags; 738218065Sadrian if (iswep) 739218065Sadrian sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; 740218065Sadrian if (isfrag) 741218065Sadrian sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG; 742218065Sadrian sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate; 743218065Sadrian sc->sc_tx_th.wt_txpower = ni->ni_txpower; 744218065Sadrian sc->sc_tx_th.wt_antenna = sc->sc_txantenna; 745218065Sadrian 746218065Sadrian ieee80211_radiotap_tx(vap, m0); 747218065Sadrian } 748218065Sadrian 749218065Sadrian /* 750218065Sadrian * Determine if a tx interrupt should be generated for 751218065Sadrian * this descriptor. We take a tx interrupt to reap 752218065Sadrian * descriptors when the h/w hits an EOL condition or 753218065Sadrian * when the descriptor is specifically marked to generate 754218065Sadrian * an interrupt. We periodically mark descriptors in this 755218065Sadrian * way to insure timely replenishing of the supply needed 756218065Sadrian * for sending frames. Defering interrupts reduces system 757218065Sadrian * load and potentially allows more concurrent work to be 758218065Sadrian * done but if done to aggressively can cause senders to 759218065Sadrian * backup. 760218065Sadrian * 761218065Sadrian * NB: use >= to deal with sc_txintrperiod changing 762218065Sadrian * dynamically through sysctl. 763218065Sadrian */ 764218065Sadrian if (flags & HAL_TXDESC_INTREQ) { 765218065Sadrian txq->axq_intrcnt = 0; 766218065Sadrian } else if (++txq->axq_intrcnt >= sc->sc_txintrperiod) { 767218065Sadrian flags |= HAL_TXDESC_INTREQ; 768218065Sadrian txq->axq_intrcnt = 0; 769218065Sadrian } 770218065Sadrian 771218065Sadrian /* 772218065Sadrian * Formulate first tx descriptor with tx controls. 773218065Sadrian */ 774218065Sadrian /* XXX check return value? */ 775218065Sadrian ath_hal_setuptxdesc(ah, ds 776218065Sadrian , pktlen /* packet length */ 777218065Sadrian , hdrlen /* header length */ 778218065Sadrian , atype /* Atheros packet type */ 779218065Sadrian , ni->ni_txpower /* txpower */ 780218065Sadrian , txrate, try0 /* series 0 rate/tries */ 781218065Sadrian , keyix /* key cache index */ 782218065Sadrian , sc->sc_txantenna /* antenna mode */ 783218065Sadrian , flags /* flags */ 784218065Sadrian , ctsrate /* rts/cts rate */ 785218065Sadrian , ctsduration /* rts/cts duration */ 786218065Sadrian ); 787218065Sadrian bf->bf_txflags = flags; 788218065Sadrian /* 789218065Sadrian * Setup the multi-rate retry state only when we're 790218065Sadrian * going to use it. This assumes ath_hal_setuptxdesc 791218065Sadrian * initializes the descriptors (so we don't have to) 792218065Sadrian * when the hardware supports multi-rate retry and 793218065Sadrian * we don't use it. 794218065Sadrian */ 795218065Sadrian if (ismrr) 796218065Sadrian ath_rate_setupxtxdesc(sc, an, ds, shortPreamble, rix); 797218065Sadrian 798218065Sadrian ath_tx_handoff(sc, txq, bf); 799218065Sadrian return 0; 800218065Sadrian} 801218065Sadrian 802218065Sadrianstatic int 803218065Sadrianath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, 804218065Sadrian struct ath_buf *bf, struct mbuf *m0, 805218065Sadrian const struct ieee80211_bpf_params *params) 806218065Sadrian{ 807218065Sadrian struct ifnet *ifp = sc->sc_ifp; 808218065Sadrian struct ieee80211com *ic = ifp->if_l2com; 809218065Sadrian struct ath_hal *ah = sc->sc_ah; 810218065Sadrian struct ieee80211vap *vap = ni->ni_vap; 811218065Sadrian int error, ismcast, ismrr; 812218065Sadrian int keyix, hdrlen, pktlen, try0, txantenna; 813218065Sadrian u_int8_t rix, cix, txrate, ctsrate, rate1, rate2, rate3; 814218065Sadrian struct ieee80211_frame *wh; 815218065Sadrian u_int flags, ctsduration; 816218065Sadrian HAL_PKT_TYPE atype; 817218065Sadrian const HAL_RATE_TABLE *rt; 818218065Sadrian struct ath_desc *ds; 819218065Sadrian u_int pri; 820218065Sadrian 821218065Sadrian wh = mtod(m0, struct ieee80211_frame *); 822218065Sadrian ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); 823218065Sadrian hdrlen = ieee80211_anyhdrsize(wh); 824218065Sadrian /* 825218065Sadrian * Packet length must not include any 826218065Sadrian * pad bytes; deduct them here. 827218065Sadrian */ 828218065Sadrian /* XXX honor IEEE80211_BPF_DATAPAD */ 829218065Sadrian pktlen = m0->m_pkthdr.len - (hdrlen & 3) + IEEE80211_CRC_LEN; 830218065Sadrian 831218154Sadrian /* Handle encryption twiddling if needed */ 832218154Sadrian if (! ath_tx_tag_crypto(sc, ni, m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0, &hdrlen, &pktlen, &keyix)) { 833218154Sadrian ath_freetx(m0); 834218154Sadrian return EIO; 835218154Sadrian } 836218154Sadrian /* packet header may have moved, reset our local pointer */ 837218154Sadrian wh = mtod(m0, struct ieee80211_frame *); 838218065Sadrian 839218065Sadrian error = ath_tx_dmasetup(sc, bf, m0); 840218065Sadrian if (error != 0) 841218065Sadrian return error; 842218065Sadrian m0 = bf->bf_m; /* NB: may have changed */ 843218065Sadrian wh = mtod(m0, struct ieee80211_frame *); 844218065Sadrian bf->bf_node = ni; /* NB: held reference */ 845218065Sadrian 846218065Sadrian flags = HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ 847218065Sadrian flags |= HAL_TXDESC_INTREQ; /* force interrupt */ 848218065Sadrian if (params->ibp_flags & IEEE80211_BPF_RTS) 849218065Sadrian flags |= HAL_TXDESC_RTSENA; 850218065Sadrian else if (params->ibp_flags & IEEE80211_BPF_CTS) 851218065Sadrian flags |= HAL_TXDESC_CTSENA; 852218065Sadrian /* XXX leave ismcast to injector? */ 853218065Sadrian if ((params->ibp_flags & IEEE80211_BPF_NOACK) || ismcast) 854218065Sadrian flags |= HAL_TXDESC_NOACK; 855218065Sadrian 856218065Sadrian rt = sc->sc_currates; 857218065Sadrian KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 858218065Sadrian rix = ath_tx_findrix(sc, params->ibp_rate0); 859218065Sadrian txrate = rt->info[rix].rateCode; 860218065Sadrian if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) 861218065Sadrian txrate |= rt->info[rix].shortPreamble; 862218065Sadrian sc->sc_txrix = rix; 863218065Sadrian try0 = params->ibp_try0; 864218065Sadrian ismrr = (params->ibp_try1 != 0); 865218065Sadrian txantenna = params->ibp_pri >> 2; 866218065Sadrian if (txantenna == 0) /* XXX? */ 867218065Sadrian txantenna = sc->sc_txantenna; 868218157Sadrian 869218065Sadrian ctsduration = 0; 870218157Sadrian if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) { 871218065Sadrian cix = ath_tx_findrix(sc, params->ibp_ctsrate); 872218157Sadrian (void) ath_tx_calc_ctsduration(ah, rix, cix, 873218157Sadrian params->ibp_flags & IEEE80211_BPF_SHORTPRE, pktlen, 874218157Sadrian rt, flags, &ctsrate, &ctsduration); 875218157Sadrian /* 876218157Sadrian * Must disable multi-rate retry when using RTS/CTS. 877218157Sadrian */ 878218065Sadrian ismrr = 0; /* XXX */ 879218065Sadrian } else 880218065Sadrian ctsrate = 0; 881218157Sadrian 882218065Sadrian pri = params->ibp_pri & 3; 883218065Sadrian /* 884218065Sadrian * NB: we mark all packets as type PSPOLL so the h/w won't 885218065Sadrian * set the sequence number, duration, etc. 886218065Sadrian */ 887218065Sadrian atype = HAL_PKT_TYPE_PSPOLL; 888218065Sadrian 889218065Sadrian if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) 890218065Sadrian ieee80211_dump_pkt(ic, mtod(m0, caddr_t), m0->m_len, 891218065Sadrian sc->sc_hwmap[rix].ieeerate, -1); 892218065Sadrian 893218065Sadrian if (ieee80211_radiotap_active_vap(vap)) { 894218065Sadrian u_int64_t tsf = ath_hal_gettsf64(ah); 895218065Sadrian 896218065Sadrian sc->sc_tx_th.wt_tsf = htole64(tsf); 897218065Sadrian sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags; 898218065Sadrian if (wh->i_fc[1] & IEEE80211_FC1_WEP) 899218065Sadrian sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; 900218065Sadrian if (m0->m_flags & M_FRAG) 901218065Sadrian sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG; 902218065Sadrian sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate; 903218065Sadrian sc->sc_tx_th.wt_txpower = ni->ni_txpower; 904218065Sadrian sc->sc_tx_th.wt_antenna = sc->sc_txantenna; 905218065Sadrian 906218065Sadrian ieee80211_radiotap_tx(vap, m0); 907218065Sadrian } 908218065Sadrian 909218065Sadrian /* 910218065Sadrian * Formulate first tx descriptor with tx controls. 911218065Sadrian */ 912218065Sadrian ds = bf->bf_desc; 913218065Sadrian /* XXX check return value? */ 914218065Sadrian ath_hal_setuptxdesc(ah, ds 915218065Sadrian , pktlen /* packet length */ 916218065Sadrian , hdrlen /* header length */ 917218065Sadrian , atype /* Atheros packet type */ 918218065Sadrian , params->ibp_power /* txpower */ 919218065Sadrian , txrate, try0 /* series 0 rate/tries */ 920218065Sadrian , keyix /* key cache index */ 921218065Sadrian , txantenna /* antenna mode */ 922218065Sadrian , flags /* flags */ 923218065Sadrian , ctsrate /* rts/cts rate */ 924218065Sadrian , ctsduration /* rts/cts duration */ 925218065Sadrian ); 926218065Sadrian bf->bf_txflags = flags; 927218065Sadrian 928218065Sadrian if (ismrr) { 929218065Sadrian rix = ath_tx_findrix(sc, params->ibp_rate1); 930218065Sadrian rate1 = rt->info[rix].rateCode; 931218065Sadrian if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) 932218065Sadrian rate1 |= rt->info[rix].shortPreamble; 933218065Sadrian if (params->ibp_try2) { 934218065Sadrian rix = ath_tx_findrix(sc, params->ibp_rate2); 935218065Sadrian rate2 = rt->info[rix].rateCode; 936218065Sadrian if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) 937218065Sadrian rate2 |= rt->info[rix].shortPreamble; 938218065Sadrian } else 939218065Sadrian rate2 = 0; 940218065Sadrian if (params->ibp_try3) { 941218065Sadrian rix = ath_tx_findrix(sc, params->ibp_rate3); 942218065Sadrian rate3 = rt->info[rix].rateCode; 943218065Sadrian if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) 944218065Sadrian rate3 |= rt->info[rix].shortPreamble; 945218065Sadrian } else 946218065Sadrian rate3 = 0; 947218065Sadrian ath_hal_setupxtxdesc(ah, ds 948218065Sadrian , rate1, params->ibp_try1 /* series 1 */ 949218065Sadrian , rate2, params->ibp_try2 /* series 2 */ 950218065Sadrian , rate3, params->ibp_try3 /* series 3 */ 951218065Sadrian ); 952218065Sadrian } 953218065Sadrian 954218065Sadrian /* NB: no buffered multicast in power save support */ 955218065Sadrian ath_tx_handoff(sc, sc->sc_ac2q[pri], bf); 956218065Sadrian return 0; 957218065Sadrian} 958218065Sadrian 959218065Sadrianint 960218065Sadrianath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 961218065Sadrian const struct ieee80211_bpf_params *params) 962218065Sadrian{ 963218065Sadrian struct ieee80211com *ic = ni->ni_ic; 964218065Sadrian struct ifnet *ifp = ic->ic_ifp; 965218065Sadrian struct ath_softc *sc = ifp->if_softc; 966218065Sadrian struct ath_buf *bf; 967218065Sadrian int error; 968218065Sadrian 969218065Sadrian if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) { 970218065Sadrian DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__, 971218065Sadrian (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ? 972218065Sadrian "!running" : "invalid"); 973218065Sadrian m_freem(m); 974218065Sadrian error = ENETDOWN; 975218065Sadrian goto bad; 976218065Sadrian } 977218065Sadrian /* 978218065Sadrian * Grab a TX buffer and associated resources. 979218065Sadrian */ 980218065Sadrian bf = ath_getbuf(sc); 981218065Sadrian if (bf == NULL) { 982218065Sadrian sc->sc_stats.ast_tx_nobuf++; 983218065Sadrian m_freem(m); 984218065Sadrian error = ENOBUFS; 985218065Sadrian goto bad; 986218065Sadrian } 987218065Sadrian 988218065Sadrian if (params == NULL) { 989218065Sadrian /* 990218065Sadrian * Legacy path; interpret frame contents to decide 991218065Sadrian * precisely how to send the frame. 992218065Sadrian */ 993218065Sadrian if (ath_tx_start(sc, ni, bf, m)) { 994218065Sadrian error = EIO; /* XXX */ 995218065Sadrian goto bad2; 996218065Sadrian } 997218065Sadrian } else { 998218065Sadrian /* 999218065Sadrian * Caller supplied explicit parameters to use in 1000218065Sadrian * sending the frame. 1001218065Sadrian */ 1002218065Sadrian if (ath_tx_raw_start(sc, ni, bf, m, params)) { 1003218065Sadrian error = EIO; /* XXX */ 1004218065Sadrian goto bad2; 1005218065Sadrian } 1006218065Sadrian } 1007218065Sadrian sc->sc_wd_timer = 5; 1008218065Sadrian ifp->if_opackets++; 1009218065Sadrian sc->sc_stats.ast_tx_raw++; 1010218065Sadrian 1011218065Sadrian return 0; 1012218065Sadrianbad2: 1013218065Sadrian ATH_TXBUF_LOCK(sc); 1014218065Sadrian STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); 1015218065Sadrian ATH_TXBUF_UNLOCK(sc); 1016218065Sadrianbad: 1017218065Sadrian ifp->if_oerrors++; 1018218065Sadrian sc->sc_stats.ast_tx_raw_fail++; 1019218065Sadrian ieee80211_free_node(ni); 1020218065Sadrian return error; 1021218065Sadrian} 1022