1b8e788a5SAdrian Chadd /*- 2b8e788a5SAdrian Chadd * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3b8e788a5SAdrian Chadd * All rights reserved. 4b8e788a5SAdrian Chadd * 5b8e788a5SAdrian Chadd * Redistribution and use in source and binary forms, with or without 6b8e788a5SAdrian Chadd * modification, are permitted provided that the following conditions 7b8e788a5SAdrian Chadd * are met: 8b8e788a5SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 9b8e788a5SAdrian Chadd * notice, this list of conditions and the following disclaimer, 10b8e788a5SAdrian Chadd * without modification. 11b8e788a5SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12b8e788a5SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13b8e788a5SAdrian Chadd * redistribution must be conditioned upon including a substantially 14b8e788a5SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 15b8e788a5SAdrian Chadd * 16b8e788a5SAdrian Chadd * NO WARRANTY 17b8e788a5SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18b8e788a5SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19b8e788a5SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20b8e788a5SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21b8e788a5SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22b8e788a5SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23b8e788a5SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24b8e788a5SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25b8e788a5SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26b8e788a5SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27b8e788a5SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 28b8e788a5SAdrian Chadd */ 29b8e788a5SAdrian Chadd 30b8e788a5SAdrian Chadd #include <sys/cdefs.h> 31b8e788a5SAdrian Chadd __FBSDID("$FreeBSD$"); 32b8e788a5SAdrian Chadd 33b8e788a5SAdrian Chadd /* 34b8e788a5SAdrian Chadd * Driver for the Atheros Wireless LAN controller. 35b8e788a5SAdrian Chadd * 36b8e788a5SAdrian Chadd * This software is derived from work of Atsushi Onoe; his contribution 37b8e788a5SAdrian Chadd * is greatly appreciated. 38b8e788a5SAdrian Chadd */ 39b8e788a5SAdrian Chadd 40b8e788a5SAdrian Chadd #include "opt_inet.h" 41b8e788a5SAdrian Chadd #include "opt_ath.h" 42b8e788a5SAdrian Chadd #include "opt_wlan.h" 43b8e788a5SAdrian Chadd 44b8e788a5SAdrian Chadd #include <sys/param.h> 45b8e788a5SAdrian Chadd #include <sys/systm.h> 46b8e788a5SAdrian Chadd #include <sys/sysctl.h> 47b8e788a5SAdrian Chadd #include <sys/mbuf.h> 48b8e788a5SAdrian Chadd #include <sys/malloc.h> 49b8e788a5SAdrian Chadd #include <sys/lock.h> 50b8e788a5SAdrian Chadd #include <sys/mutex.h> 51b8e788a5SAdrian Chadd #include <sys/kernel.h> 52b8e788a5SAdrian Chadd #include <sys/socket.h> 53b8e788a5SAdrian Chadd #include <sys/sockio.h> 54b8e788a5SAdrian Chadd #include <sys/errno.h> 55b8e788a5SAdrian Chadd #include <sys/callout.h> 56b8e788a5SAdrian Chadd #include <sys/bus.h> 57b8e788a5SAdrian Chadd #include <sys/endian.h> 58b8e788a5SAdrian Chadd #include <sys/kthread.h> 59b8e788a5SAdrian Chadd #include <sys/taskqueue.h> 60b8e788a5SAdrian Chadd #include <sys/priv.h> 61b8e788a5SAdrian Chadd 62b8e788a5SAdrian Chadd #include <machine/bus.h> 63b8e788a5SAdrian Chadd 64b8e788a5SAdrian Chadd #include <net/if.h> 65b8e788a5SAdrian Chadd #include <net/if_dl.h> 66b8e788a5SAdrian Chadd #include <net/if_media.h> 67b8e788a5SAdrian Chadd #include <net/if_types.h> 68b8e788a5SAdrian Chadd #include <net/if_arp.h> 69b8e788a5SAdrian Chadd #include <net/ethernet.h> 70b8e788a5SAdrian Chadd #include <net/if_llc.h> 71b8e788a5SAdrian Chadd 72b8e788a5SAdrian Chadd #include <net80211/ieee80211_var.h> 73b8e788a5SAdrian Chadd #include <net80211/ieee80211_regdomain.h> 74b8e788a5SAdrian Chadd #ifdef IEEE80211_SUPPORT_SUPERG 75b8e788a5SAdrian Chadd #include <net80211/ieee80211_superg.h> 76b8e788a5SAdrian Chadd #endif 77b8e788a5SAdrian Chadd #ifdef IEEE80211_SUPPORT_TDMA 78b8e788a5SAdrian Chadd #include <net80211/ieee80211_tdma.h> 79b8e788a5SAdrian Chadd #endif 80b8e788a5SAdrian Chadd 81b8e788a5SAdrian Chadd #include <net/bpf.h> 82b8e788a5SAdrian Chadd 83b8e788a5SAdrian Chadd #ifdef INET 84b8e788a5SAdrian Chadd #include <netinet/in.h> 85b8e788a5SAdrian Chadd #include <netinet/if_ether.h> 86b8e788a5SAdrian Chadd #endif 87b8e788a5SAdrian Chadd 88b8e788a5SAdrian Chadd #include <dev/ath/if_athvar.h> 89b8e788a5SAdrian Chadd #include <dev/ath/ath_hal/ah_devid.h> /* XXX for softled */ 90b8e788a5SAdrian Chadd #include <dev/ath/ath_hal/ah_diagcodes.h> 91b8e788a5SAdrian Chadd 92b8e788a5SAdrian Chadd #include <dev/ath/if_ath_debug.h> 93b8e788a5SAdrian Chadd 94b8e788a5SAdrian Chadd #ifdef ATH_TX99_DIAG 95b8e788a5SAdrian Chadd #include <dev/ath/ath_tx99/ath_tx99.h> 96b8e788a5SAdrian Chadd #endif 97b8e788a5SAdrian Chadd 98b8e788a5SAdrian Chadd #include <dev/ath/if_ath_misc.h> 99b8e788a5SAdrian Chadd #include <dev/ath/if_ath_tx.h> 100c1782ce0SAdrian Chadd #include <dev/ath/if_ath_tx_ht.h> 101b8e788a5SAdrian Chadd 10281a82688SAdrian Chadd /* 10381a82688SAdrian Chadd * Whether to use the 11n rate scenario functions or not 10481a82688SAdrian Chadd */ 10581a82688SAdrian Chadd static inline int 10681a82688SAdrian Chadd ath_tx_is_11n(struct ath_softc *sc) 10781a82688SAdrian Chadd { 10881a82688SAdrian Chadd return (sc->sc_ah->ah_magic == 0x20065416); 10981a82688SAdrian Chadd } 11081a82688SAdrian Chadd 111b8e788a5SAdrian Chadd void 112b8e788a5SAdrian Chadd ath_txfrag_cleanup(struct ath_softc *sc, 113b8e788a5SAdrian Chadd ath_bufhead *frags, struct ieee80211_node *ni) 114b8e788a5SAdrian Chadd { 115b8e788a5SAdrian Chadd struct ath_buf *bf, *next; 116b8e788a5SAdrian Chadd 117b8e788a5SAdrian Chadd ATH_TXBUF_LOCK_ASSERT(sc); 118b8e788a5SAdrian Chadd 1196b349e5aSAdrian Chadd TAILQ_FOREACH_SAFE(bf, frags, bf_list, next) { 120b8e788a5SAdrian Chadd /* NB: bf assumed clean */ 1216b349e5aSAdrian Chadd TAILQ_REMOVE(frags, bf, bf_list); 1226b349e5aSAdrian Chadd TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); 123b8e788a5SAdrian Chadd ieee80211_node_decref(ni); 124b8e788a5SAdrian Chadd } 125b8e788a5SAdrian Chadd } 126b8e788a5SAdrian Chadd 127b8e788a5SAdrian Chadd /* 128b8e788a5SAdrian Chadd * Setup xmit of a fragmented frame. Allocate a buffer 129b8e788a5SAdrian Chadd * for each frag and bump the node reference count to 130b8e788a5SAdrian Chadd * reflect the held reference to be setup by ath_tx_start. 131b8e788a5SAdrian Chadd */ 132b8e788a5SAdrian Chadd int 133b8e788a5SAdrian Chadd ath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags, 134b8e788a5SAdrian Chadd struct mbuf *m0, struct ieee80211_node *ni) 135b8e788a5SAdrian Chadd { 136b8e788a5SAdrian Chadd struct mbuf *m; 137b8e788a5SAdrian Chadd struct ath_buf *bf; 138b8e788a5SAdrian Chadd 139b8e788a5SAdrian Chadd ATH_TXBUF_LOCK(sc); 140b8e788a5SAdrian Chadd for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) { 141b8e788a5SAdrian Chadd bf = _ath_getbuf_locked(sc); 142b8e788a5SAdrian Chadd if (bf == NULL) { /* out of buffers, cleanup */ 143b8e788a5SAdrian Chadd ath_txfrag_cleanup(sc, frags, ni); 144b8e788a5SAdrian Chadd break; 145b8e788a5SAdrian Chadd } 146b8e788a5SAdrian Chadd ieee80211_node_incref(ni); 1476b349e5aSAdrian Chadd TAILQ_INSERT_TAIL(frags, bf, bf_list); 148b8e788a5SAdrian Chadd } 149b8e788a5SAdrian Chadd ATH_TXBUF_UNLOCK(sc); 150b8e788a5SAdrian Chadd 1516b349e5aSAdrian Chadd return !TAILQ_EMPTY(frags); 152b8e788a5SAdrian Chadd } 153b8e788a5SAdrian Chadd 154b8e788a5SAdrian Chadd /* 155b8e788a5SAdrian Chadd * Reclaim mbuf resources. For fragmented frames we 156b8e788a5SAdrian Chadd * need to claim each frag chained with m_nextpkt. 157b8e788a5SAdrian Chadd */ 158b8e788a5SAdrian Chadd void 159b8e788a5SAdrian Chadd ath_freetx(struct mbuf *m) 160b8e788a5SAdrian Chadd { 161b8e788a5SAdrian Chadd struct mbuf *next; 162b8e788a5SAdrian Chadd 163b8e788a5SAdrian Chadd do { 164b8e788a5SAdrian Chadd next = m->m_nextpkt; 165b8e788a5SAdrian Chadd m->m_nextpkt = NULL; 166b8e788a5SAdrian Chadd m_freem(m); 167b8e788a5SAdrian Chadd } while ((m = next) != NULL); 168b8e788a5SAdrian Chadd } 169b8e788a5SAdrian Chadd 170b8e788a5SAdrian Chadd static int 171b8e788a5SAdrian Chadd ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) 172b8e788a5SAdrian Chadd { 173b8e788a5SAdrian Chadd struct mbuf *m; 174b8e788a5SAdrian Chadd int error; 175b8e788a5SAdrian Chadd 176b8e788a5SAdrian Chadd /* 177b8e788a5SAdrian Chadd * Load the DMA map so any coalescing is done. This 178b8e788a5SAdrian Chadd * also calculates the number of descriptors we need. 179b8e788a5SAdrian Chadd */ 180b8e788a5SAdrian Chadd error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0, 181b8e788a5SAdrian Chadd bf->bf_segs, &bf->bf_nseg, 182b8e788a5SAdrian Chadd BUS_DMA_NOWAIT); 183b8e788a5SAdrian Chadd if (error == EFBIG) { 184b8e788a5SAdrian Chadd /* XXX packet requires too many descriptors */ 185b8e788a5SAdrian Chadd bf->bf_nseg = ATH_TXDESC+1; 186b8e788a5SAdrian Chadd } else if (error != 0) { 187b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_busdma++; 188b8e788a5SAdrian Chadd ath_freetx(m0); 189b8e788a5SAdrian Chadd return error; 190b8e788a5SAdrian Chadd } 191b8e788a5SAdrian Chadd /* 192b8e788a5SAdrian Chadd * Discard null packets and check for packets that 193b8e788a5SAdrian Chadd * require too many TX descriptors. We try to convert 194b8e788a5SAdrian Chadd * the latter to a cluster. 195b8e788a5SAdrian Chadd */ 196b8e788a5SAdrian Chadd if (bf->bf_nseg > ATH_TXDESC) { /* too many desc's, linearize */ 197b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_linear++; 198b8e788a5SAdrian Chadd m = m_collapse(m0, M_DONTWAIT, ATH_TXDESC); 199b8e788a5SAdrian Chadd if (m == NULL) { 200b8e788a5SAdrian Chadd ath_freetx(m0); 201b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_nombuf++; 202b8e788a5SAdrian Chadd return ENOMEM; 203b8e788a5SAdrian Chadd } 204b8e788a5SAdrian Chadd m0 = m; 205b8e788a5SAdrian Chadd error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0, 206b8e788a5SAdrian Chadd bf->bf_segs, &bf->bf_nseg, 207b8e788a5SAdrian Chadd BUS_DMA_NOWAIT); 208b8e788a5SAdrian Chadd if (error != 0) { 209b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_busdma++; 210b8e788a5SAdrian Chadd ath_freetx(m0); 211b8e788a5SAdrian Chadd return error; 212b8e788a5SAdrian Chadd } 213b8e788a5SAdrian Chadd KASSERT(bf->bf_nseg <= ATH_TXDESC, 214b8e788a5SAdrian Chadd ("too many segments after defrag; nseg %u", bf->bf_nseg)); 215b8e788a5SAdrian Chadd } else if (bf->bf_nseg == 0) { /* null packet, discard */ 216b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_nodata++; 217b8e788a5SAdrian Chadd ath_freetx(m0); 218b8e788a5SAdrian Chadd return EIO; 219b8e788a5SAdrian Chadd } 220b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n", 221b8e788a5SAdrian Chadd __func__, m0, m0->m_pkthdr.len); 222b8e788a5SAdrian Chadd bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE); 223b8e788a5SAdrian Chadd bf->bf_m = m0; 224b8e788a5SAdrian Chadd 225b8e788a5SAdrian Chadd return 0; 226b8e788a5SAdrian Chadd } 227b8e788a5SAdrian Chadd 228*6edf1dc7SAdrian Chadd /* 229*6edf1dc7SAdrian Chadd * Chain together segments+descriptors for a non-11n frame. 230*6edf1dc7SAdrian Chadd */ 231b8e788a5SAdrian Chadd static void 23281a82688SAdrian Chadd ath_tx_chaindesclist(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf) 233b8e788a5SAdrian Chadd { 234b8e788a5SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 235b8e788a5SAdrian Chadd struct ath_desc *ds, *ds0; 236b8e788a5SAdrian Chadd int i; 237b8e788a5SAdrian Chadd 238b8e788a5SAdrian Chadd /* 239b8e788a5SAdrian Chadd * Fillin the remainder of the descriptor info. 240b8e788a5SAdrian Chadd */ 241b8e788a5SAdrian Chadd ds0 = ds = bf->bf_desc; 242b8e788a5SAdrian Chadd for (i = 0; i < bf->bf_nseg; i++, ds++) { 243b8e788a5SAdrian Chadd ds->ds_data = bf->bf_segs[i].ds_addr; 244b8e788a5SAdrian Chadd if (i == bf->bf_nseg - 1) 245b8e788a5SAdrian Chadd ds->ds_link = 0; 246b8e788a5SAdrian Chadd else 247b8e788a5SAdrian Chadd ds->ds_link = bf->bf_daddr + sizeof(*ds) * (i + 1); 248b8e788a5SAdrian Chadd ath_hal_filltxdesc(ah, ds 249b8e788a5SAdrian Chadd , bf->bf_segs[i].ds_len /* segment length */ 250b8e788a5SAdrian Chadd , i == 0 /* first segment */ 251b8e788a5SAdrian Chadd , i == bf->bf_nseg - 1 /* last segment */ 252b8e788a5SAdrian Chadd , ds0 /* first descriptor */ 253b8e788a5SAdrian Chadd ); 254b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_XMIT, 255b8e788a5SAdrian Chadd "%s: %d: %08x %08x %08x %08x %08x %08x\n", 256b8e788a5SAdrian Chadd __func__, i, ds->ds_link, ds->ds_data, 257b8e788a5SAdrian Chadd ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]); 258*6edf1dc7SAdrian Chadd bf->bf_lastds = ds; 259b8e788a5SAdrian Chadd } 26081a82688SAdrian Chadd } 26181a82688SAdrian Chadd 26281a82688SAdrian Chadd static void 26381a82688SAdrian Chadd ath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf) 26481a82688SAdrian Chadd { 26581a82688SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 26681a82688SAdrian Chadd 26781a82688SAdrian Chadd /* Fill in the details in the descriptor list */ 26881a82688SAdrian Chadd ath_tx_chaindesclist(sc, txq, bf); 26981a82688SAdrian Chadd 270b8e788a5SAdrian Chadd /* 271b8e788a5SAdrian Chadd * Insert the frame on the outbound list and pass it on 272b8e788a5SAdrian Chadd * to the hardware. Multicast frames buffered for power 273b8e788a5SAdrian Chadd * save stations and transmit from the CAB queue are stored 274b8e788a5SAdrian Chadd * on a s/w only queue and loaded on to the CAB queue in 275b8e788a5SAdrian Chadd * the SWBA handler since frames only go out on DTIM and 276b8e788a5SAdrian Chadd * to avoid possible races. 277b8e788a5SAdrian Chadd */ 278b8e788a5SAdrian Chadd ATH_TXQ_LOCK(txq); 279b8e788a5SAdrian Chadd KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0, 280b8e788a5SAdrian Chadd ("busy status 0x%x", bf->bf_flags)); 281b8e788a5SAdrian Chadd if (txq->axq_qnum != ATH_TXQ_SWQ) { 282b8e788a5SAdrian Chadd #ifdef IEEE80211_SUPPORT_TDMA 283b8e788a5SAdrian Chadd int qbusy; 284b8e788a5SAdrian Chadd 285b8e788a5SAdrian Chadd ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); 286b8e788a5SAdrian Chadd qbusy = ath_hal_txqenabled(ah, txq->axq_qnum); 287b8e788a5SAdrian Chadd if (txq->axq_link == NULL) { 288b8e788a5SAdrian Chadd /* 289b8e788a5SAdrian Chadd * Be careful writing the address to TXDP. If 290b8e788a5SAdrian Chadd * the tx q is enabled then this write will be 291b8e788a5SAdrian Chadd * ignored. Normally this is not an issue but 292b8e788a5SAdrian Chadd * when tdma is in use and the q is beacon gated 293b8e788a5SAdrian Chadd * this race can occur. If the q is busy then 294b8e788a5SAdrian Chadd * defer the work to later--either when another 295b8e788a5SAdrian Chadd * packet comes along or when we prepare a beacon 296b8e788a5SAdrian Chadd * frame at SWBA. 297b8e788a5SAdrian Chadd */ 298b8e788a5SAdrian Chadd if (!qbusy) { 299b8e788a5SAdrian Chadd ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); 300b8e788a5SAdrian Chadd txq->axq_flags &= ~ATH_TXQ_PUTPENDING; 301b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_XMIT, 302b8e788a5SAdrian Chadd "%s: TXDP[%u] = %p (%p) depth %d\n", 303b8e788a5SAdrian Chadd __func__, txq->axq_qnum, 304b8e788a5SAdrian Chadd (caddr_t)bf->bf_daddr, bf->bf_desc, 305b8e788a5SAdrian Chadd txq->axq_depth); 306b8e788a5SAdrian Chadd } else { 307b8e788a5SAdrian Chadd txq->axq_flags |= ATH_TXQ_PUTPENDING; 308b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT, 309b8e788a5SAdrian Chadd "%s: Q%u busy, defer enable\n", __func__, 310b8e788a5SAdrian Chadd txq->axq_qnum); 311b8e788a5SAdrian Chadd } 312b8e788a5SAdrian Chadd } else { 313b8e788a5SAdrian Chadd *txq->axq_link = bf->bf_daddr; 314b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_XMIT, 315b8e788a5SAdrian Chadd "%s: link[%u](%p)=%p (%p) depth %d\n", __func__, 316b8e788a5SAdrian Chadd txq->axq_qnum, txq->axq_link, 317b8e788a5SAdrian Chadd (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth); 318b8e788a5SAdrian Chadd if ((txq->axq_flags & ATH_TXQ_PUTPENDING) && !qbusy) { 319b8e788a5SAdrian Chadd /* 320b8e788a5SAdrian Chadd * The q was busy when we previously tried 321b8e788a5SAdrian Chadd * to write the address of the first buffer 322b8e788a5SAdrian Chadd * in the chain. Since it's not busy now 323b8e788a5SAdrian Chadd * handle this chore. We are certain the 324b8e788a5SAdrian Chadd * buffer at the front is the right one since 325b8e788a5SAdrian Chadd * axq_link is NULL only when the buffer list 326b8e788a5SAdrian Chadd * is/was empty. 327b8e788a5SAdrian Chadd */ 328b8e788a5SAdrian Chadd ath_hal_puttxbuf(ah, txq->axq_qnum, 3296b349e5aSAdrian Chadd TAILQ_FIRST(&txq->axq_q)->bf_daddr); 330b8e788a5SAdrian Chadd txq->axq_flags &= ~ATH_TXQ_PUTPENDING; 331b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_TDMA | ATH_DEBUG_XMIT, 332b8e788a5SAdrian Chadd "%s: Q%u restarted\n", __func__, 333b8e788a5SAdrian Chadd txq->axq_qnum); 334b8e788a5SAdrian Chadd } 335b8e788a5SAdrian Chadd } 336b8e788a5SAdrian Chadd #else 337b8e788a5SAdrian Chadd ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); 338b8e788a5SAdrian Chadd if (txq->axq_link == NULL) { 339b8e788a5SAdrian Chadd ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); 340b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_XMIT, 341b8e788a5SAdrian Chadd "%s: TXDP[%u] = %p (%p) depth %d\n", 342b8e788a5SAdrian Chadd __func__, txq->axq_qnum, 343b8e788a5SAdrian Chadd (caddr_t)bf->bf_daddr, bf->bf_desc, 344b8e788a5SAdrian Chadd txq->axq_depth); 345b8e788a5SAdrian Chadd } else { 346b8e788a5SAdrian Chadd *txq->axq_link = bf->bf_daddr; 347b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_XMIT, 348b8e788a5SAdrian Chadd "%s: link[%u](%p)=%p (%p) depth %d\n", __func__, 349b8e788a5SAdrian Chadd txq->axq_qnum, txq->axq_link, 350b8e788a5SAdrian Chadd (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth); 351b8e788a5SAdrian Chadd } 352b8e788a5SAdrian Chadd #endif /* IEEE80211_SUPPORT_TDMA */ 353*6edf1dc7SAdrian Chadd if (bf->bf_state.bfs_aggr) 354*6edf1dc7SAdrian Chadd txq->axq_aggr_depth++; 355*6edf1dc7SAdrian Chadd txq->axq_link = &bf->bf_lastds->ds_link; 356b8e788a5SAdrian Chadd ath_hal_txstart(ah, txq->axq_qnum); 357b8e788a5SAdrian Chadd } else { 358b8e788a5SAdrian Chadd if (txq->axq_link != NULL) { 3596b349e5aSAdrian Chadd struct ath_buf *last = ATH_TXQ_LAST(txq, axq_q_s); 360b8e788a5SAdrian Chadd struct ieee80211_frame *wh; 361b8e788a5SAdrian Chadd 362b8e788a5SAdrian Chadd /* mark previous frame */ 363b8e788a5SAdrian Chadd wh = mtod(last->bf_m, struct ieee80211_frame *); 364b8e788a5SAdrian Chadd wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA; 365b8e788a5SAdrian Chadd bus_dmamap_sync(sc->sc_dmat, last->bf_dmamap, 366b8e788a5SAdrian Chadd BUS_DMASYNC_PREWRITE); 367b8e788a5SAdrian Chadd 368b8e788a5SAdrian Chadd /* link descriptor */ 369b8e788a5SAdrian Chadd *txq->axq_link = bf->bf_daddr; 370b8e788a5SAdrian Chadd } 371b8e788a5SAdrian Chadd ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); 372b8e788a5SAdrian Chadd txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link; 373b8e788a5SAdrian Chadd } 374b8e788a5SAdrian Chadd ATH_TXQ_UNLOCK(txq); 375b8e788a5SAdrian Chadd } 376b8e788a5SAdrian Chadd 37781a82688SAdrian Chadd static int 37881a82688SAdrian Chadd ath_tx_tag_crypto(struct ath_softc *sc, struct ieee80211_node *ni, 37981a82688SAdrian Chadd struct mbuf *m0, int iswep, int isfrag, int *hdrlen, int *pktlen, int *keyix) 38081a82688SAdrian Chadd { 38181a82688SAdrian Chadd if (iswep) { 38281a82688SAdrian Chadd const struct ieee80211_cipher *cip; 38381a82688SAdrian Chadd struct ieee80211_key *k; 38481a82688SAdrian Chadd 38581a82688SAdrian Chadd /* 38681a82688SAdrian Chadd * Construct the 802.11 header+trailer for an encrypted 38781a82688SAdrian Chadd * frame. The only reason this can fail is because of an 38881a82688SAdrian Chadd * unknown or unsupported cipher/key type. 38981a82688SAdrian Chadd */ 39081a82688SAdrian Chadd k = ieee80211_crypto_encap(ni, m0); 39181a82688SAdrian Chadd if (k == NULL) { 39281a82688SAdrian Chadd /* 39381a82688SAdrian Chadd * This can happen when the key is yanked after the 39481a82688SAdrian Chadd * frame was queued. Just discard the frame; the 39581a82688SAdrian Chadd * 802.11 layer counts failures and provides 39681a82688SAdrian Chadd * debugging/diagnostics. 39781a82688SAdrian Chadd */ 39881a82688SAdrian Chadd return 0; 39981a82688SAdrian Chadd } 40081a82688SAdrian Chadd /* 40181a82688SAdrian Chadd * Adjust the packet + header lengths for the crypto 40281a82688SAdrian Chadd * additions and calculate the h/w key index. When 40381a82688SAdrian Chadd * a s/w mic is done the frame will have had any mic 40481a82688SAdrian Chadd * added to it prior to entry so m0->m_pkthdr.len will 40581a82688SAdrian Chadd * account for it. Otherwise we need to add it to the 40681a82688SAdrian Chadd * packet length. 40781a82688SAdrian Chadd */ 40881a82688SAdrian Chadd cip = k->wk_cipher; 40981a82688SAdrian Chadd (*hdrlen) += cip->ic_header; 41081a82688SAdrian Chadd (*pktlen) += cip->ic_header + cip->ic_trailer; 41181a82688SAdrian Chadd /* NB: frags always have any TKIP MIC done in s/w */ 41281a82688SAdrian Chadd if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && !isfrag) 41381a82688SAdrian Chadd (*pktlen) += cip->ic_miclen; 41481a82688SAdrian Chadd (*keyix) = k->wk_keyix; 41581a82688SAdrian Chadd } else if (ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) { 41681a82688SAdrian Chadd /* 41781a82688SAdrian Chadd * Use station key cache slot, if assigned. 41881a82688SAdrian Chadd */ 41981a82688SAdrian Chadd (*keyix) = ni->ni_ucastkey.wk_keyix; 42081a82688SAdrian Chadd if ((*keyix) == IEEE80211_KEYIX_NONE) 42181a82688SAdrian Chadd (*keyix) = HAL_TXKEYIX_INVALID; 42281a82688SAdrian Chadd } else 42381a82688SAdrian Chadd (*keyix) = HAL_TXKEYIX_INVALID; 42481a82688SAdrian Chadd 42581a82688SAdrian Chadd return 1; 42681a82688SAdrian Chadd } 42781a82688SAdrian Chadd 428e42b5dbaSAdrian Chadd static uint8_t 429e42b5dbaSAdrian Chadd ath_tx_get_rtscts_rate(struct ath_hal *ah, const HAL_RATE_TABLE *rt, 430e42b5dbaSAdrian Chadd int rix, int cix, int shortPreamble) 43179f02dbfSAdrian Chadd { 432e42b5dbaSAdrian Chadd uint8_t ctsrate; 433e42b5dbaSAdrian Chadd 43479f02dbfSAdrian Chadd /* 43579f02dbfSAdrian Chadd * CTS transmit rate is derived from the transmit rate 43679f02dbfSAdrian Chadd * by looking in the h/w rate table. We must also factor 43779f02dbfSAdrian Chadd * in whether or not a short preamble is to be used. 43879f02dbfSAdrian Chadd */ 43979f02dbfSAdrian Chadd /* NB: cix is set above where RTS/CTS is enabled */ 44079f02dbfSAdrian Chadd KASSERT(cix != 0xff, ("cix not setup")); 441e42b5dbaSAdrian Chadd ctsrate = rt->info[cix].rateCode; 442e42b5dbaSAdrian Chadd 443e42b5dbaSAdrian Chadd /* XXX this should only matter for legacy rates */ 444e42b5dbaSAdrian Chadd if (shortPreamble) 445e42b5dbaSAdrian Chadd ctsrate |= rt->info[cix].shortPreamble; 446e42b5dbaSAdrian Chadd 447e42b5dbaSAdrian Chadd return ctsrate; 448e42b5dbaSAdrian Chadd } 449e42b5dbaSAdrian Chadd 450e42b5dbaSAdrian Chadd 451e42b5dbaSAdrian Chadd /* 452e42b5dbaSAdrian Chadd * Calculate the RTS/CTS duration for legacy frames. 453e42b5dbaSAdrian Chadd */ 454e42b5dbaSAdrian Chadd static int 455e42b5dbaSAdrian Chadd ath_tx_calc_ctsduration(struct ath_hal *ah, int rix, int cix, 456e42b5dbaSAdrian Chadd int shortPreamble, int pktlen, const HAL_RATE_TABLE *rt, 457e42b5dbaSAdrian Chadd int flags) 458e42b5dbaSAdrian Chadd { 459e42b5dbaSAdrian Chadd int ctsduration = 0; 460e42b5dbaSAdrian Chadd 461e42b5dbaSAdrian Chadd /* This mustn't be called for HT modes */ 462e42b5dbaSAdrian Chadd if (rt->info[cix].phy == IEEE80211_T_HT) { 463e42b5dbaSAdrian Chadd printf("%s: HT rate where it shouldn't be (0x%x)\n", 464e42b5dbaSAdrian Chadd __func__, rt->info[cix].rateCode); 465e42b5dbaSAdrian Chadd return -1; 466e42b5dbaSAdrian Chadd } 467e42b5dbaSAdrian Chadd 46879f02dbfSAdrian Chadd /* 46979f02dbfSAdrian Chadd * Compute the transmit duration based on the frame 47079f02dbfSAdrian Chadd * size and the size of an ACK frame. We call into the 47179f02dbfSAdrian Chadd * HAL to do the computation since it depends on the 47279f02dbfSAdrian Chadd * characteristics of the actual PHY being used. 47379f02dbfSAdrian Chadd * 47479f02dbfSAdrian Chadd * NB: CTS is assumed the same size as an ACK so we can 47579f02dbfSAdrian Chadd * use the precalculated ACK durations. 47679f02dbfSAdrian Chadd */ 47779f02dbfSAdrian Chadd if (shortPreamble) { 47879f02dbfSAdrian Chadd if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ 479e42b5dbaSAdrian Chadd ctsduration += rt->info[cix].spAckDuration; 480e42b5dbaSAdrian Chadd ctsduration += ath_hal_computetxtime(ah, 48179f02dbfSAdrian Chadd rt, pktlen, rix, AH_TRUE); 48279f02dbfSAdrian Chadd if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ 483e42b5dbaSAdrian Chadd ctsduration += rt->info[rix].spAckDuration; 48479f02dbfSAdrian Chadd } else { 48579f02dbfSAdrian Chadd if (flags & HAL_TXDESC_RTSENA) /* SIFS + CTS */ 486e42b5dbaSAdrian Chadd ctsduration += rt->info[cix].lpAckDuration; 487e42b5dbaSAdrian Chadd ctsduration += ath_hal_computetxtime(ah, 48879f02dbfSAdrian Chadd rt, pktlen, rix, AH_FALSE); 48979f02dbfSAdrian Chadd if ((flags & HAL_TXDESC_NOACK) == 0) /* SIFS + ACK */ 490e42b5dbaSAdrian Chadd ctsduration += rt->info[rix].lpAckDuration; 49179f02dbfSAdrian Chadd } 492e42b5dbaSAdrian Chadd 493e42b5dbaSAdrian Chadd return ctsduration; 49479f02dbfSAdrian Chadd } 49579f02dbfSAdrian Chadd 496b8e788a5SAdrian Chadd int 497b8e788a5SAdrian Chadd ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, 498b8e788a5SAdrian Chadd struct mbuf *m0) 499b8e788a5SAdrian Chadd { 500b8e788a5SAdrian Chadd struct ieee80211vap *vap = ni->ni_vap; 501b8e788a5SAdrian Chadd struct ath_vap *avp = ATH_VAP(vap); 502b8e788a5SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 503b8e788a5SAdrian Chadd struct ifnet *ifp = sc->sc_ifp; 504b8e788a5SAdrian Chadd struct ieee80211com *ic = ifp->if_l2com; 505b8e788a5SAdrian Chadd const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams; 506b8e788a5SAdrian Chadd int error, iswep, ismcast, isfrag, ismrr; 507b8e788a5SAdrian Chadd int keyix, hdrlen, pktlen, try0; 508b8e788a5SAdrian Chadd u_int8_t rix, txrate, ctsrate; 509b8e788a5SAdrian Chadd u_int8_t cix = 0xff; /* NB: silence compiler */ 510b8e788a5SAdrian Chadd struct ath_desc *ds; 511b8e788a5SAdrian Chadd struct ath_txq *txq; 512b8e788a5SAdrian Chadd struct ieee80211_frame *wh; 513b8e788a5SAdrian Chadd u_int subtype, flags, ctsduration; 514b8e788a5SAdrian Chadd HAL_PKT_TYPE atype; 515b8e788a5SAdrian Chadd const HAL_RATE_TABLE *rt; 516b8e788a5SAdrian Chadd HAL_BOOL shortPreamble; 517b8e788a5SAdrian Chadd struct ath_node *an; 518b8e788a5SAdrian Chadd u_int pri; 519c1782ce0SAdrian Chadd uint8_t try[4], rate[4]; 520c1782ce0SAdrian Chadd 521c1782ce0SAdrian Chadd bzero(try, sizeof(try)); 522c1782ce0SAdrian Chadd bzero(rate, sizeof(rate)); 523b8e788a5SAdrian Chadd 524b8e788a5SAdrian Chadd wh = mtod(m0, struct ieee80211_frame *); 525b8e788a5SAdrian Chadd iswep = wh->i_fc[1] & IEEE80211_FC1_WEP; 526b8e788a5SAdrian Chadd ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); 527b8e788a5SAdrian Chadd isfrag = m0->m_flags & M_FRAG; 528b8e788a5SAdrian Chadd hdrlen = ieee80211_anyhdrsize(wh); 529b8e788a5SAdrian Chadd /* 530b8e788a5SAdrian Chadd * Packet length must not include any 531b8e788a5SAdrian Chadd * pad bytes; deduct them here. 532b8e788a5SAdrian Chadd */ 533b8e788a5SAdrian Chadd pktlen = m0->m_pkthdr.len - (hdrlen & 3); 534b8e788a5SAdrian Chadd 53581a82688SAdrian Chadd /* Handle encryption twiddling if needed */ 53681a82688SAdrian Chadd if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen, &pktlen, &keyix)) { 537b8e788a5SAdrian Chadd ath_freetx(m0); 538b8e788a5SAdrian Chadd return EIO; 539b8e788a5SAdrian Chadd } 540b8e788a5SAdrian Chadd 541b8e788a5SAdrian Chadd /* packet header may have moved, reset our local pointer */ 542b8e788a5SAdrian Chadd wh = mtod(m0, struct ieee80211_frame *); 543b8e788a5SAdrian Chadd 544b8e788a5SAdrian Chadd pktlen += IEEE80211_CRC_LEN; 545b8e788a5SAdrian Chadd 546b8e788a5SAdrian Chadd /* 547b8e788a5SAdrian Chadd * Load the DMA map so any coalescing is done. This 548b8e788a5SAdrian Chadd * also calculates the number of descriptors we need. 549b8e788a5SAdrian Chadd */ 550b8e788a5SAdrian Chadd error = ath_tx_dmasetup(sc, bf, m0); 551b8e788a5SAdrian Chadd if (error != 0) 552b8e788a5SAdrian Chadd return error; 553b8e788a5SAdrian Chadd bf->bf_node = ni; /* NB: held reference */ 554b8e788a5SAdrian Chadd m0 = bf->bf_m; /* NB: may have changed */ 555b8e788a5SAdrian Chadd wh = mtod(m0, struct ieee80211_frame *); 556b8e788a5SAdrian Chadd 557b8e788a5SAdrian Chadd /* setup descriptors */ 558b8e788a5SAdrian Chadd ds = bf->bf_desc; 559b8e788a5SAdrian Chadd rt = sc->sc_currates; 560b8e788a5SAdrian Chadd KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 561b8e788a5SAdrian Chadd 562b8e788a5SAdrian Chadd /* 563b8e788a5SAdrian Chadd * NB: the 802.11 layer marks whether or not we should 564b8e788a5SAdrian Chadd * use short preamble based on the current mode and 565b8e788a5SAdrian Chadd * negotiated parameters. 566b8e788a5SAdrian Chadd */ 567b8e788a5SAdrian Chadd if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 568b8e788a5SAdrian Chadd (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) { 569b8e788a5SAdrian Chadd shortPreamble = AH_TRUE; 570b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_shortpre++; 571b8e788a5SAdrian Chadd } else { 572b8e788a5SAdrian Chadd shortPreamble = AH_FALSE; 573b8e788a5SAdrian Chadd } 574b8e788a5SAdrian Chadd 575b8e788a5SAdrian Chadd an = ATH_NODE(ni); 576b8e788a5SAdrian Chadd flags = HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ 577b8e788a5SAdrian Chadd ismrr = 0; /* default no multi-rate retry*/ 578b8e788a5SAdrian Chadd pri = M_WME_GETAC(m0); /* honor classification */ 579b8e788a5SAdrian Chadd /* XXX use txparams instead of fixed values */ 580b8e788a5SAdrian Chadd /* 581b8e788a5SAdrian Chadd * Calculate Atheros packet type from IEEE80211 packet header, 582b8e788a5SAdrian Chadd * setup for rate calculations, and select h/w transmit queue. 583b8e788a5SAdrian Chadd */ 584b8e788a5SAdrian Chadd switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 585b8e788a5SAdrian Chadd case IEEE80211_FC0_TYPE_MGT: 586b8e788a5SAdrian Chadd subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 587b8e788a5SAdrian Chadd if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) 588b8e788a5SAdrian Chadd atype = HAL_PKT_TYPE_BEACON; 589b8e788a5SAdrian Chadd else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) 590b8e788a5SAdrian Chadd atype = HAL_PKT_TYPE_PROBE_RESP; 591b8e788a5SAdrian Chadd else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM) 592b8e788a5SAdrian Chadd atype = HAL_PKT_TYPE_ATIM; 593b8e788a5SAdrian Chadd else 594b8e788a5SAdrian Chadd atype = HAL_PKT_TYPE_NORMAL; /* XXX */ 595b8e788a5SAdrian Chadd rix = an->an_mgmtrix; 596b8e788a5SAdrian Chadd txrate = rt->info[rix].rateCode; 597b8e788a5SAdrian Chadd if (shortPreamble) 598b8e788a5SAdrian Chadd txrate |= rt->info[rix].shortPreamble; 599b8e788a5SAdrian Chadd try0 = ATH_TXMGTTRY; 600b8e788a5SAdrian Chadd flags |= HAL_TXDESC_INTREQ; /* force interrupt */ 601b8e788a5SAdrian Chadd break; 602b8e788a5SAdrian Chadd case IEEE80211_FC0_TYPE_CTL: 603b8e788a5SAdrian Chadd atype = HAL_PKT_TYPE_PSPOLL; /* stop setting of duration */ 604b8e788a5SAdrian Chadd rix = an->an_mgmtrix; 605b8e788a5SAdrian Chadd txrate = rt->info[rix].rateCode; 606b8e788a5SAdrian Chadd if (shortPreamble) 607b8e788a5SAdrian Chadd txrate |= rt->info[rix].shortPreamble; 608b8e788a5SAdrian Chadd try0 = ATH_TXMGTTRY; 609b8e788a5SAdrian Chadd flags |= HAL_TXDESC_INTREQ; /* force interrupt */ 610b8e788a5SAdrian Chadd break; 611b8e788a5SAdrian Chadd case IEEE80211_FC0_TYPE_DATA: 612b8e788a5SAdrian Chadd atype = HAL_PKT_TYPE_NORMAL; /* default */ 613b8e788a5SAdrian Chadd /* 614b8e788a5SAdrian Chadd * Data frames: multicast frames go out at a fixed rate, 615b8e788a5SAdrian Chadd * EAPOL frames use the mgmt frame rate; otherwise consult 616b8e788a5SAdrian Chadd * the rate control module for the rate to use. 617b8e788a5SAdrian Chadd */ 618b8e788a5SAdrian Chadd if (ismcast) { 619b8e788a5SAdrian Chadd rix = an->an_mcastrix; 620b8e788a5SAdrian Chadd txrate = rt->info[rix].rateCode; 621b8e788a5SAdrian Chadd if (shortPreamble) 622b8e788a5SAdrian Chadd txrate |= rt->info[rix].shortPreamble; 623b8e788a5SAdrian Chadd try0 = 1; 624b8e788a5SAdrian Chadd } else if (m0->m_flags & M_EAPOL) { 625b8e788a5SAdrian Chadd /* XXX? maybe always use long preamble? */ 626b8e788a5SAdrian Chadd rix = an->an_mgmtrix; 627b8e788a5SAdrian Chadd txrate = rt->info[rix].rateCode; 628b8e788a5SAdrian Chadd if (shortPreamble) 629b8e788a5SAdrian Chadd txrate |= rt->info[rix].shortPreamble; 630b8e788a5SAdrian Chadd try0 = ATH_TXMAXTRY; /* XXX?too many? */ 631b8e788a5SAdrian Chadd } else { 632b8e788a5SAdrian Chadd ath_rate_findrate(sc, an, shortPreamble, pktlen, 633b8e788a5SAdrian Chadd &rix, &try0, &txrate); 634b8e788a5SAdrian Chadd sc->sc_txrix = rix; /* for LED blinking */ 635b8e788a5SAdrian Chadd sc->sc_lastdatarix = rix; /* for fast frames */ 636b8e788a5SAdrian Chadd if (try0 != ATH_TXMAXTRY) 637b8e788a5SAdrian Chadd ismrr = 1; 638b8e788a5SAdrian Chadd } 639b8e788a5SAdrian Chadd if (cap->cap_wmeParams[pri].wmep_noackPolicy) 640b8e788a5SAdrian Chadd flags |= HAL_TXDESC_NOACK; 641b8e788a5SAdrian Chadd break; 642b8e788a5SAdrian Chadd default: 643b8e788a5SAdrian Chadd if_printf(ifp, "bogus frame type 0x%x (%s)\n", 644b8e788a5SAdrian Chadd wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); 645b8e788a5SAdrian Chadd /* XXX statistic */ 646b8e788a5SAdrian Chadd ath_freetx(m0); 647b8e788a5SAdrian Chadd return EIO; 648b8e788a5SAdrian Chadd } 649b8e788a5SAdrian Chadd txq = sc->sc_ac2q[pri]; 650b8e788a5SAdrian Chadd 651b8e788a5SAdrian Chadd /* 652b8e788a5SAdrian Chadd * When servicing one or more stations in power-save mode 653b8e788a5SAdrian Chadd * (or) if there is some mcast data waiting on the mcast 654b8e788a5SAdrian Chadd * queue (to prevent out of order delivery) multicast 655b8e788a5SAdrian Chadd * frames must be buffered until after the beacon. 656b8e788a5SAdrian Chadd */ 657b8e788a5SAdrian Chadd if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth)) 658b8e788a5SAdrian Chadd txq = &avp->av_mcastq; 659b8e788a5SAdrian Chadd 660b8e788a5SAdrian Chadd /* 661b8e788a5SAdrian Chadd * Calculate miscellaneous flags. 662b8e788a5SAdrian Chadd */ 663b8e788a5SAdrian Chadd if (ismcast) { 664b8e788a5SAdrian Chadd flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */ 665b8e788a5SAdrian Chadd } else if (pktlen > vap->iv_rtsthreshold && 666b8e788a5SAdrian Chadd (ni->ni_ath_flags & IEEE80211_NODE_FF) == 0) { 667b8e788a5SAdrian Chadd flags |= HAL_TXDESC_RTSENA; /* RTS based on frame length */ 668b8e788a5SAdrian Chadd cix = rt->info[rix].controlRate; 669b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_rts++; 670b8e788a5SAdrian Chadd } 671b8e788a5SAdrian Chadd if (flags & HAL_TXDESC_NOACK) /* NB: avoid double counting */ 672b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_noack++; 673b8e788a5SAdrian Chadd #ifdef IEEE80211_SUPPORT_TDMA 674b8e788a5SAdrian Chadd if (sc->sc_tdma && (flags & HAL_TXDESC_NOACK) == 0) { 675b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_TDMA, 676b8e788a5SAdrian Chadd "%s: discard frame, ACK required w/ TDMA\n", __func__); 677b8e788a5SAdrian Chadd sc->sc_stats.ast_tdma_ack++; 678b8e788a5SAdrian Chadd ath_freetx(m0); 679b8e788a5SAdrian Chadd return EIO; 680b8e788a5SAdrian Chadd } 681b8e788a5SAdrian Chadd #endif 682b8e788a5SAdrian Chadd 683b8e788a5SAdrian Chadd /* 684b8e788a5SAdrian Chadd * If 802.11g protection is enabled, determine whether 685b8e788a5SAdrian Chadd * to use RTS/CTS or just CTS. Note that this is only 686b8e788a5SAdrian Chadd * done for OFDM unicast frames. 687b8e788a5SAdrian Chadd */ 688b8e788a5SAdrian Chadd if ((ic->ic_flags & IEEE80211_F_USEPROT) && 689b8e788a5SAdrian Chadd rt->info[rix].phy == IEEE80211_T_OFDM && 690b8e788a5SAdrian Chadd (flags & HAL_TXDESC_NOACK) == 0) { 691b8e788a5SAdrian Chadd /* XXX fragments must use CCK rates w/ protection */ 692b8e788a5SAdrian Chadd if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 693b8e788a5SAdrian Chadd flags |= HAL_TXDESC_RTSENA; 694b8e788a5SAdrian Chadd else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 695b8e788a5SAdrian Chadd flags |= HAL_TXDESC_CTSENA; 696b8e788a5SAdrian Chadd if (isfrag) { 697b8e788a5SAdrian Chadd /* 698b8e788a5SAdrian Chadd * For frags it would be desirable to use the 699b8e788a5SAdrian Chadd * highest CCK rate for RTS/CTS. But stations 700b8e788a5SAdrian Chadd * farther away may detect it at a lower CCK rate 701b8e788a5SAdrian Chadd * so use the configured protection rate instead 702b8e788a5SAdrian Chadd * (for now). 703b8e788a5SAdrian Chadd */ 704b8e788a5SAdrian Chadd cix = rt->info[sc->sc_protrix].controlRate; 705b8e788a5SAdrian Chadd } else 706b8e788a5SAdrian Chadd cix = rt->info[sc->sc_protrix].controlRate; 707b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_protect++; 708b8e788a5SAdrian Chadd } 709b8e788a5SAdrian Chadd 7104f545a2cSAdrian Chadd #if 0 7114f545a2cSAdrian Chadd /* 7124f545a2cSAdrian Chadd * If 11n protection is enabled and it's a HT frame, 7134f545a2cSAdrian Chadd * enable RTS. 7144f545a2cSAdrian Chadd * 7154f545a2cSAdrian Chadd * XXX ic_htprotmode or ic_curhtprotmode? 7164f545a2cSAdrian Chadd * XXX should it_htprotmode only matter if ic_curhtprotmode 7174f545a2cSAdrian Chadd * XXX indicates it's not a HT pure environment? 7184f545a2cSAdrian Chadd */ 7194f545a2cSAdrian Chadd if ((ic->ic_htprotmode == IEEE80211_PROT_RTSCTS) && 7204f545a2cSAdrian Chadd rt->info[rix].phy == IEEE80211_T_HT && 7214f545a2cSAdrian Chadd (flags & HAL_TXDESC_NOACK) == 0) { 7224f545a2cSAdrian Chadd cix = rt->info[sc->sc_protrix].controlRate; 7234f545a2cSAdrian Chadd flags |= HAL_TXDESC_RTSENA; 7244f545a2cSAdrian Chadd sc->sc_stats.ast_tx_htprotect++; 7254f545a2cSAdrian Chadd } 7264f545a2cSAdrian Chadd #endif 7274f545a2cSAdrian Chadd 728b8e788a5SAdrian Chadd /* 729b8e788a5SAdrian Chadd * Calculate duration. This logically belongs in the 802.11 730b8e788a5SAdrian Chadd * layer but it lacks sufficient information to calculate it. 731b8e788a5SAdrian Chadd */ 732b8e788a5SAdrian Chadd if ((flags & HAL_TXDESC_NOACK) == 0 && 733b8e788a5SAdrian Chadd (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) { 734b8e788a5SAdrian Chadd u_int16_t dur; 735b8e788a5SAdrian Chadd if (shortPreamble) 736b8e788a5SAdrian Chadd dur = rt->info[rix].spAckDuration; 737b8e788a5SAdrian Chadd else 738b8e788a5SAdrian Chadd dur = rt->info[rix].lpAckDuration; 739b8e788a5SAdrian Chadd if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) { 740b8e788a5SAdrian Chadd dur += dur; /* additional SIFS+ACK */ 741b8e788a5SAdrian Chadd KASSERT(m0->m_nextpkt != NULL, ("no fragment")); 742b8e788a5SAdrian Chadd /* 743b8e788a5SAdrian Chadd * Include the size of next fragment so NAV is 744b8e788a5SAdrian Chadd * updated properly. The last fragment uses only 745b8e788a5SAdrian Chadd * the ACK duration 746b8e788a5SAdrian Chadd */ 747b8e788a5SAdrian Chadd dur += ath_hal_computetxtime(ah, rt, 748b8e788a5SAdrian Chadd m0->m_nextpkt->m_pkthdr.len, 749b8e788a5SAdrian Chadd rix, shortPreamble); 750b8e788a5SAdrian Chadd } 751b8e788a5SAdrian Chadd if (isfrag) { 752b8e788a5SAdrian Chadd /* 753b8e788a5SAdrian Chadd * Force hardware to use computed duration for next 754b8e788a5SAdrian Chadd * fragment by disabling multi-rate retry which updates 755b8e788a5SAdrian Chadd * duration based on the multi-rate duration table. 756b8e788a5SAdrian Chadd */ 757b8e788a5SAdrian Chadd ismrr = 0; 758b8e788a5SAdrian Chadd try0 = ATH_TXMGTTRY; /* XXX? */ 759b8e788a5SAdrian Chadd } 760b8e788a5SAdrian Chadd *(u_int16_t *)wh->i_dur = htole16(dur); 761b8e788a5SAdrian Chadd } 762b8e788a5SAdrian Chadd 763b8e788a5SAdrian Chadd /* 764b8e788a5SAdrian Chadd * Calculate RTS/CTS rate and duration if needed. 765b8e788a5SAdrian Chadd */ 766b8e788a5SAdrian Chadd ctsduration = 0; 767b8e788a5SAdrian Chadd if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) { 768e42b5dbaSAdrian Chadd ctsrate = ath_tx_get_rtscts_rate(ah, rt, rix, cix, shortPreamble); 769e42b5dbaSAdrian Chadd 770e42b5dbaSAdrian Chadd /* The 11n chipsets do ctsduration calculations for you */ 771e42b5dbaSAdrian Chadd if (! ath_tx_is_11n(sc)) 772e42b5dbaSAdrian Chadd ctsduration = ath_tx_calc_ctsduration(ah, rix, cix, shortPreamble, 773e42b5dbaSAdrian Chadd pktlen, rt, flags); 774b8e788a5SAdrian Chadd /* 775b8e788a5SAdrian Chadd * Must disable multi-rate retry when using RTS/CTS. 776b8e788a5SAdrian Chadd */ 777b8e788a5SAdrian Chadd ismrr = 0; 778b8e788a5SAdrian Chadd try0 = ATH_TXMGTTRY; /* XXX */ 779b8e788a5SAdrian Chadd } else 780b8e788a5SAdrian Chadd ctsrate = 0; 781b8e788a5SAdrian Chadd 782b8e788a5SAdrian Chadd /* 783b8e788a5SAdrian Chadd * At this point we are committed to sending the frame 784b8e788a5SAdrian Chadd * and we don't need to look at m_nextpkt; clear it in 785b8e788a5SAdrian Chadd * case this frame is part of frag chain. 786b8e788a5SAdrian Chadd */ 787b8e788a5SAdrian Chadd m0->m_nextpkt = NULL; 788b8e788a5SAdrian Chadd 789b8e788a5SAdrian Chadd if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) 790b8e788a5SAdrian Chadd ieee80211_dump_pkt(ic, mtod(m0, const uint8_t *), m0->m_len, 791b8e788a5SAdrian Chadd sc->sc_hwmap[rix].ieeerate, -1); 792b8e788a5SAdrian Chadd 793b8e788a5SAdrian Chadd if (ieee80211_radiotap_active_vap(vap)) { 794b8e788a5SAdrian Chadd u_int64_t tsf = ath_hal_gettsf64(ah); 795b8e788a5SAdrian Chadd 796b8e788a5SAdrian Chadd sc->sc_tx_th.wt_tsf = htole64(tsf); 797b8e788a5SAdrian Chadd sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags; 798b8e788a5SAdrian Chadd if (iswep) 799b8e788a5SAdrian Chadd sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; 800b8e788a5SAdrian Chadd if (isfrag) 801b8e788a5SAdrian Chadd sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG; 802b8e788a5SAdrian Chadd sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate; 803b8e788a5SAdrian Chadd sc->sc_tx_th.wt_txpower = ni->ni_txpower; 804b8e788a5SAdrian Chadd sc->sc_tx_th.wt_antenna = sc->sc_txantenna; 805b8e788a5SAdrian Chadd 806b8e788a5SAdrian Chadd ieee80211_radiotap_tx(vap, m0); 807b8e788a5SAdrian Chadd } 808b8e788a5SAdrian Chadd 809b8e788a5SAdrian Chadd /* 810b8e788a5SAdrian Chadd * Determine if a tx interrupt should be generated for 811b8e788a5SAdrian Chadd * this descriptor. We take a tx interrupt to reap 812b8e788a5SAdrian Chadd * descriptors when the h/w hits an EOL condition or 813b8e788a5SAdrian Chadd * when the descriptor is specifically marked to generate 814b8e788a5SAdrian Chadd * an interrupt. We periodically mark descriptors in this 815b8e788a5SAdrian Chadd * way to insure timely replenishing of the supply needed 816b8e788a5SAdrian Chadd * for sending frames. Defering interrupts reduces system 817b8e788a5SAdrian Chadd * load and potentially allows more concurrent work to be 818b8e788a5SAdrian Chadd * done but if done to aggressively can cause senders to 819b8e788a5SAdrian Chadd * backup. 820b8e788a5SAdrian Chadd * 821b8e788a5SAdrian Chadd * NB: use >= to deal with sc_txintrperiod changing 822b8e788a5SAdrian Chadd * dynamically through sysctl. 823b8e788a5SAdrian Chadd */ 824b8e788a5SAdrian Chadd if (flags & HAL_TXDESC_INTREQ) { 825b8e788a5SAdrian Chadd txq->axq_intrcnt = 0; 826b8e788a5SAdrian Chadd } else if (++txq->axq_intrcnt >= sc->sc_txintrperiod) { 827b8e788a5SAdrian Chadd flags |= HAL_TXDESC_INTREQ; 828b8e788a5SAdrian Chadd txq->axq_intrcnt = 0; 829b8e788a5SAdrian Chadd } 830b8e788a5SAdrian Chadd 831c1782ce0SAdrian Chadd if (ath_tx_is_11n(sc)) { 832c1782ce0SAdrian Chadd rate[0] = rix; 833c1782ce0SAdrian Chadd try[0] = try0; 834c1782ce0SAdrian Chadd } 835c1782ce0SAdrian Chadd 836b8e788a5SAdrian Chadd /* 837b8e788a5SAdrian Chadd * Formulate first tx descriptor with tx controls. 838b8e788a5SAdrian Chadd */ 839b8e788a5SAdrian Chadd /* XXX check return value? */ 840c1782ce0SAdrian Chadd /* XXX is this ok to call for 11n descriptors? */ 841c1782ce0SAdrian Chadd /* XXX or should it go through the first, next, last 11n calls? */ 842b8e788a5SAdrian Chadd ath_hal_setuptxdesc(ah, ds 843b8e788a5SAdrian Chadd , pktlen /* packet length */ 844b8e788a5SAdrian Chadd , hdrlen /* header length */ 845b8e788a5SAdrian Chadd , atype /* Atheros packet type */ 846b8e788a5SAdrian Chadd , ni->ni_txpower /* txpower */ 847b8e788a5SAdrian Chadd , txrate, try0 /* series 0 rate/tries */ 848b8e788a5SAdrian Chadd , keyix /* key cache index */ 849b8e788a5SAdrian Chadd , sc->sc_txantenna /* antenna mode */ 850b8e788a5SAdrian Chadd , flags /* flags */ 851b8e788a5SAdrian Chadd , ctsrate /* rts/cts rate */ 852b8e788a5SAdrian Chadd , ctsduration /* rts/cts duration */ 853b8e788a5SAdrian Chadd ); 854b8e788a5SAdrian Chadd bf->bf_txflags = flags; 855b8e788a5SAdrian Chadd /* 856b8e788a5SAdrian Chadd * Setup the multi-rate retry state only when we're 857b8e788a5SAdrian Chadd * going to use it. This assumes ath_hal_setuptxdesc 858b8e788a5SAdrian Chadd * initializes the descriptors (so we don't have to) 859b8e788a5SAdrian Chadd * when the hardware supports multi-rate retry and 860b8e788a5SAdrian Chadd * we don't use it. 861b8e788a5SAdrian Chadd */ 862c1782ce0SAdrian Chadd if (ismrr) { 863c1782ce0SAdrian Chadd if (ath_tx_is_11n(sc)) 864c1782ce0SAdrian Chadd ath_rate_getxtxrates(sc, an, rix, rate, try); 865c1782ce0SAdrian Chadd else 866b8e788a5SAdrian Chadd ath_rate_setupxtxdesc(sc, an, ds, shortPreamble, rix); 867c1782ce0SAdrian Chadd } 868c1782ce0SAdrian Chadd 869c1782ce0SAdrian Chadd if (ath_tx_is_11n(sc)) { 870bf26df36SAdrian Chadd ath_buf_set_rate(sc, ni, bf, pktlen, flags, ctsrate, (atype == HAL_PKT_TYPE_PSPOLL), rate, try); 871c1782ce0SAdrian Chadd } 872b8e788a5SAdrian Chadd 873b8e788a5SAdrian Chadd ath_tx_handoff(sc, txq, bf); 874b8e788a5SAdrian Chadd return 0; 875b8e788a5SAdrian Chadd } 876b8e788a5SAdrian Chadd 877b8e788a5SAdrian Chadd static int 878b8e788a5SAdrian Chadd ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, 879b8e788a5SAdrian Chadd struct ath_buf *bf, struct mbuf *m0, 880b8e788a5SAdrian Chadd const struct ieee80211_bpf_params *params) 881b8e788a5SAdrian Chadd { 882b8e788a5SAdrian Chadd struct ifnet *ifp = sc->sc_ifp; 883b8e788a5SAdrian Chadd struct ieee80211com *ic = ifp->if_l2com; 884b8e788a5SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 885b8e788a5SAdrian Chadd struct ieee80211vap *vap = ni->ni_vap; 886b8e788a5SAdrian Chadd int error, ismcast, ismrr; 887b8e788a5SAdrian Chadd int keyix, hdrlen, pktlen, try0, txantenna; 888b8e788a5SAdrian Chadd u_int8_t rix, cix, txrate, ctsrate, rate1, rate2, rate3; 889b8e788a5SAdrian Chadd struct ieee80211_frame *wh; 890b8e788a5SAdrian Chadd u_int flags, ctsduration; 891b8e788a5SAdrian Chadd HAL_PKT_TYPE atype; 892b8e788a5SAdrian Chadd const HAL_RATE_TABLE *rt; 893b8e788a5SAdrian Chadd struct ath_desc *ds; 894b8e788a5SAdrian Chadd u_int pri; 895c1782ce0SAdrian Chadd uint8_t try[4], rate[4]; 896c1782ce0SAdrian Chadd 897c1782ce0SAdrian Chadd bzero(try, sizeof(try)); 898c1782ce0SAdrian Chadd bzero(rate, sizeof(rate)); 899b8e788a5SAdrian Chadd 900b8e788a5SAdrian Chadd wh = mtod(m0, struct ieee80211_frame *); 901b8e788a5SAdrian Chadd ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); 902b8e788a5SAdrian Chadd hdrlen = ieee80211_anyhdrsize(wh); 903b8e788a5SAdrian Chadd /* 904b8e788a5SAdrian Chadd * Packet length must not include any 905b8e788a5SAdrian Chadd * pad bytes; deduct them here. 906b8e788a5SAdrian Chadd */ 907b8e788a5SAdrian Chadd /* XXX honor IEEE80211_BPF_DATAPAD */ 908b8e788a5SAdrian Chadd pktlen = m0->m_pkthdr.len - (hdrlen & 3) + IEEE80211_CRC_LEN; 909b8e788a5SAdrian Chadd 91081a82688SAdrian Chadd /* Handle encryption twiddling if needed */ 91181a82688SAdrian Chadd if (! ath_tx_tag_crypto(sc, ni, m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0, &hdrlen, &pktlen, &keyix)) { 912b8e788a5SAdrian Chadd ath_freetx(m0); 913b8e788a5SAdrian Chadd return EIO; 914b8e788a5SAdrian Chadd } 915b8e788a5SAdrian Chadd /* packet header may have moved, reset our local pointer */ 916b8e788a5SAdrian Chadd wh = mtod(m0, struct ieee80211_frame *); 917b8e788a5SAdrian Chadd 918b8e788a5SAdrian Chadd error = ath_tx_dmasetup(sc, bf, m0); 919b8e788a5SAdrian Chadd if (error != 0) 920b8e788a5SAdrian Chadd return error; 921b8e788a5SAdrian Chadd m0 = bf->bf_m; /* NB: may have changed */ 922b8e788a5SAdrian Chadd wh = mtod(m0, struct ieee80211_frame *); 923b8e788a5SAdrian Chadd bf->bf_node = ni; /* NB: held reference */ 924b8e788a5SAdrian Chadd 925b8e788a5SAdrian Chadd flags = HAL_TXDESC_CLRDMASK; /* XXX needed for crypto errs */ 926b8e788a5SAdrian Chadd flags |= HAL_TXDESC_INTREQ; /* force interrupt */ 927b8e788a5SAdrian Chadd if (params->ibp_flags & IEEE80211_BPF_RTS) 928b8e788a5SAdrian Chadd flags |= HAL_TXDESC_RTSENA; 929b8e788a5SAdrian Chadd else if (params->ibp_flags & IEEE80211_BPF_CTS) 930b8e788a5SAdrian Chadd flags |= HAL_TXDESC_CTSENA; 931b8e788a5SAdrian Chadd /* XXX leave ismcast to injector? */ 932b8e788a5SAdrian Chadd if ((params->ibp_flags & IEEE80211_BPF_NOACK) || ismcast) 933b8e788a5SAdrian Chadd flags |= HAL_TXDESC_NOACK; 934b8e788a5SAdrian Chadd 935b8e788a5SAdrian Chadd rt = sc->sc_currates; 936b8e788a5SAdrian Chadd KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 937b8e788a5SAdrian Chadd rix = ath_tx_findrix(sc, params->ibp_rate0); 938b8e788a5SAdrian Chadd txrate = rt->info[rix].rateCode; 939b8e788a5SAdrian Chadd if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) 940b8e788a5SAdrian Chadd txrate |= rt->info[rix].shortPreamble; 941b8e788a5SAdrian Chadd sc->sc_txrix = rix; 942b8e788a5SAdrian Chadd try0 = params->ibp_try0; 943b8e788a5SAdrian Chadd ismrr = (params->ibp_try1 != 0); 944b8e788a5SAdrian Chadd txantenna = params->ibp_pri >> 2; 945b8e788a5SAdrian Chadd if (txantenna == 0) /* XXX? */ 946b8e788a5SAdrian Chadd txantenna = sc->sc_txantenna; 94779f02dbfSAdrian Chadd 948b8e788a5SAdrian Chadd ctsduration = 0; 94979f02dbfSAdrian Chadd if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) { 950b8e788a5SAdrian Chadd cix = ath_tx_findrix(sc, params->ibp_ctsrate); 951e42b5dbaSAdrian Chadd ctsrate = ath_tx_get_rtscts_rate(ah, rt, rix, cix, params->ibp_flags & IEEE80211_BPF_SHORTPRE); 952e42b5dbaSAdrian Chadd /* The 11n chipsets do ctsduration calculations for you */ 953e42b5dbaSAdrian Chadd if (! ath_tx_is_11n(sc)) 954e42b5dbaSAdrian Chadd ctsduration = ath_tx_calc_ctsduration(ah, rix, cix, 95579f02dbfSAdrian Chadd params->ibp_flags & IEEE80211_BPF_SHORTPRE, pktlen, 956e42b5dbaSAdrian Chadd rt, flags); 95779f02dbfSAdrian Chadd /* 95879f02dbfSAdrian Chadd * Must disable multi-rate retry when using RTS/CTS. 95979f02dbfSAdrian Chadd */ 960b8e788a5SAdrian Chadd ismrr = 0; /* XXX */ 961b8e788a5SAdrian Chadd } else 962b8e788a5SAdrian Chadd ctsrate = 0; 96379f02dbfSAdrian Chadd 964b8e788a5SAdrian Chadd pri = params->ibp_pri & 3; 965b8e788a5SAdrian Chadd /* 966b8e788a5SAdrian Chadd * NB: we mark all packets as type PSPOLL so the h/w won't 967b8e788a5SAdrian Chadd * set the sequence number, duration, etc. 968b8e788a5SAdrian Chadd */ 969b8e788a5SAdrian Chadd atype = HAL_PKT_TYPE_PSPOLL; 970b8e788a5SAdrian Chadd 971b8e788a5SAdrian Chadd if (IFF_DUMPPKTS(sc, ATH_DEBUG_XMIT)) 972b8e788a5SAdrian Chadd ieee80211_dump_pkt(ic, mtod(m0, caddr_t), m0->m_len, 973b8e788a5SAdrian Chadd sc->sc_hwmap[rix].ieeerate, -1); 974b8e788a5SAdrian Chadd 975b8e788a5SAdrian Chadd if (ieee80211_radiotap_active_vap(vap)) { 976b8e788a5SAdrian Chadd u_int64_t tsf = ath_hal_gettsf64(ah); 977b8e788a5SAdrian Chadd 978b8e788a5SAdrian Chadd sc->sc_tx_th.wt_tsf = htole64(tsf); 979b8e788a5SAdrian Chadd sc->sc_tx_th.wt_flags = sc->sc_hwmap[rix].txflags; 980b8e788a5SAdrian Chadd if (wh->i_fc[1] & IEEE80211_FC1_WEP) 981b8e788a5SAdrian Chadd sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; 982b8e788a5SAdrian Chadd if (m0->m_flags & M_FRAG) 983b8e788a5SAdrian Chadd sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_FRAG; 984b8e788a5SAdrian Chadd sc->sc_tx_th.wt_rate = sc->sc_hwmap[rix].ieeerate; 985b8e788a5SAdrian Chadd sc->sc_tx_th.wt_txpower = ni->ni_txpower; 986b8e788a5SAdrian Chadd sc->sc_tx_th.wt_antenna = sc->sc_txantenna; 987b8e788a5SAdrian Chadd 988b8e788a5SAdrian Chadd ieee80211_radiotap_tx(vap, m0); 989b8e788a5SAdrian Chadd } 990b8e788a5SAdrian Chadd 991b8e788a5SAdrian Chadd /* 992b8e788a5SAdrian Chadd * Formulate first tx descriptor with tx controls. 993b8e788a5SAdrian Chadd */ 994b8e788a5SAdrian Chadd ds = bf->bf_desc; 995b8e788a5SAdrian Chadd /* XXX check return value? */ 996b8e788a5SAdrian Chadd ath_hal_setuptxdesc(ah, ds 997b8e788a5SAdrian Chadd , pktlen /* packet length */ 998b8e788a5SAdrian Chadd , hdrlen /* header length */ 999b8e788a5SAdrian Chadd , atype /* Atheros packet type */ 1000b8e788a5SAdrian Chadd , params->ibp_power /* txpower */ 1001b8e788a5SAdrian Chadd , txrate, try0 /* series 0 rate/tries */ 1002b8e788a5SAdrian Chadd , keyix /* key cache index */ 1003b8e788a5SAdrian Chadd , txantenna /* antenna mode */ 1004b8e788a5SAdrian Chadd , flags /* flags */ 1005b8e788a5SAdrian Chadd , ctsrate /* rts/cts rate */ 1006b8e788a5SAdrian Chadd , ctsduration /* rts/cts duration */ 1007b8e788a5SAdrian Chadd ); 1008b8e788a5SAdrian Chadd bf->bf_txflags = flags; 1009b8e788a5SAdrian Chadd 1010c1782ce0SAdrian Chadd if (ath_tx_is_11n(sc)) { 1011c1782ce0SAdrian Chadd rate[0] = ath_tx_findrix(sc, params->ibp_rate0); 1012c1782ce0SAdrian Chadd try[0] = params->ibp_try0; 1013c1782ce0SAdrian Chadd 1014c1782ce0SAdrian Chadd if (ismrr) { 1015c1782ce0SAdrian Chadd /* Remember, rate[] is actually an array of rix's -adrian */ 1016c1782ce0SAdrian Chadd rate[0] = ath_tx_findrix(sc, params->ibp_rate0); 1017c1782ce0SAdrian Chadd rate[1] = ath_tx_findrix(sc, params->ibp_rate1); 1018c1782ce0SAdrian Chadd rate[2] = ath_tx_findrix(sc, params->ibp_rate2); 1019c1782ce0SAdrian Chadd rate[3] = ath_tx_findrix(sc, params->ibp_rate3); 1020c1782ce0SAdrian Chadd 1021c1782ce0SAdrian Chadd try[0] = params->ibp_try0; 1022c1782ce0SAdrian Chadd try[1] = params->ibp_try1; 1023c1782ce0SAdrian Chadd try[2] = params->ibp_try2; 1024c1782ce0SAdrian Chadd try[3] = params->ibp_try3; 1025c1782ce0SAdrian Chadd } 1026c1782ce0SAdrian Chadd } else { 1027b8e788a5SAdrian Chadd if (ismrr) { 1028b8e788a5SAdrian Chadd rix = ath_tx_findrix(sc, params->ibp_rate1); 1029b8e788a5SAdrian Chadd rate1 = rt->info[rix].rateCode; 1030b8e788a5SAdrian Chadd if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) 1031b8e788a5SAdrian Chadd rate1 |= rt->info[rix].shortPreamble; 1032b8e788a5SAdrian Chadd if (params->ibp_try2) { 1033b8e788a5SAdrian Chadd rix = ath_tx_findrix(sc, params->ibp_rate2); 1034b8e788a5SAdrian Chadd rate2 = rt->info[rix].rateCode; 1035b8e788a5SAdrian Chadd if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) 1036b8e788a5SAdrian Chadd rate2 |= rt->info[rix].shortPreamble; 1037b8e788a5SAdrian Chadd } else 1038b8e788a5SAdrian Chadd rate2 = 0; 1039b8e788a5SAdrian Chadd if (params->ibp_try3) { 1040b8e788a5SAdrian Chadd rix = ath_tx_findrix(sc, params->ibp_rate3); 1041b8e788a5SAdrian Chadd rate3 = rt->info[rix].rateCode; 1042b8e788a5SAdrian Chadd if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) 1043b8e788a5SAdrian Chadd rate3 |= rt->info[rix].shortPreamble; 1044b8e788a5SAdrian Chadd } else 1045b8e788a5SAdrian Chadd rate3 = 0; 1046b8e788a5SAdrian Chadd ath_hal_setupxtxdesc(ah, ds 1047b8e788a5SAdrian Chadd , rate1, params->ibp_try1 /* series 1 */ 1048b8e788a5SAdrian Chadd , rate2, params->ibp_try2 /* series 2 */ 1049b8e788a5SAdrian Chadd , rate3, params->ibp_try3 /* series 3 */ 1050b8e788a5SAdrian Chadd ); 1051b8e788a5SAdrian Chadd } 1052c1782ce0SAdrian Chadd } 1053c1782ce0SAdrian Chadd 1054c1782ce0SAdrian Chadd if (ath_tx_is_11n(sc)) { 1055c1782ce0SAdrian Chadd /* 1056c1782ce0SAdrian Chadd * notice that rix doesn't include any of the "magic" flags txrate 1057c1782ce0SAdrian Chadd * does for communicating "other stuff" to the HAL. 1058c1782ce0SAdrian Chadd */ 1059bf26df36SAdrian Chadd ath_buf_set_rate(sc, ni, bf, pktlen, flags, ctsrate, (atype == HAL_PKT_TYPE_PSPOLL), rate, try); 1060c1782ce0SAdrian Chadd } 1061b8e788a5SAdrian Chadd 1062b8e788a5SAdrian Chadd /* NB: no buffered multicast in power save support */ 1063b8e788a5SAdrian Chadd ath_tx_handoff(sc, sc->sc_ac2q[pri], bf); 1064b8e788a5SAdrian Chadd return 0; 1065b8e788a5SAdrian Chadd } 1066b8e788a5SAdrian Chadd 1067b8e788a5SAdrian Chadd int 1068b8e788a5SAdrian Chadd ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 1069b8e788a5SAdrian Chadd const struct ieee80211_bpf_params *params) 1070b8e788a5SAdrian Chadd { 1071b8e788a5SAdrian Chadd struct ieee80211com *ic = ni->ni_ic; 1072b8e788a5SAdrian Chadd struct ifnet *ifp = ic->ic_ifp; 1073b8e788a5SAdrian Chadd struct ath_softc *sc = ifp->if_softc; 1074b8e788a5SAdrian Chadd struct ath_buf *bf; 1075b8e788a5SAdrian Chadd int error; 1076b8e788a5SAdrian Chadd 1077b8e788a5SAdrian Chadd if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) { 1078b8e788a5SAdrian Chadd DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__, 1079b8e788a5SAdrian Chadd (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ? 1080b8e788a5SAdrian Chadd "!running" : "invalid"); 1081b8e788a5SAdrian Chadd m_freem(m); 1082b8e788a5SAdrian Chadd error = ENETDOWN; 1083b8e788a5SAdrian Chadd goto bad; 1084b8e788a5SAdrian Chadd } 1085b8e788a5SAdrian Chadd /* 1086b8e788a5SAdrian Chadd * Grab a TX buffer and associated resources. 1087b8e788a5SAdrian Chadd */ 1088b8e788a5SAdrian Chadd bf = ath_getbuf(sc); 1089b8e788a5SAdrian Chadd if (bf == NULL) { 1090b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_nobuf++; 1091b8e788a5SAdrian Chadd m_freem(m); 1092b8e788a5SAdrian Chadd error = ENOBUFS; 1093b8e788a5SAdrian Chadd goto bad; 1094b8e788a5SAdrian Chadd } 1095b8e788a5SAdrian Chadd 1096b8e788a5SAdrian Chadd if (params == NULL) { 1097b8e788a5SAdrian Chadd /* 1098b8e788a5SAdrian Chadd * Legacy path; interpret frame contents to decide 1099b8e788a5SAdrian Chadd * precisely how to send the frame. 1100b8e788a5SAdrian Chadd */ 1101b8e788a5SAdrian Chadd if (ath_tx_start(sc, ni, bf, m)) { 1102b8e788a5SAdrian Chadd error = EIO; /* XXX */ 1103b8e788a5SAdrian Chadd goto bad2; 1104b8e788a5SAdrian Chadd } 1105b8e788a5SAdrian Chadd } else { 1106b8e788a5SAdrian Chadd /* 1107b8e788a5SAdrian Chadd * Caller supplied explicit parameters to use in 1108b8e788a5SAdrian Chadd * sending the frame. 1109b8e788a5SAdrian Chadd */ 1110b8e788a5SAdrian Chadd if (ath_tx_raw_start(sc, ni, bf, m, params)) { 1111b8e788a5SAdrian Chadd error = EIO; /* XXX */ 1112b8e788a5SAdrian Chadd goto bad2; 1113b8e788a5SAdrian Chadd } 1114b8e788a5SAdrian Chadd } 1115b8e788a5SAdrian Chadd sc->sc_wd_timer = 5; 1116b8e788a5SAdrian Chadd ifp->if_opackets++; 1117b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_raw++; 1118b8e788a5SAdrian Chadd 1119b8e788a5SAdrian Chadd return 0; 1120b8e788a5SAdrian Chadd bad2: 1121b8e788a5SAdrian Chadd ATH_TXBUF_LOCK(sc); 11226b349e5aSAdrian Chadd TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list); 1123b8e788a5SAdrian Chadd ATH_TXBUF_UNLOCK(sc); 1124b8e788a5SAdrian Chadd bad: 1125b8e788a5SAdrian Chadd ifp->if_oerrors++; 1126b8e788a5SAdrian Chadd sc->sc_stats.ast_tx_raw_fail++; 1127b8e788a5SAdrian Chadd ieee80211_free_node(ni); 1128b8e788a5SAdrian Chadd return error; 1129b8e788a5SAdrian Chadd } 1130