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