summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/if_ath.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r--sys/dev/ath/if_ath.c51
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 */
OpenPOWER on IntegriCloud