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 1333fdfc330SAdrian Chadd static int 134*79607afeSAdrian Chadd ath_edma_setup_txfifo(struct ath_softc *sc, int qnum) 135*79607afeSAdrian Chadd { 136*79607afeSAdrian Chadd struct ath_tx_edma_fifo *te = &sc->sc_txedma[qnum]; 137*79607afeSAdrian Chadd 138*79607afeSAdrian Chadd te->m_fifo = malloc(sizeof(struct ath_buf *) * HAL_TXFIFO_DEPTH, 139*79607afeSAdrian Chadd M_ATHDEV, 140*79607afeSAdrian Chadd M_NOWAIT | M_ZERO); 141*79607afeSAdrian Chadd if (te->m_fifo == NULL) { 142*79607afeSAdrian Chadd device_printf(sc->sc_dev, "%s: malloc failed\n", 143*79607afeSAdrian Chadd __func__); 144*79607afeSAdrian Chadd return (-ENOMEM); 145*79607afeSAdrian Chadd } 146*79607afeSAdrian Chadd 147*79607afeSAdrian Chadd /* 148*79607afeSAdrian Chadd * Set initial "empty" state. 149*79607afeSAdrian Chadd */ 150*79607afeSAdrian Chadd te->m_fifo_head = te->m_fifo_tail = te->m_fifo_depth = 0; 151*79607afeSAdrian Chadd 152*79607afeSAdrian Chadd return (0); 153*79607afeSAdrian Chadd } 154*79607afeSAdrian Chadd 155*79607afeSAdrian Chadd static int 156*79607afeSAdrian Chadd ath_edma_free_txfifo(struct ath_softc *sc, int qnum) 157*79607afeSAdrian Chadd { 158*79607afeSAdrian Chadd struct ath_tx_edma_fifo *te = &sc->sc_txedma[qnum]; 159*79607afeSAdrian Chadd 160*79607afeSAdrian Chadd /* XXX TODO: actually deref the ath_buf entries? */ 161*79607afeSAdrian Chadd free(te->m_fifo, M_ATHDEV); 162*79607afeSAdrian Chadd return (0); 163*79607afeSAdrian Chadd } 164*79607afeSAdrian Chadd 165*79607afeSAdrian Chadd static int 1663fdfc330SAdrian Chadd ath_edma_dma_txsetup(struct ath_softc *sc) 1673fdfc330SAdrian Chadd { 168ba3fd9d8SAdrian Chadd int error; 169*79607afeSAdrian Chadd int i; 1703fdfc330SAdrian Chadd 171ba3fd9d8SAdrian Chadd error = ath_descdma_alloc_desc(sc, &sc->sc_txsdma, 172ba3fd9d8SAdrian Chadd NULL, "txcomp", sc->sc_tx_statuslen, ATH_TXSTATUS_RING_SIZE); 173ba3fd9d8SAdrian Chadd if (error != 0) 174ba3fd9d8SAdrian Chadd return (error); 175ba3fd9d8SAdrian Chadd 176ba3fd9d8SAdrian Chadd ath_hal_setuptxstatusring(sc->sc_ah, 177ba3fd9d8SAdrian Chadd (void *) sc->sc_txsdma.dd_desc, 178ba3fd9d8SAdrian Chadd sc->sc_txsdma.dd_desc_paddr, 179ba3fd9d8SAdrian Chadd ATH_TXSTATUS_RING_SIZE); 180ba3fd9d8SAdrian Chadd 181*79607afeSAdrian Chadd for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 182*79607afeSAdrian Chadd ath_edma_setup_txfifo(sc, i); 183*79607afeSAdrian Chadd } 184*79607afeSAdrian Chadd 185ba3fd9d8SAdrian Chadd 1863fdfc330SAdrian Chadd return (0); 1873fdfc330SAdrian Chadd } 1883fdfc330SAdrian Chadd 1893fdfc330SAdrian Chadd static int 1903fdfc330SAdrian Chadd ath_edma_dma_txteardown(struct ath_softc *sc) 1913fdfc330SAdrian Chadd { 192*79607afeSAdrian Chadd int i; 193*79607afeSAdrian Chadd 194*79607afeSAdrian Chadd for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { 195*79607afeSAdrian Chadd ath_edma_free_txfifo(sc, i); 196*79607afeSAdrian Chadd } 1973fdfc330SAdrian Chadd 198ba3fd9d8SAdrian Chadd ath_descdma_cleanup(sc, &sc->sc_txsdma, NULL); 1993fdfc330SAdrian Chadd return (0); 2003fdfc330SAdrian Chadd } 2013fdfc330SAdrian Chadd 2023fdfc330SAdrian Chadd void 2033fdfc330SAdrian Chadd ath_xmit_setup_edma(struct ath_softc *sc) 2043fdfc330SAdrian Chadd { 2053fdfc330SAdrian Chadd 2063fdfc330SAdrian Chadd /* Fetch EDMA field and buffer sizes */ 2073fdfc330SAdrian Chadd (void) ath_hal_gettxdesclen(sc->sc_ah, &sc->sc_tx_desclen); 2083fdfc330SAdrian Chadd (void) ath_hal_gettxstatuslen(sc->sc_ah, &sc->sc_tx_statuslen); 2093fdfc330SAdrian Chadd (void) ath_hal_getntxmaps(sc->sc_ah, &sc->sc_tx_nmaps); 2103fdfc330SAdrian Chadd 2113fdfc330SAdrian Chadd device_printf(sc->sc_dev, "TX descriptor length: %d\n", 2123fdfc330SAdrian Chadd sc->sc_tx_desclen); 2133fdfc330SAdrian Chadd device_printf(sc->sc_dev, "TX status length: %d\n", 2143fdfc330SAdrian Chadd sc->sc_tx_statuslen); 2153fdfc330SAdrian Chadd device_printf(sc->sc_dev, "TX buffers per descriptor: %d\n", 2163fdfc330SAdrian Chadd sc->sc_tx_nmaps); 2173fdfc330SAdrian Chadd 2183fdfc330SAdrian Chadd sc->sc_tx.xmit_setup = ath_edma_dma_txsetup; 2193fdfc330SAdrian Chadd sc->sc_tx.xmit_teardown = ath_edma_dma_txteardown; 2203fdfc330SAdrian Chadd } 221