148237774SAdrian Chadd /*- 248237774SAdrian Chadd * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd 348237774SAdrian Chadd * All rights reserved. 448237774SAdrian Chadd * 548237774SAdrian Chadd * Redistribution and use in source and binary forms, with or without 648237774SAdrian Chadd * modification, are permitted provided that the following conditions 748237774SAdrian Chadd * are met: 848237774SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 948237774SAdrian Chadd * notice, this list of conditions and the following disclaimer, 1048237774SAdrian Chadd * without modification. 1148237774SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1248237774SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 1348237774SAdrian Chadd * redistribution must be conditioned upon including a substantially 1448237774SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 1548237774SAdrian Chadd * 1648237774SAdrian Chadd * NO WARRANTY 1748237774SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1848237774SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1948237774SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 2048237774SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 2148237774SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 2248237774SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2348237774SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2448237774SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 2548237774SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2648237774SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 2748237774SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 2848237774SAdrian Chadd * 2948237774SAdrian Chadd * $FreeBSD$ 3048237774SAdrian Chadd */ 3148237774SAdrian Chadd #include <sys/cdefs.h> 3248237774SAdrian Chadd __FBSDID("$FreeBSD$"); 3348237774SAdrian Chadd 3448237774SAdrian Chadd /* 3548237774SAdrian Chadd * This implements an empty DFS module. 3648237774SAdrian Chadd */ 3748237774SAdrian Chadd #include "opt_inet.h" 3848237774SAdrian Chadd #include "opt_wlan.h" 3948237774SAdrian Chadd 4048237774SAdrian Chadd #include <sys/param.h> 4148237774SAdrian Chadd #include <sys/systm.h> 4248237774SAdrian Chadd #include <sys/sysctl.h> 4348237774SAdrian Chadd #include <sys/kernel.h> 4448237774SAdrian Chadd #include <sys/lock.h> 4548237774SAdrian Chadd #include <sys/mutex.h> 4648237774SAdrian Chadd #include <sys/errno.h> 4748237774SAdrian Chadd 4848237774SAdrian Chadd #include <machine/bus.h> 4948237774SAdrian Chadd #include <machine/resource.h> 5048237774SAdrian Chadd #include <sys/bus.h> 5148237774SAdrian Chadd 5248237774SAdrian Chadd #include <sys/socket.h> 5348237774SAdrian Chadd 5448237774SAdrian Chadd #include <net/if.h> 5548237774SAdrian Chadd #include <net/if_media.h> 5648237774SAdrian Chadd #include <net/if_arp.h> 5748237774SAdrian Chadd #include <net/ethernet.h> /* XXX for ether_sprintf */ 5848237774SAdrian Chadd 5948237774SAdrian Chadd #include <net80211/ieee80211_var.h> 6048237774SAdrian Chadd 6148237774SAdrian Chadd #include <net/bpf.h> 6248237774SAdrian Chadd 6348237774SAdrian Chadd #ifdef INET 6448237774SAdrian Chadd #include <netinet/in.h> 6548237774SAdrian Chadd #include <netinet/if_ether.h> 6648237774SAdrian Chadd #endif 6748237774SAdrian Chadd 6848237774SAdrian Chadd #include <dev/ath/if_athvar.h> 6948237774SAdrian Chadd #include <dev/ath/if_athdfs.h> 7048237774SAdrian Chadd 7148237774SAdrian Chadd #include <dev/ath/ath_hal/ah_desc.h> 7248237774SAdrian Chadd 7348237774SAdrian Chadd /* 74ab434358SAdrian Chadd * These are default parameters for the AR5416 and 75ab434358SAdrian Chadd * later 802.11n NICs. They simply enable some 76ab434358SAdrian Chadd * radar pulse event generation. 77ab434358SAdrian Chadd * 78ab434358SAdrian Chadd * These are very likely not valid for the AR5212 era 79ab434358SAdrian Chadd * NICs. 80ab434358SAdrian Chadd * 81ab434358SAdrian Chadd * Since these define signal sizing and threshold 82ab434358SAdrian Chadd * parameters, they may need changing based on the 83ab434358SAdrian Chadd * specific antenna and receive amplifier 84ab434358SAdrian Chadd * configuration. 85ab434358SAdrian Chadd */ 86ab434358SAdrian Chadd #define AR5416_DFS_FIRPWR -33 87ab434358SAdrian Chadd #define AR5416_DFS_RRSSI 20 88ab434358SAdrian Chadd #define AR5416_DFS_HEIGHT 10 89ab434358SAdrian Chadd #define AR5416_DFS_PRSSI 15 90ab434358SAdrian Chadd #define AR5416_DFS_INBAND 15 91ab434358SAdrian Chadd #define AR5416_DFS_RELPWR 8 92ab434358SAdrian Chadd #define AR5416_DFS_RELSTEP 12 93ab434358SAdrian Chadd #define AR5416_DFS_MAXLEN 255 94ab434358SAdrian Chadd 95ab434358SAdrian Chadd /* 9648237774SAdrian Chadd * Methods which are required 9748237774SAdrian Chadd */ 9848237774SAdrian Chadd 9948237774SAdrian Chadd /* 10048237774SAdrian Chadd * Attach DFS to the given interface 10148237774SAdrian Chadd */ 10248237774SAdrian Chadd int 10348237774SAdrian Chadd ath_dfs_attach(struct ath_softc *sc) 10448237774SAdrian Chadd { 10548237774SAdrian Chadd return 1; 10648237774SAdrian Chadd } 10748237774SAdrian Chadd 10848237774SAdrian Chadd /* 10948237774SAdrian Chadd * Detach DFS from the given interface 11048237774SAdrian Chadd */ 11148237774SAdrian Chadd int 11248237774SAdrian Chadd ath_dfs_detach(struct ath_softc *sc) 11348237774SAdrian Chadd { 11448237774SAdrian Chadd return 1; 11548237774SAdrian Chadd } 11648237774SAdrian Chadd 11748237774SAdrian Chadd /* 11848237774SAdrian Chadd * Enable radar check 11948237774SAdrian Chadd */ 120bfa5e927SAdrian Chadd int 12148237774SAdrian Chadd ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan) 12248237774SAdrian Chadd { 123ab434358SAdrian Chadd #if 0 124ab434358SAdrian Chadd HAL_PHYERR_PARAM pe; 125ab434358SAdrian Chadd 12648237774SAdrian Chadd /* Check if the current channel is radar-enabled */ 12748237774SAdrian Chadd if (! IEEE80211_IS_CHAN_DFS(chan)) 128bfa5e927SAdrian Chadd return (0); 129bfa5e927SAdrian Chadd 130ab434358SAdrian Chadd /* Enable radar PHY error reporting */ 131ab434358SAdrian Chadd sc->sc_dodfs = 1; 132ab434358SAdrian Chadd 133bfa5e927SAdrian Chadd /* 134ab434358SAdrian Chadd * These are general examples of the parameter values 135ab434358SAdrian Chadd * to use when configuring radar pulse detection for 136ab434358SAdrian Chadd * the AR5416, AR91xx, AR92xx NICs. They are only 137ab434358SAdrian Chadd * for testing and do require tuning depending upon the 138ab434358SAdrian Chadd * hardware and deployment specifics. 139bfa5e927SAdrian Chadd */ 140ab434358SAdrian Chadd pe.pe_firpwr = AR5416_DFS_FIRPWR; 141ab434358SAdrian Chadd pe.pe_rrssi = AR5416_DFS_RRSSI; 142ab434358SAdrian Chadd pe.pe_height = AR5416_DFS_HEIGHT; 143ab434358SAdrian Chadd pe.pe_prssi = AR5416_DFS_PRSSI; 144ab434358SAdrian Chadd pe.pe_inband = AR5416_DFS_INBAND; 145ab434358SAdrian Chadd pe.pe_relpwr = AR5416_DFS_RELPWR; 146ab434358SAdrian Chadd pe.pe_relstep = AR5416_DFS_RELSTEP; 147ab434358SAdrian Chadd pe.pe_maxlen = AR5416_DFS_MAXLEN; 148ab434358SAdrian Chadd pe.pe_enabled = 1; 149ab434358SAdrian Chadd 150ab434358SAdrian Chadd /* Flip on extension channel events only if doing HT40 */ 151ab434358SAdrian Chadd if (IEEE80211_IS_CHAN_HT40(chan)) 152ab434358SAdrian Chadd pe.pe_extchannel = 1; 153ab434358SAdrian Chadd else 154ab434358SAdrian Chadd pe.pe_extchannel = 0; 155ab434358SAdrian Chadd 156ab434358SAdrian Chadd ath_hal_enabledfs(sc->sc_ah, &pe); 157bfa5e927SAdrian Chadd 158bfa5e927SAdrian Chadd return (1); 159ab434358SAdrian Chadd #else 160ab434358SAdrian Chadd return (0); 161ab434358SAdrian Chadd #endif 16248237774SAdrian Chadd } 16348237774SAdrian Chadd 16448237774SAdrian Chadd /* 16548237774SAdrian Chadd * Process DFS related PHY errors 16648237774SAdrian Chadd */ 16748237774SAdrian Chadd void 1686025dd9fSAdrian Chadd ath_dfs_process_phy_err(struct ath_softc *sc, const char *buf, 16948237774SAdrian Chadd uint64_t tsf, struct ath_rx_status *rxstat) 17048237774SAdrian Chadd { 17148237774SAdrian Chadd 17248237774SAdrian Chadd } 17348237774SAdrian Chadd 17448237774SAdrian Chadd /* 17548237774SAdrian Chadd * Process the radar events and determine whether a DFS event has occured. 17648237774SAdrian Chadd * 17748237774SAdrian Chadd * This is designed to run outside of the RX processing path. 17848237774SAdrian Chadd * The RX path will call ath_dfs_tasklet_needed() to see whether 17948237774SAdrian Chadd * the task/callback running this routine needs to be called. 18048237774SAdrian Chadd */ 18148237774SAdrian Chadd int 18248237774SAdrian Chadd ath_dfs_process_radar_event(struct ath_softc *sc, 18348237774SAdrian Chadd struct ieee80211_channel *chan) 18448237774SAdrian Chadd { 18548237774SAdrian Chadd return 0; 18648237774SAdrian Chadd } 18748237774SAdrian Chadd 18848237774SAdrian Chadd /* 18936daf049SEitan Adler * Determine whether the DFS check task needs to be queued. 19048237774SAdrian Chadd * 19148237774SAdrian Chadd * This is called in the RX task when the current batch of packets 19248237774SAdrian Chadd * have been received. It will return whether there are any radar 19348237774SAdrian Chadd * events for ath_dfs_process_radar_event() to handle. 19448237774SAdrian Chadd */ 19548237774SAdrian Chadd int 19648237774SAdrian Chadd ath_dfs_tasklet_needed(struct ath_softc *sc, struct ieee80211_channel *chan) 19748237774SAdrian Chadd { 19848237774SAdrian Chadd return 0; 19948237774SAdrian Chadd } 20048237774SAdrian Chadd 20148237774SAdrian Chadd /* 202c5f2a23cSAdrian Chadd * Handle ioctl requests from the diagnostic interface. 203c5f2a23cSAdrian Chadd * 204c5f2a23cSAdrian Chadd * The initial part of this code resembles ath_ioctl_diag(); 205c5f2a23cSAdrian Chadd * it's likely a good idea to reduce duplication between 206c5f2a23cSAdrian Chadd * these two routines. 20748237774SAdrian Chadd */ 20848237774SAdrian Chadd int 20948237774SAdrian Chadd ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad) 21048237774SAdrian Chadd { 211c5f2a23cSAdrian Chadd unsigned int id = ad->ad_id & ATH_DIAG_ID; 212c5f2a23cSAdrian Chadd void *indata = NULL; 213c5f2a23cSAdrian Chadd void *outdata = NULL; 214c5f2a23cSAdrian Chadd u_int32_t insize = ad->ad_in_size; 215c5f2a23cSAdrian Chadd u_int32_t outsize = ad->ad_out_size; 216c5f2a23cSAdrian Chadd int error = 0; 217c5f2a23cSAdrian Chadd HAL_PHYERR_PARAM peout; 218c5f2a23cSAdrian Chadd HAL_PHYERR_PARAM *pe; 219c5f2a23cSAdrian Chadd 220c5f2a23cSAdrian Chadd if (ad->ad_id & ATH_DIAG_IN) { 221c5f2a23cSAdrian Chadd /* 222c5f2a23cSAdrian Chadd * Copy in data. 223c5f2a23cSAdrian Chadd */ 224c5f2a23cSAdrian Chadd indata = malloc(insize, M_TEMP, M_NOWAIT); 225c5f2a23cSAdrian Chadd if (indata == NULL) { 226c5f2a23cSAdrian Chadd error = ENOMEM; 227c5f2a23cSAdrian Chadd goto bad; 228c5f2a23cSAdrian Chadd } 229c5f2a23cSAdrian Chadd error = copyin(ad->ad_in_data, indata, insize); 230c5f2a23cSAdrian Chadd if (error) 231c5f2a23cSAdrian Chadd goto bad; 232c5f2a23cSAdrian Chadd } 233c5f2a23cSAdrian Chadd if (ad->ad_id & ATH_DIAG_DYN) { 234c5f2a23cSAdrian Chadd /* 235c5f2a23cSAdrian Chadd * Allocate a buffer for the results (otherwise the HAL 236c5f2a23cSAdrian Chadd * returns a pointer to a buffer where we can read the 237c5f2a23cSAdrian Chadd * results). Note that we depend on the HAL leaving this 238c5f2a23cSAdrian Chadd * pointer for us to use below in reclaiming the buffer; 239c5f2a23cSAdrian Chadd * may want to be more defensive. 240c5f2a23cSAdrian Chadd */ 241c5f2a23cSAdrian Chadd outdata = malloc(outsize, M_TEMP, M_NOWAIT); 242c5f2a23cSAdrian Chadd if (outdata == NULL) { 243c5f2a23cSAdrian Chadd error = ENOMEM; 244c5f2a23cSAdrian Chadd goto bad; 245c5f2a23cSAdrian Chadd } 246c5f2a23cSAdrian Chadd } 247c5f2a23cSAdrian Chadd switch (id) { 248c5f2a23cSAdrian Chadd case DFS_SET_THRESH: 249c5f2a23cSAdrian Chadd if (insize < sizeof(HAL_PHYERR_PARAM)) { 25099271119SAdrian Chadd error = EINVAL; 251c5f2a23cSAdrian Chadd break; 252c5f2a23cSAdrian Chadd } 253c5f2a23cSAdrian Chadd pe = (HAL_PHYERR_PARAM *) indata; 254c5f2a23cSAdrian Chadd ath_hal_enabledfs(sc->sc_ah, pe); 255c5f2a23cSAdrian Chadd break; 256c5f2a23cSAdrian Chadd case DFS_GET_THRESH: 257c5f2a23cSAdrian Chadd memset(&peout, 0, sizeof(peout)); 258c5f2a23cSAdrian Chadd outsize = sizeof(HAL_PHYERR_PARAM); 259c5f2a23cSAdrian Chadd ath_hal_getdfsthresh(sc->sc_ah, &peout); 260c5f2a23cSAdrian Chadd pe = (HAL_PHYERR_PARAM *) outdata; 261c5f2a23cSAdrian Chadd memcpy(pe, &peout, sizeof(*pe)); 262c5f2a23cSAdrian Chadd break; 263c5f2a23cSAdrian Chadd default: 26499271119SAdrian Chadd error = EINVAL; 265c5f2a23cSAdrian Chadd } 266c5f2a23cSAdrian Chadd if (outsize < ad->ad_out_size) 267c5f2a23cSAdrian Chadd ad->ad_out_size = outsize; 268c5f2a23cSAdrian Chadd if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) 26999271119SAdrian Chadd error = EFAULT; 270c5f2a23cSAdrian Chadd bad: 271c5f2a23cSAdrian Chadd if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) 272c5f2a23cSAdrian Chadd free(indata, M_TEMP); 273c5f2a23cSAdrian Chadd if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) 274c5f2a23cSAdrian Chadd free(outdata, M_TEMP); 275c5f2a23cSAdrian Chadd return error; 27648237774SAdrian Chadd } 27748237774SAdrian Chadd 27848237774SAdrian Chadd /* 27948237774SAdrian Chadd * Get the current DFS thresholds from the HAL 28048237774SAdrian Chadd */ 28148237774SAdrian Chadd int 28248237774SAdrian Chadd ath_dfs_get_thresholds(struct ath_softc *sc, HAL_PHYERR_PARAM *param) 28348237774SAdrian Chadd { 28448237774SAdrian Chadd ath_hal_getdfsthresh(sc->sc_ah, param); 28548237774SAdrian Chadd return 1; 28648237774SAdrian Chadd } 287