diff options
author | adrian <adrian@FreeBSD.org> | 2011-06-01 20:09:49 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2011-06-01 20:09:49 +0000 |
commit | fa6dbdd4a2c067d514a8442f406a37ad52fb9be7 (patch) | |
tree | 942b1aedba63c78ee502d3d0b69c23bd4e06495c /sys | |
parent | 772a896ba2a009541fa253fca8537347b58945e7 (diff) | |
download | FreeBSD-src-fa6dbdd4a2c067d514a8442f406a37ad52fb9be7.zip FreeBSD-src-fa6dbdd4a2c067d514a8442f406a37ad52fb9be7.tar.gz |
Flesh out the radar detection related operations for the ath driver.
This is in no way a complete DFS/radar detection implementation!
It merely creates an abstracted interface which allows for future
development of the DFS radar detection code.
Note: Net80211 already handles the bulk of the DFS machinery,
all we need to do here is figure out that a radar event has occured
and inform it as such. It then drives the DFS state engine for us.
The "null" DFS radar detection module is included by default;
it doesn't require a device line.
This commit:
* Adds a simple abstracted layer for radar detection state -
sys/dev/ath/ath_dfs/;
* Implements a null DFS module which doesn't do anything;
(ie, implements the exact behaviour at the moment);
* Adds hooks to the ath driver to process received radar events
and gives the DFS module a chance to determine whether
a radar has been detected.
Obtained from: Atheros
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/files | 5 | ||||
-rw-r--r-- | sys/dev/ath/ath_dfs/null/dfs_null.c | 160 | ||||
-rw-r--r-- | sys/dev/ath/if_ath.c | 51 | ||||
-rw-r--r-- | sys/dev/ath/if_athdfs.h | 47 | ||||
-rw-r--r-- | sys/dev/ath/if_athvar.h | 15 | ||||
-rw-r--r-- | sys/modules/ath/Makefile | 4 |
6 files changed, 281 insertions, 1 deletions
diff --git a/sys/conf/files b/sys/conf/files index d75a2b8..0f5c512 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -846,7 +846,10 @@ dev/ath/ath_rate/onoe/onoe.c optional ath_rate_onoe \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_rate/sample/sample.c optional ath_rate_sample \ compile-with "${NORMAL_C} -I$S/dev/ath" -# +# ath DFS modules +dev/ath/ath_dfs/null/dfs_null.c optional ath \ + compile-with "${NORMAL_C} -I$S/dev/ath" +# dev/bce/if_bce.c optional bce dev/bfe/if_bfe.c optional bfe dev/bge/if_bge.c optional bge diff --git a/sys/dev/ath/ath_dfs/null/dfs_null.c b/sys/dev/ath/ath_dfs/null/dfs_null.c new file mode 100644 index 0000000..781e93d --- /dev/null +++ b/sys/dev/ath/ath_dfs/null/dfs_null.c @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * This implements an empty DFS module. + */ +#include "opt_inet.h" +#include "opt_wlan.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/errno.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> + +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> +#include <net/if_arp.h> +#include <net/ethernet.h> /* XXX for ether_sprintf */ + +#include <net80211/ieee80211_var.h> + +#include <net/bpf.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/if_ether.h> +#endif + +#include <dev/ath/if_athvar.h> +#include <dev/ath/if_athdfs.h> + +#include <dev/ath/ath_hal/ah_desc.h> + +/* + * Methods which are required + */ + +/* + * Attach DFS to the given interface + */ +int +ath_dfs_attach(struct ath_softc *sc) +{ + return 1; +} + +/* + * Detach DFS from the given interface + */ +int +ath_dfs_detach(struct ath_softc *sc) +{ + return 1; +} + +/* + * Enable radar check + */ +void +ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan) +{ + /* Check if the current channel is radar-enabled */ + if (! IEEE80211_IS_CHAN_DFS(chan)) + return; +} + +/* + * Process DFS related PHY errors + */ +void +ath_dfs_process_phy_err(struct ath_softc *sc, struct ath_desc *ds, + uint64_t tsf, struct ath_rx_status *rxstat) +{ + +} + +/* + * Process the radar events and determine whether a DFS event has occured. + * + * This is designed to run outside of the RX processing path. + * The RX path will call ath_dfs_tasklet_needed() to see whether + * the task/callback running this routine needs to be called. + */ +int +ath_dfs_process_radar_event(struct ath_softc *sc, + struct ieee80211_channel *chan) +{ + return 0; +} + +/* + * Determine whether the the DFS check task needs to be queued. + * + * This is called in the RX task when the current batch of packets + * have been received. It will return whether there are any radar + * events for ath_dfs_process_radar_event() to handle. + */ +int +ath_dfs_tasklet_needed(struct ath_softc *sc, struct ieee80211_channel *chan) +{ + return 0; +} + +/* + * Handle ioctl requests from the diagnostic interface + */ +int +ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad) +{ + return 1; +} + +/* + * Get the current DFS thresholds from the HAL + */ +int +ath_dfs_get_thresholds(struct ath_softc *sc, HAL_PHYERR_PARAM *param) +{ + ath_hal_getdfsthresh(sc->sc_ah, param); + return 1; +} diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 29e7186..45bd9ed 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -95,11 +95,13 @@ __FBSDID("$FreeBSD$"); #include <dev/ath/if_ath_tx.h> #include <dev/ath/if_ath_sysctl.h> #include <dev/ath/if_ath_keycache.h> +#include <dev/ath/if_athdfs.h> #ifdef ATH_TX99_DIAG #include <dev/ath/ath_tx99/ath_tx99.h> #endif + /* * ATH_BCBUF determines the number of vap's that can transmit * beacons and also (currently) the number of vap's that can @@ -199,6 +201,8 @@ static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode); static void ath_announce(struct ath_softc *); +static void ath_dfs_tasklet(void *, int); + #ifdef IEEE80211_SUPPORT_TDMA static void ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval); @@ -471,6 +475,16 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) goto bad2; } + /* Attach DFS module */ + if (! ath_dfs_attach(sc)) { + device_printf(sc->sc_dev, "%s: unable to attach DFS\n", __func__); + error = EIO; + goto bad2; + } + + /* Start DFS processing tasklet */ + TASK_INIT(&sc->sc_dfstask, 0, ath_dfs_tasklet, sc); + sc->sc_blinking = 0; sc->sc_ledstate = 1; sc->sc_ledon = 0; /* low true */ @@ -771,6 +785,8 @@ ath_detach(struct ath_softc *sc) sc->sc_tx99->detach(sc->sc_tx99); #endif ath_rate_detach(sc->sc_rc); + + ath_dfs_detach(sc); ath_desc_free(sc); ath_tx_cleanup(sc); ath_hal_detach(sc->sc_ah); /* NB: sets chip in full sleep */ @@ -1554,6 +1570,9 @@ ath_init(void *arg) } ath_chan_change(sc, ic->ic_curchan); + /* Let DFS at it in case it's a DFS channel */ + ath_dfs_radar_enable(sc, ic->ic_curchan); + /* * Likewise this is set during reset so update * state cached in the driver. @@ -1699,6 +1718,10 @@ ath_reset(struct ifnet *ifp) if_printf(ifp, "%s: unable to reset hardware; hal status %u\n", __func__, status); sc->sc_diversity = ath_hal_getdiversity(ah); + + /* Let DFS at it in case it's a DFS channel */ + ath_dfs_radar_enable(sc, ic->ic_curchan); + if (ath_startrecv(sc) != 0) /* restart recv */ if_printf(ifp, "%s: unable to start recv logic\n", __func__); /* @@ -3441,6 +3464,9 @@ ath_rx_proc(void *arg, int npending) sc->sc_stats.ast_rx_fifoerr++; if (rs->rs_status & HAL_RXERR_PHY) { sc->sc_stats.ast_rx_phyerr++; + /* Process DFS radar events */ + ath_dfs_process_phy_err(sc, ds, tsf, rs); + /* Be suitably paranoid about receiving phy errors out of the stats array bounds */ if (rs->rs_phyerr < 64) sc->sc_stats.ast_rx_phy[rs->rs_phyerr]++; @@ -3682,6 +3708,10 @@ rx_next: if (ngood) sc->sc_lastrx = tsf; + /* Queue DFS tasklet if needed */ + if (ath_dfs_tasklet_needed(sc, sc->sc_curchan)) + taskqueue_enqueue(sc->sc_tq, &sc->sc_dfstask); + if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) { #ifdef IEEE80211_SUPPORT_SUPERG ieee80211_ff_age_all(ic, 100); @@ -4399,6 +4429,9 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) } sc->sc_diversity = ath_hal_getdiversity(ah); + /* Let DFS at it in case it's a DFS channel */ + ath_dfs_radar_enable(sc, ic->ic_curchan); + /* * Re-enable rx framework. */ @@ -5665,5 +5698,23 @@ ath_tdma_beacon_send(struct ath_softc *sc, struct ieee80211vap *vap) } #endif /* IEEE80211_SUPPORT_TDMA */ +static void +ath_dfs_tasklet(void *p, int npending) +{ + struct ath_softc *sc = (struct ath_softc *) p; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + + /* + * If previous processing has found a radar event, + * signal this to the net80211 layer to begin DFS + * processing. + */ + if (ath_dfs_process_radar_event(sc, sc->sc_curchan)) { + /* DFS event found, initiate channel change */ + ieee80211_dfs_notify_radar(ic, sc->sc_curchan); + } +} + MODULE_VERSION(if_ath, 1); MODULE_DEPEND(if_ath, wlan, 1, 1, 1); /* 802.11 media layer */ diff --git a/sys/dev/ath/if_athdfs.h b/sys/dev/ath/if_athdfs.h new file mode 100644 index 0000000..057e926 --- /dev/null +++ b/sys/dev/ath/if_athdfs.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#ifndef __IF_ATHDFS_H__ +#define __IF_ATHDFS_H__ + +extern int ath_dfs_attach(struct ath_softc *sc); +extern int ath_dfs_detach(struct ath_softc *sc); +extern void ath_dfs_radar_enable(struct ath_softc *, + struct ieee80211_channel *chan); +extern void ath_dfs_process_phy_err(struct ath_softc *sc, struct ath_desc *ds, + uint64_t tsf, struct ath_rx_status *rxstat); +extern int ath_dfs_process_radar_event(struct ath_softc *sc, + struct ieee80211_channel *chan); +extern int ath_dfs_tasklet_needed(struct ath_softc *sc, + struct ieee80211_channel *chan); +extern int ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad); +extern int ath_dfs_get_thresholds(struct ath_softc *sc, HAL_PHYERR_PARAM *param); + +#endif /* __IF_ATHDFS_H__ */ diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 6353847..786494e 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -357,6 +357,10 @@ struct ath_softc { uint16_t *sc_eepromdata; /* Local eeprom data, if AR9100 */ int sc_txchainmask; /* currently configured TX chainmask */ int sc_rxchainmask; /* currently configured RX chainmask */ + + /* DFS related state */ + void *sc_dfs; /* Used by an optional DFS module */ + struct task sc_dfstask; /* DFS processing task */ }; #define ATH_LOCK_INIT(_sc) \ @@ -694,6 +698,17 @@ void ath_intr(void *); #define ath_hal_set11nburstduration(_ah, _ds, _dur) \ ((*(_ah)->ah_set11nBurstDuration)((_ah), (_ds), (_dur))) +/* + * This is badly-named; you need to set the correct parameters + * to begin to receive useful radar events; and even then + * it doesn't "enable" DFS. See the ath_dfs/null/ module for + * more information. + */ +#define ath_hal_enabledfs(_ah, _param) \ + ((*(_ah)->ah_enableDfs)((_ah), (_param))) +#define ath_hal_getdfsthresh(_ah, _param) \ + ((*(_ah)->ah_getDfsThresh)((_ah), (_param))) + #define ath_hal_gpioCfgOutput(_ah, _gpio, _type) \ ((*(_ah)->ah_gpioCfgOutput)((_ah), (_gpio), (_type))) #define ath_hal_gpioset(_ah, _gpio, _b) \ diff --git a/sys/modules/ath/Makefile b/sys/modules/ath/Makefile index 6b093a9..49f7fa6 100644 --- a/sys/modules/ath/Makefile +++ b/sys/modules/ath/Makefile @@ -134,6 +134,10 @@ SRCS+= onoe.c SRCS+= amrr.c .endif +# DFS +.PATH: ${.CURDIR}/../../dev/ath/ath_dfs/null +SRCS+= dfs_null.c + CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal opt_ah.h: |