if_ath_tx_edma.c revision 239204
1181053Srwatson/*- 2188313Srwatson * Copyright (c) 2012 Adrian Chadd <adrian@FreeBSD.org> 3155192Srwatson * All rights reserved. 4155192Srwatson * 5155192Srwatson * Redistribution and use in source and binary forms, with or without 6155192Srwatson * modification, are permitted provided that the following conditions 7155192Srwatson * are met: 8155192Srwatson * 1. Redistributions of source code must retain the above copyright 9155192Srwatson * notice, this list of conditions and the following disclaimer, 10155192Srwatson * without modification. 11155192Srwatson * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12155192Srwatson * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13180701Srwatson * redistribution must be conditioned upon including a substantially 14155192Srwatson * similar Disclaimer requirement for further binary redistribution. 15155192Srwatson * 16155192Srwatson * NO WARRANTY 17155192Srwatson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18155192Srwatson * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19155192Srwatson * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20155192Srwatson * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21155192Srwatson * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22155192Srwatson * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23155192Srwatson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24155192Srwatson * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25155192Srwatson * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26155192Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27155192Srwatson * THE POSSIBILITY OF SUCH DAMAGES. 28155192Srwatson */ 29155192Srwatson 30155192Srwatson#include <sys/cdefs.h> 31155192Srwatson__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx_edma.c 239204 2012-08-12 00:37:29Z adrian $"); 32155192Srwatson 33155192Srwatson/* 34155192Srwatson * Driver for the Atheros Wireless LAN controller. 35155192Srwatson * 36155192Srwatson * This software is derived from work of Atsushi Onoe; his contribution 37156882Srwatson * is greatly appreciated. 38156882Srwatson */ 39155192Srwatson 40155192Srwatson#include "opt_inet.h" 41155192Srwatson#include "opt_ath.h" 42155192Srwatson/* 43155192Srwatson * This is needed for register operations which are performed 44155192Srwatson * by the driver - eg, calls to ath_hal_gettsf32(). 45155192Srwatson * 46155192Srwatson * It's also required for any AH_DEBUG checks in here, eg the 47155192Srwatson * module dependencies. 48155192Srwatson */ 49155192Srwatson#include "opt_ah.h" 50155192Srwatson#include "opt_wlan.h" 51155192Srwatson 52155192Srwatson#include <sys/param.h> 53195177Ssson#include <sys/systm.h> 54155192Srwatson#include <sys/sysctl.h> 55155192Srwatson#include <sys/mbuf.h> 56155192Srwatson#include <sys/malloc.h> 57156889Srwatson#include <sys/lock.h> 58156889Srwatson#include <sys/mutex.h> 59155192Srwatson#include <sys/kernel.h> 60155192Srwatson#include <sys/socket.h> 61155192Srwatson#include <sys/sockio.h> 62155192Srwatson#include <sys/errno.h> 63155192Srwatson#include <sys/callout.h> 64155192Srwatson#include <sys/bus.h> 65161813Swsalamon#include <sys/endian.h> 66161813Swsalamon#include <sys/kthread.h> 67155192Srwatson#include <sys/taskqueue.h> 68155192Srwatson#include <sys/priv.h> 69155192Srwatson#include <sys/module.h> 70155192Srwatson#include <sys/ktr.h> 71155192Srwatson#include <sys/smp.h> /* for mp_ncpus */ 72156889Srwatson 73156889Srwatson#include <machine/bus.h> 74156889Srwatson 75155192Srwatson#include <net/if.h> 76155192Srwatson#include <net/if_dl.h> 77159269Srwatson#include <net/if_media.h> 78159269Srwatson#include <net/if_types.h> 79159269Srwatson#include <net/if_arp.h> 80155192Srwatson#include <net/ethernet.h> 81155192Srwatson#include <net/if_llc.h> 82155192Srwatson 83155192Srwatson#include <net80211/ieee80211_var.h> 84159269Srwatson#include <net80211/ieee80211_regdomain.h> 85159269Srwatson#ifdef IEEE80211_SUPPORT_SUPERG 86159269Srwatson#include <net80211/ieee80211_superg.h> 87162380Scsjp#endif 88162380Scsjp#ifdef IEEE80211_SUPPORT_TDMA 89162380Scsjp#include <net80211/ieee80211_tdma.h> 90155192Srwatson#endif 91155192Srwatson 92155192Srwatson#include <net/bpf.h> 93155192Srwatson 94155192Srwatson#ifdef INET 95155192Srwatson#include <netinet/in.h> 96155192Srwatson#include <netinet/if_ether.h> 97155192Srwatson#endif 98156889Srwatson 99156889Srwatson#include <dev/ath/if_athvar.h> 100156889Srwatson#include <dev/ath/ath_hal/ah_devid.h> /* XXX for softled */ 101156889Srwatson#include <dev/ath/ath_hal/ah_diagcodes.h> 102156889Srwatson 103156889Srwatson#include <dev/ath/if_ath_debug.h> 104156889Srwatson#include <dev/ath/if_ath_misc.h> 105155192Srwatson#include <dev/ath/if_ath_tsf.h> 106155192Srwatson#include <dev/ath/if_ath_tx.h> 107155192Srwatson#include <dev/ath/if_ath_sysctl.h> 108195177Ssson#include <dev/ath/if_ath_led.h> 109195177Ssson#include <dev/ath/if_ath_keycache.h> 110155192Srwatson#include <dev/ath/if_ath_rx.h> 111155192Srwatson#include <dev/ath/if_ath_beacon.h> 112155192Srwatson#include <dev/ath/if_athdfs.h> 113180709Srwatson 114155192Srwatson#ifdef ATH_TX99_DIAG 115155192Srwatson#include <dev/ath/ath_tx99/ath_tx99.h> 116156889Srwatson#endif 117156889Srwatson 118156889Srwatson#include <dev/ath/if_ath_tx_edma.h> 119156889Srwatson 120155192Srwatson/* 121155192Srwatson * some general macros 122191270Srwatson */ 123191270Srwatson#define INCR(_l, _sz) (_l) ++; (_l) &= ((_sz) - 1) 124191270Srwatson#define DECR(_l, _sz) (_l) --; (_l) &= ((_sz) - 1) 125191270Srwatson 126191270Srwatson/* 127191270Srwatson * XXX doesn't belong here, and should be tunable 128191270Srwatson */ 129191270Srwatson#define ATH_TXSTATUS_RING_SIZE 512 130191270Srwatson 131191270SrwatsonMALLOC_DECLARE(M_ATHDEV); 132191270Srwatson 133191270Srwatson/* 134191270Srwatson * Re-initialise the DMA FIFO with the current contents of 135155192Srwatson * said TXQ. 136155192Srwatson * 137191270Srwatson * This should only be called as part of the chip reset path, as it 138191270Srwatson * assumes the FIFO is currently empty. 139191270Srwatson * 140155192Srwatson * TODO: verify that a cold/warm reset does clear the TX FIFO, so 141191270Srwatson * writing in a partially-filled FIFO will not cause double-entries 142191270Srwatson * to appear. 143155192Srwatson */ 144155192Srwatsonstatic void 145155192Srwatsonath_edma_dma_restart(struct ath_softc *sc, struct ath_txq *txq) 146155192Srwatson{ 147155192Srwatson 148155192Srwatson device_printf(sc->sc_dev, "%s: called: txq=%p, qnum=%d\n", 149191270Srwatson __func__, 150155192Srwatson txq, 151155192Srwatson txq->axq_qnum); 152184856Scsjp} 153155192Srwatson 154155192Srwatson/* 155155192Srwatson * Hand off this frame to a hardware queue. 156156889Srwatson * 157156889Srwatson * Things are a bit hairy in the EDMA world. The TX FIFO is only 158156889Srwatson * 8 entries deep, so we need to keep track of exactly what we've 159155192Srwatson * pushed into the FIFO and what's just sitting in the TX queue, 160155192Srwatson * waiting to go out. 161155192Srwatson * 162155192Srwatson * So this is split into two halves - frames get appended to the 163155192Srwatson * TXQ; then a scheduler is called to push some frames into the 164155192Srwatson * actual TX FIFO. 165155192Srwatson */ 166155192Srwatsonstatic void 167155192Srwatsonath_edma_xmit_handoff_hw(struct ath_softc *sc, struct ath_txq *txq, 168155192Srwatson struct ath_buf *bf) 169155192Srwatson{ 170155192Srwatson struct ath_hal *ah = sc->sc_ah; 171155192Srwatson 172156889Srwatson ATH_TXQ_LOCK_ASSERT(txq); 173156889Srwatson 174156889Srwatson KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0, 175156889Srwatson ("%s: busy status 0x%x", __func__, bf->bf_flags)); 176156889Srwatson 177156889Srwatson /* 178156889Srwatson * XXX TODO: write a hard-coded check to ensure that 179156889Srwatson * the queue id in the TX descriptor matches txq->axq_qnum. 180168688Scsjp */ 181156889Srwatson 182155192Srwatson /* Update aggr stats */ 183155192Srwatson if (bf->bf_state.bfs_aggr) 184156889Srwatson txq->axq_aggr_depth++; 185156889Srwatson 186156889Srwatson /* Push and update frame stats */ 187156889Srwatson ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); 188156889Srwatson 189156889Srwatson /* Only schedule to the FIFO if there's space */ 190156889Srwatson if (txq->axq_fifo_depth < HAL_TXFIFO_DEPTH) { 191156889Srwatson ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); 192156889Srwatson ath_hal_txstart(ah, txq->axq_qnum); 193168688Scsjp } 194156889Srwatson} 195156889Srwatson 196156889Srwatson/* 197156889Srwatson * Hand off this frame to a multicast software queue. 198156889Srwatson * 199195925Srwatson * Unlike legacy DMA, this doesn't chain together frames via the 200195925Srwatson * link pointer. Instead, they're just added to the queue. 201156889Srwatson * When it comes time to populate the CABQ, these frames should 202156889Srwatson * be individually pushed into the FIFO as appropriate. 203156889Srwatson * 204156889Srwatson * Yes, this does mean that I'll eventually have to flesh out some 205246691Spjd * replacement code to handle populating the CABQ, rather than 206156889Srwatson * what's done in ath_beacon_generate(). It'll have to push each 207156889Srwatson * frame from the HW CABQ to the FIFO rather than just appending 208156889Srwatson * it to the existing TXQ and kicking off DMA. 209156889Srwatson */ 210156889Srwatsonstatic void 211156889Srwatsonath_edma_xmit_handoff_mcast(struct ath_softc *sc, struct ath_txq *txq, 212156889Srwatson struct ath_buf *bf) 213156889Srwatson{ 214156889Srwatson 215156889Srwatson ATH_TXQ_LOCK_ASSERT(txq); 216156889Srwatson KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0, 217156889Srwatson ("%s: busy status 0x%x", __func__, bf->bf_flags)); 218156889Srwatson 219156889Srwatson /* 220156889Srwatson * XXX this is mostly duplicated in ath_tx_handoff_mcast(). 221156889Srwatson */ 222246691Spjd if (ATH_TXQ_FIRST(txq) != NULL) { 223156889Srwatson struct ath_buf *bf_last = ATH_TXQ_LAST(txq, axq_q_s); 224156889Srwatson struct ieee80211_frame *wh; 225161813Swsalamon 226161813Swsalamon /* mark previous frame */ 227161813Swsalamon wh = mtod(bf_last->bf_m, struct ieee80211_frame *); 228161813Swsalamon wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA; 229156889Srwatson 230156889Srwatson /* sync descriptor to memory */ 231164011Scsjp bus_dmamap_sync(sc->sc_dmat, bf_last->bf_dmamap, 232224181Sjonathan BUS_DMASYNC_PREWRITE); 233245573Scsjp } 234155192Srwatson 235155192Srwatson ATH_TXQ_INSERT_TAIL(txq, bf, bf_list); 236155192Srwatson} 237155192Srwatson 238155192Srwatson/* 239155192Srwatson * Handoff this frame to the hardware. 240155192Srwatson * 241195939Srwatson * For the multicast queue, this will treat it as a software queue 242195939Srwatson * and append it to the list, after updating the MORE_DATA flag 243195939Srwatson * in the previous frame. The cabq processing code will ensure 244195939Srwatson * that the queue contents gets transferred over. 245195939Srwatson * 246195939Srwatson * For the hardware queues, this will queue a frame to the queue 247195939Srwatson * like before, then populate the FIFO from that. Since the 248195939Srwatson * EDMA hardware has 8 FIFO slots per TXQ, this ensures that 249195939Srwatson * frames such as management frames don't get prematurely dropped. 250195939Srwatson * 251195939Srwatson * This does imply that a similar flush-hwq-to-fifoq method will 252195939Srwatson * need to be called from the processq function, before the 253195939Srwatson * per-node software scheduler is called. 254195939Srwatson */ 255195939Srwatsonstatic void 256195939Srwatsonath_edma_xmit_handoff(struct ath_softc *sc, struct ath_txq *txq, 257195939Srwatson struct ath_buf *bf) 258195939Srwatson{ 259195939Srwatson 260195939Srwatson ATH_TXQ_LOCK_ASSERT(txq); 261195939Srwatson 262195939Srwatson device_printf(sc->sc_dev, "%s: called; bf=%p, txq=%p, qnum=%d\n", 263195939Srwatson __func__, 264195939Srwatson bf, 265195939Srwatson txq, 266195939Srwatson txq->axq_qnum); 267195939Srwatson 268195939Srwatson if (txq->axq_qnum == ATH_TXQ_SWQ) 269195939Srwatson ath_edma_xmit_handoff_mcast(sc, txq, bf); 270195939Srwatson else 271195939Srwatson ath_edma_xmit_handoff_hw(sc, txq, bf); 272195939Srwatson 273195939Srwatson#if 0 274195939Srwatson /* 275195939Srwatson * XXX For now this is a placeholder; free the buffer 276195939Srwatson * and inform the stack that the TX failed. 277195939Srwatson */ 278195939Srwatson ath_tx_default_comp(sc, bf, 1); 279195939Srwatson#endif 280195939Srwatson} 281195939Srwatson 282195939Srwatsonstatic int 283195939Srwatsonath_edma_setup_txfifo(struct ath_softc *sc, int qnum) 284195939Srwatson{ 285195939Srwatson struct ath_tx_edma_fifo *te = &sc->sc_txedma[qnum]; 286195939Srwatson 287195939Srwatson te->m_fifo = malloc(sizeof(struct ath_buf *) * HAL_TXFIFO_DEPTH, 288195939Srwatson M_ATHDEV, 289195939Srwatson M_NOWAIT | M_ZERO); 290195939Srwatson if (te->m_fifo == NULL) { 291195939Srwatson device_printf(sc->sc_dev, "%s: malloc failed\n", 292195939Srwatson __func__); 293224181Sjonathan return (-ENOMEM); 294195939Srwatson } 295195939Srwatson 296195939Srwatson /* 297155192Srwatson * Set initial "empty" state. 298155192Srwatson */ 299155192Srwatson te->m_fifo_head = te->m_fifo_tail = te->m_fifo_depth = 0; 300155192Srwatson 301195926Srwatson return (0); 302195926Srwatson} 303195926Srwatson 304155192Srwatsonstatic int 305155192Srwatsonath_edma_free_txfifo(struct ath_softc *sc, int qnum) 306155192Srwatson{ 307156889Srwatson struct ath_tx_edma_fifo *te = &sc->sc_txedma[qnum]; 308156889Srwatson 309155192Srwatson /* XXX TODO: actually deref the ath_buf entries? */ 310155192Srwatson free(te->m_fifo, M_ATHDEV); 311156889Srwatson return (0); 312156889Srwatson} 313156889Srwatson 314156889Srwatsonstatic int 315156889Srwatsonath_edma_dma_txsetup(struct ath_softc *sc) 316156889Srwatson{ 317155192Srwatson int error; 318156888Srwatson int i; 319155192Srwatson 320155192Srwatson error = ath_descdma_alloc_desc(sc, &sc->sc_txsdma, 321155192Srwatson NULL, "txcomp", sc->sc_tx_statuslen, ATH_TXSTATUS_RING_SIZE); 322155192Srwatson if (error != 0) 323155192Srwatson return (error); 324155192Srwatson 325156888Srwatson ath_hal_setuptxstatusring(sc->sc_ah, 326155192Srwatson (void *) sc->sc_txsdma.dd_desc, 327155192Srwatson sc->sc_txsdma.dd_desc_paddr, 328155192Srwatson ATH_TXSTATUS_RING_SIZE); 329155192Srwatson 330155192Srwatson for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 331155192Srwatson ath_edma_setup_txfifo(sc, i); 332155192Srwatson } 333156291Srwatson 334156889Srwatson 335156889Srwatson return (0); 336155192Srwatson} 337155192Srwatson 338155192Srwatsonstatic int 339155192Srwatsonath_edma_dma_txteardown(struct ath_softc *sc) 340156889Srwatson{ 341156889Srwatson int i; 342155192Srwatson 343155192Srwatson for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 344155192Srwatson ath_edma_free_txfifo(sc, i); 345155192Srwatson } 346156889Srwatson 347156889Srwatson ath_descdma_cleanup(sc, &sc->sc_txsdma, NULL); 348156889Srwatson return (0); 349155192Srwatson} 350156888Srwatson 351156888Srwatson/* 352156888Srwatson * Drain all TXQs, potentially after completing the existing completed 353156888Srwatson * frames. 354156889Srwatson */ 355159261Srwatsonstatic void 356159261Srwatsonath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type) 357156889Srwatson{ 358191270Srwatson 359191270Srwatson device_printf(sc->sc_dev, "%s: called\n", __func__); 360156889Srwatson} 361156888Srwatson 362156888Srwatson/* 363155192Srwatson * Completely drain the TXQ, completing frames that were completed. 364155192Srwatson * 365155192Srwatson * This is only called to _explictly_ drain the frames from a queue 366155192Srwatson * without caring if they were completed or not. 367155192Srwatson */ 368155192Srwatsonstatic void 369155192Srwatsonath_edma_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq) 370155192Srwatson{ 371155192Srwatson 372155192Srwatson device_printf(sc->sc_dev, "%s: called\n", __func__); 373155192Srwatson} 374156889Srwatson 375170196Srwatson/* 376155192Srwatson * Process the TX status queue. 377155192Srwatson */ 378155192Srwatsonstatic void 379155192Srwatsonath_edma_tx_proc(void *arg, int npending) 380155192Srwatson{ 381155192Srwatson struct ath_softc *sc = (struct ath_softc *) arg; 382159269Srwatson struct ath_hal *ah = sc->sc_ah; 383159269Srwatson HAL_STATUS status; 384155192Srwatson struct ath_tx_status ts; 385155192Srwatson struct ath_txq *txq; 386155192Srwatson 387176690Srwatson device_printf(sc->sc_dev, "%s: called, npending=%d\n", 388176690Srwatson __func__, npending); 389195925Srwatson 390188313Srwatson for (;;) { 391188313Srwatson ATH_TXSTATUS_LOCK(sc); 392243726Spjd status = ath_hal_txprocdesc(ah, NULL, (void *) &ts); 393243726Spjd ATH_TXSTATUS_UNLOCK(sc); 394188313Srwatson 395155192Srwatson if (status != HAL_OK) 396155192Srwatson break; 397155192Srwatson 398155192Srwatson /* 399155192Srwatson * At this point we have a valid status descriptor. 400155192Srwatson * The QID and descriptor ID (which currently isn't set) 401176686Srwatson * is part of the status. 402155192Srwatson * 403155192Srwatson * We then assume that the descriptor in question is the 404184858Srwatson * -head- of the given QID. Eventually we should verify 405184858Srwatson * this by using the descriptor ID. 406184858Srwatson */ 407184858Srwatson device_printf(sc->sc_dev, "%s: qcuid=%d\n", 408184858Srwatson __func__, 409184858Srwatson ts.ts_queue_id); 410155192Srwatson 411155192Srwatson txq = &sc->sc_txq[ts.ts_queue_id]; 412155192Srwatson } 413156888Srwatson} 414155192Srwatson 415155192Srwatsonstatic void 416155192Srwatsonath_edma_attach_comp_func(struct ath_softc *sc) 417156888Srwatson{ 418155192Srwatson 419155408Srwatson TASK_INIT(&sc->sc_txtask, 0, ath_edma_tx_proc, sc); 420155408Srwatson} 421155408Srwatson 422159269Srwatsonvoid 423159269Srwatsonath_xmit_setup_edma(struct ath_softc *sc) 424159269Srwatson{ 425159269Srwatson 426159269Srwatson /* Fetch EDMA field and buffer sizes */ 427155408Srwatson (void) ath_hal_gettxdesclen(sc->sc_ah, &sc->sc_tx_desclen); 428156882Srwatson (void) ath_hal_gettxstatuslen(sc->sc_ah, &sc->sc_tx_statuslen); 429 (void) ath_hal_getntxmaps(sc->sc_ah, &sc->sc_tx_nmaps); 430 431 device_printf(sc->sc_dev, "TX descriptor length: %d\n", 432 sc->sc_tx_desclen); 433 device_printf(sc->sc_dev, "TX status length: %d\n", 434 sc->sc_tx_statuslen); 435 device_printf(sc->sc_dev, "TX buffers per descriptor: %d\n", 436 sc->sc_tx_nmaps); 437 438 sc->sc_tx.xmit_setup = ath_edma_dma_txsetup; 439 sc->sc_tx.xmit_teardown = ath_edma_dma_txteardown; 440 sc->sc_tx.xmit_attach_comp_func = ath_edma_attach_comp_func; 441 442 sc->sc_tx.xmit_dma_restart = ath_edma_dma_restart; 443 sc->sc_tx.xmit_handoff = ath_edma_xmit_handoff; 444 sc->sc_tx.xmit_drainq = ath_edma_tx_draintxq; 445 sc->sc_tx.xmit_drain = ath_edma_tx_drain; 446} 447