diff options
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r-- | sys/dev/ath/if_ath.c | 51 |
1 files changed, 51 insertions, 0 deletions
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 */ |