13fdfc330SAdrian Chadd /*- 23fdfc330SAdrian Chadd * Copyright (c) 2012 Adrian Chadd <adrian@FreeBSD.org> 33fdfc330SAdrian Chadd * All rights reserved. 43fdfc330SAdrian Chadd * 53fdfc330SAdrian Chadd * Redistribution and use in source and binary forms, with or without 63fdfc330SAdrian Chadd * modification, are permitted provided that the following conditions 73fdfc330SAdrian Chadd * are met: 83fdfc330SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 93fdfc330SAdrian Chadd * notice, this list of conditions and the following disclaimer, 103fdfc330SAdrian Chadd * without modification. 113fdfc330SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 123fdfc330SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 133fdfc330SAdrian Chadd * redistribution must be conditioned upon including a substantially 143fdfc330SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 153fdfc330SAdrian Chadd * 163fdfc330SAdrian Chadd * NO WARRANTY 173fdfc330SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 183fdfc330SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 193fdfc330SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 203fdfc330SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 213fdfc330SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 223fdfc330SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 233fdfc330SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 243fdfc330SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 253fdfc330SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 263fdfc330SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 273fdfc330SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 283fdfc330SAdrian Chadd */ 293fdfc330SAdrian Chadd 303fdfc330SAdrian Chadd #include <sys/cdefs.h> 313fdfc330SAdrian Chadd __FBSDID("$FreeBSD$"); 323fdfc330SAdrian Chadd 333fdfc330SAdrian Chadd /* 343fdfc330SAdrian Chadd * Driver for the Atheros Wireless LAN controller. 353fdfc330SAdrian Chadd * 363fdfc330SAdrian Chadd * This software is derived from work of Atsushi Onoe; his contribution 373fdfc330SAdrian Chadd * is greatly appreciated. 383fdfc330SAdrian Chadd */ 393fdfc330SAdrian Chadd 403fdfc330SAdrian Chadd #include "opt_inet.h" 413fdfc330SAdrian Chadd #include "opt_ath.h" 423fdfc330SAdrian Chadd /* 433fdfc330SAdrian Chadd * This is needed for register operations which are performed 443fdfc330SAdrian Chadd * by the driver - eg, calls to ath_hal_gettsf32(). 453fdfc330SAdrian Chadd * 463fdfc330SAdrian Chadd * It's also required for any AH_DEBUG checks in here, eg the 473fdfc330SAdrian Chadd * module dependencies. 483fdfc330SAdrian Chadd */ 493fdfc330SAdrian Chadd #include "opt_ah.h" 503fdfc330SAdrian Chadd #include "opt_wlan.h" 513fdfc330SAdrian Chadd 523fdfc330SAdrian Chadd #include <sys/param.h> 533fdfc330SAdrian Chadd #include <sys/systm.h> 543fdfc330SAdrian Chadd #include <sys/sysctl.h> 553fdfc330SAdrian Chadd #include <sys/mbuf.h> 563fdfc330SAdrian Chadd #include <sys/malloc.h> 573fdfc330SAdrian Chadd #include <sys/lock.h> 583fdfc330SAdrian Chadd #include <sys/mutex.h> 593fdfc330SAdrian Chadd #include <sys/kernel.h> 603fdfc330SAdrian Chadd #include <sys/socket.h> 613fdfc330SAdrian Chadd #include <sys/sockio.h> 623fdfc330SAdrian Chadd #include <sys/errno.h> 633fdfc330SAdrian Chadd #include <sys/callout.h> 643fdfc330SAdrian Chadd #include <sys/bus.h> 653fdfc330SAdrian Chadd #include <sys/endian.h> 663fdfc330SAdrian Chadd #include <sys/kthread.h> 673fdfc330SAdrian Chadd #include <sys/taskqueue.h> 683fdfc330SAdrian Chadd #include <sys/priv.h> 693fdfc330SAdrian Chadd #include <sys/module.h> 703fdfc330SAdrian Chadd #include <sys/ktr.h> 713fdfc330SAdrian Chadd #include <sys/smp.h> /* for mp_ncpus */ 723fdfc330SAdrian Chadd 733fdfc330SAdrian Chadd #include <machine/bus.h> 743fdfc330SAdrian Chadd 753fdfc330SAdrian Chadd #include <net/if.h> 763fdfc330SAdrian Chadd #include <net/if_dl.h> 773fdfc330SAdrian Chadd #include <net/if_media.h> 783fdfc330SAdrian Chadd #include <net/if_types.h> 793fdfc330SAdrian Chadd #include <net/if_arp.h> 803fdfc330SAdrian Chadd #include <net/ethernet.h> 813fdfc330SAdrian Chadd #include <net/if_llc.h> 823fdfc330SAdrian Chadd 833fdfc330SAdrian Chadd #include <net80211/ieee80211_var.h> 843fdfc330SAdrian Chadd #include <net80211/ieee80211_regdomain.h> 853fdfc330SAdrian Chadd #ifdef IEEE80211_SUPPORT_SUPERG 863fdfc330SAdrian Chadd #include <net80211/ieee80211_superg.h> 873fdfc330SAdrian Chadd #endif 883fdfc330SAdrian Chadd #ifdef IEEE80211_SUPPORT_TDMA 893fdfc330SAdrian Chadd #include <net80211/ieee80211_tdma.h> 903fdfc330SAdrian Chadd #endif 913fdfc330SAdrian Chadd 923fdfc330SAdrian Chadd #include <net/bpf.h> 933fdfc330SAdrian Chadd 943fdfc330SAdrian Chadd #ifdef INET 953fdfc330SAdrian Chadd #include <netinet/in.h> 963fdfc330SAdrian Chadd #include <netinet/if_ether.h> 973fdfc330SAdrian Chadd #endif 983fdfc330SAdrian Chadd 993fdfc330SAdrian Chadd #include <dev/ath/if_athvar.h> 1003fdfc330SAdrian Chadd #include <dev/ath/ath_hal/ah_devid.h> /* XXX for softled */ 1013fdfc330SAdrian Chadd #include <dev/ath/ath_hal/ah_diagcodes.h> 1023fdfc330SAdrian Chadd 1033fdfc330SAdrian Chadd #include <dev/ath/if_ath_debug.h> 1043fdfc330SAdrian Chadd #include <dev/ath/if_ath_misc.h> 1053fdfc330SAdrian Chadd #include <dev/ath/if_ath_tsf.h> 1063fdfc330SAdrian Chadd #include <dev/ath/if_ath_tx.h> 1073fdfc330SAdrian Chadd #include <dev/ath/if_ath_sysctl.h> 1083fdfc330SAdrian Chadd #include <dev/ath/if_ath_led.h> 1093fdfc330SAdrian Chadd #include <dev/ath/if_ath_keycache.h> 1103fdfc330SAdrian Chadd #include <dev/ath/if_ath_rx.h> 1113fdfc330SAdrian Chadd #include <dev/ath/if_ath_beacon.h> 1123fdfc330SAdrian Chadd #include <dev/ath/if_athdfs.h> 1133fdfc330SAdrian Chadd 1143fdfc330SAdrian Chadd #ifdef ATH_TX99_DIAG 1153fdfc330SAdrian Chadd #include <dev/ath/ath_tx99/ath_tx99.h> 1163fdfc330SAdrian Chadd #endif 1173fdfc330SAdrian Chadd 1183fdfc330SAdrian Chadd #include <dev/ath/if_ath_tx_edma.h> 1193fdfc330SAdrian Chadd 1203fdfc330SAdrian Chadd /* 1213fdfc330SAdrian Chadd * some general macros 1223fdfc330SAdrian Chadd */ 1233fdfc330SAdrian Chadd #define INCR(_l, _sz) (_l) ++; (_l) &= ((_sz) - 1) 1243fdfc330SAdrian Chadd #define DECR(_l, _sz) (_l) --; (_l) &= ((_sz) - 1) 1253fdfc330SAdrian Chadd 126ba3fd9d8SAdrian Chadd /* 127ba3fd9d8SAdrian Chadd * XXX doesn't belong here, and should be tunable 128ba3fd9d8SAdrian Chadd */ 129ba3fd9d8SAdrian Chadd #define ATH_TXSTATUS_RING_SIZE 512 130ba3fd9d8SAdrian Chadd 1313fdfc330SAdrian Chadd MALLOC_DECLARE(M_ATHDEV); 1323fdfc330SAdrian Chadd 133*746bab5bSAdrian Chadd /* 134*746bab5bSAdrian Chadd * Re-initialise the DMA FIFO with the current contents of 135*746bab5bSAdrian Chadd * said FIFO. 136*746bab5bSAdrian Chadd * 137*746bab5bSAdrian Chadd * This should only be called as part of the chip reset path, as it 138*746bab5bSAdrian Chadd * assumes the FIFO is currently empty. 139*746bab5bSAdrian Chadd * 140*746bab5bSAdrian Chadd * TODO: verify that a cold/warm reset does clear the TX FIFO, so 141*746bab5bSAdrian Chadd * writing in a partially-filled FIFO will not cause double-entries 142*746bab5bSAdrian Chadd * to appear. 143*746bab5bSAdrian Chadd */ 144*746bab5bSAdrian Chadd static void 145*746bab5bSAdrian Chadd ath_edma_dma_restart(struct ath_softc *sc, struct ath_txq *txq) 146*746bab5bSAdrian Chadd { 147*746bab5bSAdrian Chadd 148*746bab5bSAdrian Chadd device_printf(sc->sc_dev, "%s: called: txq=%p, qnum=%d\n", 149*746bab5bSAdrian Chadd __func__, 150*746bab5bSAdrian Chadd txq, 151*746bab5bSAdrian Chadd txq->axq_qnum); 152*746bab5bSAdrian Chadd } 153*746bab5bSAdrian Chadd 154*746bab5bSAdrian Chadd /* 155*746bab5bSAdrian Chadd * Handoff this frame to the hardware. 156*746bab5bSAdrian Chadd * 157*746bab5bSAdrian Chadd * For the multicast queue, this will treat it as a software queue 158*746bab5bSAdrian Chadd * and append it to the list, after updating the MORE_DATA flag 159*746bab5bSAdrian Chadd * in the previous frame. The cabq processing code will ensure 160*746bab5bSAdrian Chadd * that the queue contents gets transferred over. 161*746bab5bSAdrian Chadd * 162*746bab5bSAdrian Chadd * For the hardware queues, this will queue a frame to the queue 163*746bab5bSAdrian Chadd * like before, then populate the FIFO from that. Since the 164*746bab5bSAdrian Chadd * EDMA hardware has 8 FIFO slots per TXQ, this ensures that 165*746bab5bSAdrian Chadd * frames such as management frames don't get prematurely dropped. 166*746bab5bSAdrian Chadd * 167*746bab5bSAdrian Chadd * This does imply that a similar flush-hwq-to-fifoq method will 168*746bab5bSAdrian Chadd * need to be called from the processq function, before the 169*746bab5bSAdrian Chadd * per-node software scheduler is called. 170*746bab5bSAdrian Chadd */ 171*746bab5bSAdrian Chadd static void 172*746bab5bSAdrian Chadd ath_edma_xmit_handoff(struct ath_softc *sc, struct ath_txq *txq, 173*746bab5bSAdrian Chadd struct ath_buf *bf) 174*746bab5bSAdrian Chadd { 175*746bab5bSAdrian Chadd 176*746bab5bSAdrian Chadd device_printf(sc->sc_dev, "%s: called; bf=%p, txq=%p, qnum=%d\n", 177*746bab5bSAdrian Chadd __func__, 178*746bab5bSAdrian Chadd bf, 179*746bab5bSAdrian Chadd txq, 180*746bab5bSAdrian Chadd txq->axq_qnum); 181*746bab5bSAdrian Chadd 182*746bab5bSAdrian Chadd /* 183*746bab5bSAdrian Chadd * XXX For now this is a placeholder; free the buffer 184*746bab5bSAdrian Chadd * and inform the stack that the TX failed. 185*746bab5bSAdrian Chadd */ 186*746bab5bSAdrian Chadd ath_tx_default_comp(sc, bf, 1); 187*746bab5bSAdrian Chadd } 188*746bab5bSAdrian Chadd 1893fdfc330SAdrian Chadd static int 19079607afeSAdrian Chadd ath_edma_setup_txfifo(struct ath_softc *sc, int qnum) 19179607afeSAdrian Chadd { 19279607afeSAdrian Chadd struct ath_tx_edma_fifo *te = &sc->sc_txedma[qnum]; 19379607afeSAdrian Chadd 19479607afeSAdrian Chadd te->m_fifo = malloc(sizeof(struct ath_buf *) * HAL_TXFIFO_DEPTH, 19579607afeSAdrian Chadd M_ATHDEV, 19679607afeSAdrian Chadd M_NOWAIT | M_ZERO); 19779607afeSAdrian Chadd if (te->m_fifo == NULL) { 19879607afeSAdrian Chadd device_printf(sc->sc_dev, "%s: malloc failed\n", 19979607afeSAdrian Chadd __func__); 20079607afeSAdrian Chadd return (-ENOMEM); 20179607afeSAdrian Chadd } 20279607afeSAdrian Chadd 20379607afeSAdrian Chadd /* 20479607afeSAdrian Chadd * Set initial "empty" state. 20579607afeSAdrian Chadd */ 20679607afeSAdrian Chadd te->m_fifo_head = te->m_fifo_tail = te->m_fifo_depth = 0; 20779607afeSAdrian Chadd 20879607afeSAdrian Chadd return (0); 20979607afeSAdrian Chadd } 21079607afeSAdrian Chadd 21179607afeSAdrian Chadd static int 21279607afeSAdrian Chadd ath_edma_free_txfifo(struct ath_softc *sc, int qnum) 21379607afeSAdrian Chadd { 21479607afeSAdrian Chadd struct ath_tx_edma_fifo *te = &sc->sc_txedma[qnum]; 21579607afeSAdrian Chadd 21679607afeSAdrian Chadd /* XXX TODO: actually deref the ath_buf entries? */ 21779607afeSAdrian Chadd free(te->m_fifo, M_ATHDEV); 21879607afeSAdrian Chadd return (0); 21979607afeSAdrian Chadd } 22079607afeSAdrian Chadd 22179607afeSAdrian Chadd static int 2223fdfc330SAdrian Chadd ath_edma_dma_txsetup(struct ath_softc *sc) 2233fdfc330SAdrian Chadd { 224ba3fd9d8SAdrian Chadd int error; 22579607afeSAdrian Chadd int i; 2263fdfc330SAdrian Chadd 227ba3fd9d8SAdrian Chadd error = ath_descdma_alloc_desc(sc, &sc->sc_txsdma, 228ba3fd9d8SAdrian Chadd NULL, "txcomp", sc->sc_tx_statuslen, ATH_TXSTATUS_RING_SIZE); 229ba3fd9d8SAdrian Chadd if (error != 0) 230ba3fd9d8SAdrian Chadd return (error); 231ba3fd9d8SAdrian Chadd 232ba3fd9d8SAdrian Chadd ath_hal_setuptxstatusring(sc->sc_ah, 233ba3fd9d8SAdrian Chadd (void *) sc->sc_txsdma.dd_desc, 234ba3fd9d8SAdrian Chadd sc->sc_txsdma.dd_desc_paddr, 235ba3fd9d8SAdrian Chadd ATH_TXSTATUS_RING_SIZE); 236ba3fd9d8SAdrian Chadd 23779607afeSAdrian Chadd for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 23879607afeSAdrian Chadd ath_edma_setup_txfifo(sc, i); 23979607afeSAdrian Chadd } 24079607afeSAdrian Chadd 241ba3fd9d8SAdrian Chadd 2423fdfc330SAdrian Chadd return (0); 2433fdfc330SAdrian Chadd } 2443fdfc330SAdrian Chadd 2453fdfc330SAdrian Chadd static int 2463fdfc330SAdrian Chadd ath_edma_dma_txteardown(struct ath_softc *sc) 2473fdfc330SAdrian Chadd { 24879607afeSAdrian Chadd int i; 24979607afeSAdrian Chadd 25079607afeSAdrian Chadd for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 25179607afeSAdrian Chadd ath_edma_free_txfifo(sc, i); 25279607afeSAdrian Chadd } 2533fdfc330SAdrian Chadd 254ba3fd9d8SAdrian Chadd ath_descdma_cleanup(sc, &sc->sc_txsdma, NULL); 2553fdfc330SAdrian Chadd return (0); 2563fdfc330SAdrian Chadd } 2573fdfc330SAdrian Chadd 2583fdfc330SAdrian Chadd void 2593fdfc330SAdrian Chadd ath_xmit_setup_edma(struct ath_softc *sc) 2603fdfc330SAdrian Chadd { 2613fdfc330SAdrian Chadd 2623fdfc330SAdrian Chadd /* Fetch EDMA field and buffer sizes */ 2633fdfc330SAdrian Chadd (void) ath_hal_gettxdesclen(sc->sc_ah, &sc->sc_tx_desclen); 2643fdfc330SAdrian Chadd (void) ath_hal_gettxstatuslen(sc->sc_ah, &sc->sc_tx_statuslen); 2653fdfc330SAdrian Chadd (void) ath_hal_getntxmaps(sc->sc_ah, &sc->sc_tx_nmaps); 2663fdfc330SAdrian Chadd 2673fdfc330SAdrian Chadd device_printf(sc->sc_dev, "TX descriptor length: %d\n", 2683fdfc330SAdrian Chadd sc->sc_tx_desclen); 2693fdfc330SAdrian Chadd device_printf(sc->sc_dev, "TX status length: %d\n", 2703fdfc330SAdrian Chadd sc->sc_tx_statuslen); 2713fdfc330SAdrian Chadd device_printf(sc->sc_dev, "TX buffers per descriptor: %d\n", 2723fdfc330SAdrian Chadd sc->sc_tx_nmaps); 2733fdfc330SAdrian Chadd 2743fdfc330SAdrian Chadd sc->sc_tx.xmit_setup = ath_edma_dma_txsetup; 2753fdfc330SAdrian Chadd sc->sc_tx.xmit_teardown = ath_edma_dma_txteardown; 276*746bab5bSAdrian Chadd 277*746bab5bSAdrian Chadd sc->sc_tx.xmit_dma_restart = ath_edma_dma_restart; 278*746bab5bSAdrian Chadd sc->sc_tx.xmit_handoff = ath_edma_xmit_handoff; 2793fdfc330SAdrian Chadd } 280