xref: /freebsd/sys/dev/rtwn/rtl8821a/usb/r21au_dfs.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1*b8ad00b0SAndriy Voskoboinyk /*-
2*b8ad00b0SAndriy Voskoboinyk  * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
3*b8ad00b0SAndriy Voskoboinyk  * All rights reserved.
4*b8ad00b0SAndriy Voskoboinyk  *
5*b8ad00b0SAndriy Voskoboinyk  * Redistribution and use in source and binary forms, with or without
6*b8ad00b0SAndriy Voskoboinyk  * modification, are permitted provided that the following conditions
7*b8ad00b0SAndriy Voskoboinyk  * are met:
8*b8ad00b0SAndriy Voskoboinyk  * 1. Redistributions of source code must retain the above copyright
9*b8ad00b0SAndriy Voskoboinyk  *    notice, this list of conditions and the following disclaimer.
10*b8ad00b0SAndriy Voskoboinyk  * 2. Redistributions in binary form must reproduce the above copyright
11*b8ad00b0SAndriy Voskoboinyk  *    notice, this list of conditions and the following disclaimer in the
12*b8ad00b0SAndriy Voskoboinyk  *    documentation and/or other materials provided with the distribution.
13*b8ad00b0SAndriy Voskoboinyk  *
14*b8ad00b0SAndriy Voskoboinyk  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*b8ad00b0SAndriy Voskoboinyk  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*b8ad00b0SAndriy Voskoboinyk  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*b8ad00b0SAndriy Voskoboinyk  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*b8ad00b0SAndriy Voskoboinyk  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*b8ad00b0SAndriy Voskoboinyk  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*b8ad00b0SAndriy Voskoboinyk  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*b8ad00b0SAndriy Voskoboinyk  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*b8ad00b0SAndriy Voskoboinyk  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*b8ad00b0SAndriy Voskoboinyk  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*b8ad00b0SAndriy Voskoboinyk  * SUCH DAMAGE.
25*b8ad00b0SAndriy Voskoboinyk  */
26*b8ad00b0SAndriy Voskoboinyk 
27*b8ad00b0SAndriy Voskoboinyk #include <sys/cdefs.h>
28*b8ad00b0SAndriy Voskoboinyk #include "opt_wlan.h"
29*b8ad00b0SAndriy Voskoboinyk 
30*b8ad00b0SAndriy Voskoboinyk #include <sys/param.h>
31*b8ad00b0SAndriy Voskoboinyk #include <sys/lock.h>
32*b8ad00b0SAndriy Voskoboinyk #include <sys/mutex.h>
33*b8ad00b0SAndriy Voskoboinyk #include <sys/mbuf.h>
34*b8ad00b0SAndriy Voskoboinyk #include <sys/kernel.h>
35*b8ad00b0SAndriy Voskoboinyk #include <sys/socket.h>
36*b8ad00b0SAndriy Voskoboinyk #include <sys/systm.h>
37*b8ad00b0SAndriy Voskoboinyk #include <sys/malloc.h>
38*b8ad00b0SAndriy Voskoboinyk #include <sys/queue.h>
39*b8ad00b0SAndriy Voskoboinyk #include <sys/taskqueue.h>
40*b8ad00b0SAndriy Voskoboinyk #include <sys/bus.h>
41*b8ad00b0SAndriy Voskoboinyk #include <sys/endian.h>
42*b8ad00b0SAndriy Voskoboinyk #include <sys/linker.h>
43*b8ad00b0SAndriy Voskoboinyk 
44*b8ad00b0SAndriy Voskoboinyk #include <net/if.h>
45*b8ad00b0SAndriy Voskoboinyk #include <net/ethernet.h>
46*b8ad00b0SAndriy Voskoboinyk #include <net/if_media.h>
47*b8ad00b0SAndriy Voskoboinyk 
48*b8ad00b0SAndriy Voskoboinyk #include <net80211/ieee80211_var.h>
49*b8ad00b0SAndriy Voskoboinyk #include <net80211/ieee80211_radiotap.h>
50*b8ad00b0SAndriy Voskoboinyk 
51*b8ad00b0SAndriy Voskoboinyk #include <dev/rtwn/if_rtwnvar.h>
52*b8ad00b0SAndriy Voskoboinyk #include <dev/rtwn/if_rtwn_debug.h>
53*b8ad00b0SAndriy Voskoboinyk 
54*b8ad00b0SAndriy Voskoboinyk #include <dev/rtwn/usb/rtwn_usb_var.h>
55*b8ad00b0SAndriy Voskoboinyk 
56*b8ad00b0SAndriy Voskoboinyk #include <dev/rtwn/rtl8812a/r12a_var.h>
57*b8ad00b0SAndriy Voskoboinyk 
58*b8ad00b0SAndriy Voskoboinyk #include <dev/rtwn/rtl8821a/usb/r21au.h>
59*b8ad00b0SAndriy Voskoboinyk #include <dev/rtwn/rtl8821a/usb/r21au_reg.h>
60*b8ad00b0SAndriy Voskoboinyk 
61*b8ad00b0SAndriy Voskoboinyk #define R21AU_RADAR_CHECK_PERIOD	(2 * hz)
62*b8ad00b0SAndriy Voskoboinyk 
63*b8ad00b0SAndriy Voskoboinyk static void
r21au_dfs_radar_disable(struct rtwn_softc * sc)64*b8ad00b0SAndriy Voskoboinyk r21au_dfs_radar_disable(struct rtwn_softc *sc)
65*b8ad00b0SAndriy Voskoboinyk {
66*b8ad00b0SAndriy Voskoboinyk 	rtwn_bb_setbits(sc, 0x924, 0x00008000, 0);
67*b8ad00b0SAndriy Voskoboinyk }
68*b8ad00b0SAndriy Voskoboinyk 
69*b8ad00b0SAndriy Voskoboinyk static int
r21au_dfs_radar_is_enabled(struct rtwn_softc * sc)70*b8ad00b0SAndriy Voskoboinyk r21au_dfs_radar_is_enabled(struct rtwn_softc *sc)
71*b8ad00b0SAndriy Voskoboinyk {
72*b8ad00b0SAndriy Voskoboinyk 	return !!(rtwn_bb_read(sc, 0x924) & 0x00008000);
73*b8ad00b0SAndriy Voskoboinyk }
74*b8ad00b0SAndriy Voskoboinyk 
75*b8ad00b0SAndriy Voskoboinyk static int
r21au_dfs_radar_reset(struct rtwn_softc * sc)76*b8ad00b0SAndriy Voskoboinyk r21au_dfs_radar_reset(struct rtwn_softc *sc)
77*b8ad00b0SAndriy Voskoboinyk {
78*b8ad00b0SAndriy Voskoboinyk 	int error;
79*b8ad00b0SAndriy Voskoboinyk 
80*b8ad00b0SAndriy Voskoboinyk 	error = rtwn_bb_setbits(sc, 0x924, 0x00008000, 0);
81*b8ad00b0SAndriy Voskoboinyk 	if (error != 0)
82*b8ad00b0SAndriy Voskoboinyk 		return (error);
83*b8ad00b0SAndriy Voskoboinyk 
84*b8ad00b0SAndriy Voskoboinyk 	return (rtwn_bb_setbits(sc, 0x924, 0, 0x00008000));
85*b8ad00b0SAndriy Voskoboinyk }
86*b8ad00b0SAndriy Voskoboinyk 
87*b8ad00b0SAndriy Voskoboinyk static int
r21au_dfs_radar_enable(struct rtwn_softc * sc)88*b8ad00b0SAndriy Voskoboinyk r21au_dfs_radar_enable(struct rtwn_softc *sc)
89*b8ad00b0SAndriy Voskoboinyk {
90*b8ad00b0SAndriy Voskoboinyk #define RTWN_CHK(res) do {	\
91*b8ad00b0SAndriy Voskoboinyk 	if (res != 0)		\
92*b8ad00b0SAndriy Voskoboinyk 		return (EIO);	\
93*b8ad00b0SAndriy Voskoboinyk } while(0)
94*b8ad00b0SAndriy Voskoboinyk 
95*b8ad00b0SAndriy Voskoboinyk 	RTWN_ASSERT_LOCKED(sc);
96*b8ad00b0SAndriy Voskoboinyk 
97*b8ad00b0SAndriy Voskoboinyk 	RTWN_CHK(rtwn_bb_setbits(sc, 0x814, 0x3fffffff, 0x04cc4d10));
98*b8ad00b0SAndriy Voskoboinyk 	RTWN_CHK(rtwn_bb_setbits(sc, R12A_BW_INDICATION, 0xff, 0x06));
99*b8ad00b0SAndriy Voskoboinyk 	RTWN_CHK(rtwn_bb_write(sc, 0x918, 0x1c16ecdf));
100*b8ad00b0SAndriy Voskoboinyk 	RTWN_CHK(rtwn_bb_write(sc, 0x924, 0x0152a400));
101*b8ad00b0SAndriy Voskoboinyk 	RTWN_CHK(rtwn_bb_write(sc, 0x91c, 0x0fa21a20));
102*b8ad00b0SAndriy Voskoboinyk 	RTWN_CHK(rtwn_bb_write(sc, 0x920, 0xe0f57204));
103*b8ad00b0SAndriy Voskoboinyk 
104*b8ad00b0SAndriy Voskoboinyk 	return (r21au_dfs_radar_reset(sc));
105*b8ad00b0SAndriy Voskoboinyk 
106*b8ad00b0SAndriy Voskoboinyk #undef RTWN_CHK
107*b8ad00b0SAndriy Voskoboinyk }
108*b8ad00b0SAndriy Voskoboinyk 
109*b8ad00b0SAndriy Voskoboinyk static int
r21au_dfs_radar_is_detected(struct rtwn_softc * sc)110*b8ad00b0SAndriy Voskoboinyk r21au_dfs_radar_is_detected(struct rtwn_softc *sc)
111*b8ad00b0SAndriy Voskoboinyk {
112*b8ad00b0SAndriy Voskoboinyk 	return !!(rtwn_bb_read(sc, 0xf98) & 0x00020000);
113*b8ad00b0SAndriy Voskoboinyk }
114*b8ad00b0SAndriy Voskoboinyk 
115*b8ad00b0SAndriy Voskoboinyk void
r21au_chan_check(void * arg,int npending __unused)116*b8ad00b0SAndriy Voskoboinyk r21au_chan_check(void *arg, int npending __unused)
117*b8ad00b0SAndriy Voskoboinyk {
118*b8ad00b0SAndriy Voskoboinyk 	struct rtwn_softc *sc = arg;
119*b8ad00b0SAndriy Voskoboinyk 	struct r12a_softc *rs = sc->sc_priv;
120*b8ad00b0SAndriy Voskoboinyk 	struct ieee80211com *ic = &sc->sc_ic;
121*b8ad00b0SAndriy Voskoboinyk 
122*b8ad00b0SAndriy Voskoboinyk 	RTWN_LOCK(sc);
123*b8ad00b0SAndriy Voskoboinyk #ifdef DIAGNOSTIC
124*b8ad00b0SAndriy Voskoboinyk 	RTWN_DPRINTF(sc, RTWN_DEBUG_STATE,
125*b8ad00b0SAndriy Voskoboinyk 	    "%s: periodical radar detection task\n", __func__);
126*b8ad00b0SAndriy Voskoboinyk #endif
127*b8ad00b0SAndriy Voskoboinyk 
128*b8ad00b0SAndriy Voskoboinyk 	if (!r21au_dfs_radar_is_enabled(sc)) {
129*b8ad00b0SAndriy Voskoboinyk 		if (rs->rs_flags & R12A_RADAR_ENABLED) {
130*b8ad00b0SAndriy Voskoboinyk 			/* should not happen */
131*b8ad00b0SAndriy Voskoboinyk 			device_printf(sc->sc_dev,
132*b8ad00b0SAndriy Voskoboinyk 			    "%s: radar detection was turned off "
133*b8ad00b0SAndriy Voskoboinyk 			    "unexpectedly, resetting...\n", __func__);
134*b8ad00b0SAndriy Voskoboinyk 
135*b8ad00b0SAndriy Voskoboinyk 			/* XXX something more appropriate? */
136*b8ad00b0SAndriy Voskoboinyk 			ieee80211_restart_all(ic);
137*b8ad00b0SAndriy Voskoboinyk 		}
138*b8ad00b0SAndriy Voskoboinyk 		RTWN_UNLOCK(sc);
139*b8ad00b0SAndriy Voskoboinyk 		return;
140*b8ad00b0SAndriy Voskoboinyk 	}
141*b8ad00b0SAndriy Voskoboinyk 
142*b8ad00b0SAndriy Voskoboinyk 	if (r21au_dfs_radar_is_detected(sc)) {
143*b8ad00b0SAndriy Voskoboinyk 		r21au_dfs_radar_reset(sc);
144*b8ad00b0SAndriy Voskoboinyk 
145*b8ad00b0SAndriy Voskoboinyk 		RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR, "%s: got radar event\n",
146*b8ad00b0SAndriy Voskoboinyk 		    __func__);
147*b8ad00b0SAndriy Voskoboinyk 
148*b8ad00b0SAndriy Voskoboinyk 		RTWN_UNLOCK(sc);
149*b8ad00b0SAndriy Voskoboinyk 		IEEE80211_LOCK(ic);
150*b8ad00b0SAndriy Voskoboinyk 
151*b8ad00b0SAndriy Voskoboinyk 		ieee80211_dfs_notify_radar(ic, ic->ic_curchan);
152*b8ad00b0SAndriy Voskoboinyk 
153*b8ad00b0SAndriy Voskoboinyk 		IEEE80211_UNLOCK(ic);
154*b8ad00b0SAndriy Voskoboinyk 		RTWN_LOCK(sc);
155*b8ad00b0SAndriy Voskoboinyk 	}
156*b8ad00b0SAndriy Voskoboinyk 
157*b8ad00b0SAndriy Voskoboinyk 	if (rs->rs_flags & R12A_RADAR_ENABLED) {
158*b8ad00b0SAndriy Voskoboinyk 		taskqueue_enqueue_timeout(taskqueue_thread,
159*b8ad00b0SAndriy Voskoboinyk 		    &rs->rs_chan_check, R21AU_RADAR_CHECK_PERIOD);
160*b8ad00b0SAndriy Voskoboinyk 	}
161*b8ad00b0SAndriy Voskoboinyk 	RTWN_UNLOCK(sc);
162*b8ad00b0SAndriy Voskoboinyk }
163*b8ad00b0SAndriy Voskoboinyk 
164*b8ad00b0SAndriy Voskoboinyk int
r21au_newstate(struct ieee80211vap * vap,enum ieee80211_state nstate,int arg)165*b8ad00b0SAndriy Voskoboinyk r21au_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
166*b8ad00b0SAndriy Voskoboinyk {
167*b8ad00b0SAndriy Voskoboinyk 	struct ieee80211com *ic = vap->iv_ic;
168*b8ad00b0SAndriy Voskoboinyk 	struct rtwn_softc *sc = ic->ic_softc;
169*b8ad00b0SAndriy Voskoboinyk 	struct rtwn_vap *rvp = RTWN_VAP(vap);
170*b8ad00b0SAndriy Voskoboinyk 	struct r12a_softc *rs = sc->sc_priv;
171*b8ad00b0SAndriy Voskoboinyk 	int error;
172*b8ad00b0SAndriy Voskoboinyk 
173*b8ad00b0SAndriy Voskoboinyk 	KASSERT(rvp->id == 0 || rvp->id == 1,
174*b8ad00b0SAndriy Voskoboinyk 	    ("%s: unexpected vap id %d\n", __func__, rvp->id));
175*b8ad00b0SAndriy Voskoboinyk 
176*b8ad00b0SAndriy Voskoboinyk 	IEEE80211_UNLOCK(ic);
177*b8ad00b0SAndriy Voskoboinyk 	RTWN_LOCK(sc);
178*b8ad00b0SAndriy Voskoboinyk 
179*b8ad00b0SAndriy Voskoboinyk 	error = 0;
180*b8ad00b0SAndriy Voskoboinyk 	if (nstate == IEEE80211_S_CAC &&
181*b8ad00b0SAndriy Voskoboinyk 	    !(rs->rs_flags & R12A_RADAR_ENABLED)) {
182*b8ad00b0SAndriy Voskoboinyk 		error = r21au_dfs_radar_enable(sc);
183*b8ad00b0SAndriy Voskoboinyk 		if (error != 0) {
184*b8ad00b0SAndriy Voskoboinyk 			device_printf(sc->sc_dev,
185*b8ad00b0SAndriy Voskoboinyk 			    "%s: cannot enable radar detection\n", __func__);
186*b8ad00b0SAndriy Voskoboinyk 			goto fail;
187*b8ad00b0SAndriy Voskoboinyk 		}
188*b8ad00b0SAndriy Voskoboinyk 		rs->rs_flags |= R12A_RADAR_ENABLED;
189*b8ad00b0SAndriy Voskoboinyk 
190*b8ad00b0SAndriy Voskoboinyk 		RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR,
191*b8ad00b0SAndriy Voskoboinyk 		    "%s: radar detection was enabled\n", __func__);
192*b8ad00b0SAndriy Voskoboinyk 
193*b8ad00b0SAndriy Voskoboinyk 		taskqueue_enqueue_timeout(taskqueue_thread,
194*b8ad00b0SAndriy Voskoboinyk 		    &rs->rs_chan_check, R21AU_RADAR_CHECK_PERIOD);
195*b8ad00b0SAndriy Voskoboinyk 	}
196*b8ad00b0SAndriy Voskoboinyk 
197*b8ad00b0SAndriy Voskoboinyk 	if ((nstate < IEEE80211_S_CAC || nstate == IEEE80211_S_CSA) &&
198*b8ad00b0SAndriy Voskoboinyk 	    (rs->rs_flags & R12A_RADAR_ENABLED) &&
199*b8ad00b0SAndriy Voskoboinyk 	    (sc->vaps[!rvp->id] == NULL ||
200*b8ad00b0SAndriy Voskoboinyk 	    sc->vaps[!rvp->id]->vap.iv_state < IEEE80211_S_CAC ||
201*b8ad00b0SAndriy Voskoboinyk 	    sc->vaps[!rvp->id]->vap.iv_state == IEEE80211_S_CSA)) {
202*b8ad00b0SAndriy Voskoboinyk 		taskqueue_cancel_timeout(taskqueue_thread, &rs->rs_chan_check,
203*b8ad00b0SAndriy Voskoboinyk 		    NULL);
204*b8ad00b0SAndriy Voskoboinyk 
205*b8ad00b0SAndriy Voskoboinyk 		rs->rs_flags &= ~R12A_RADAR_ENABLED;
206*b8ad00b0SAndriy Voskoboinyk 		r21au_dfs_radar_disable(sc);
207*b8ad00b0SAndriy Voskoboinyk 
208*b8ad00b0SAndriy Voskoboinyk 		RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR,
209*b8ad00b0SAndriy Voskoboinyk 		    "%s: radar detection was disabled\n", __func__);
210*b8ad00b0SAndriy Voskoboinyk 	}
211*b8ad00b0SAndriy Voskoboinyk 
212*b8ad00b0SAndriy Voskoboinyk fail:
213*b8ad00b0SAndriy Voskoboinyk 	RTWN_UNLOCK(sc);
214*b8ad00b0SAndriy Voskoboinyk 	IEEE80211_LOCK(ic);
215*b8ad00b0SAndriy Voskoboinyk 
216*b8ad00b0SAndriy Voskoboinyk 	if (error != 0)
217*b8ad00b0SAndriy Voskoboinyk 		return (error);
218*b8ad00b0SAndriy Voskoboinyk 
219*b8ad00b0SAndriy Voskoboinyk 	return (rs->rs_newstate[rvp->id](vap, nstate, arg));
220*b8ad00b0SAndriy Voskoboinyk }
221*b8ad00b0SAndriy Voskoboinyk 
222*b8ad00b0SAndriy Voskoboinyk void
r21au_scan_start(struct ieee80211com * ic)223*b8ad00b0SAndriy Voskoboinyk r21au_scan_start(struct ieee80211com *ic)
224*b8ad00b0SAndriy Voskoboinyk {
225*b8ad00b0SAndriy Voskoboinyk 	struct rtwn_softc *sc = ic->ic_softc;
226*b8ad00b0SAndriy Voskoboinyk 	struct r12a_softc *rs = sc->sc_priv;
227*b8ad00b0SAndriy Voskoboinyk 
228*b8ad00b0SAndriy Voskoboinyk 	RTWN_LOCK(sc);
229*b8ad00b0SAndriy Voskoboinyk 	if (rs->rs_flags & R12A_RADAR_ENABLED) {
230*b8ad00b0SAndriy Voskoboinyk 		RTWN_UNLOCK(sc);
231*b8ad00b0SAndriy Voskoboinyk 		while (taskqueue_cancel_timeout(taskqueue_thread,
232*b8ad00b0SAndriy Voskoboinyk 		    &rs->rs_chan_check, NULL) != 0) {
233*b8ad00b0SAndriy Voskoboinyk 			taskqueue_drain_timeout(taskqueue_thread,
234*b8ad00b0SAndriy Voskoboinyk 			    &rs->rs_chan_check);
235*b8ad00b0SAndriy Voskoboinyk 		}
236*b8ad00b0SAndriy Voskoboinyk 		RTWN_LOCK(sc);
237*b8ad00b0SAndriy Voskoboinyk 
238*b8ad00b0SAndriy Voskoboinyk 		r21au_dfs_radar_disable(sc);
239*b8ad00b0SAndriy Voskoboinyk 		RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR,
240*b8ad00b0SAndriy Voskoboinyk 		    "%s: radar detection was (temporarily) disabled\n",
241*b8ad00b0SAndriy Voskoboinyk 		    __func__);
242*b8ad00b0SAndriy Voskoboinyk 	}
243*b8ad00b0SAndriy Voskoboinyk 	RTWN_UNLOCK(sc);
244*b8ad00b0SAndriy Voskoboinyk 
245*b8ad00b0SAndriy Voskoboinyk 	rs->rs_scan_start(ic);
246*b8ad00b0SAndriy Voskoboinyk }
247*b8ad00b0SAndriy Voskoboinyk 
248*b8ad00b0SAndriy Voskoboinyk void
r21au_scan_end(struct ieee80211com * ic)249*b8ad00b0SAndriy Voskoboinyk r21au_scan_end(struct ieee80211com *ic)
250*b8ad00b0SAndriy Voskoboinyk {
251*b8ad00b0SAndriy Voskoboinyk 	struct rtwn_softc *sc = ic->ic_softc;
252*b8ad00b0SAndriy Voskoboinyk 	struct r12a_softc *rs = sc->sc_priv;
253*b8ad00b0SAndriy Voskoboinyk 	int error;
254*b8ad00b0SAndriy Voskoboinyk 
255*b8ad00b0SAndriy Voskoboinyk 	RTWN_LOCK(sc);
256*b8ad00b0SAndriy Voskoboinyk 	if (rs->rs_flags & R12A_RADAR_ENABLED) {
257*b8ad00b0SAndriy Voskoboinyk 		error = r21au_dfs_radar_enable(sc);
258*b8ad00b0SAndriy Voskoboinyk 		if (error != 0) {
259*b8ad00b0SAndriy Voskoboinyk 			device_printf(sc->sc_dev,
260*b8ad00b0SAndriy Voskoboinyk 			    "%s: cannot re-enable radar detection\n",
261*b8ad00b0SAndriy Voskoboinyk 			    __func__);
262*b8ad00b0SAndriy Voskoboinyk 
263*b8ad00b0SAndriy Voskoboinyk 			/* XXX */
264*b8ad00b0SAndriy Voskoboinyk 			ieee80211_restart_all(ic);
265*b8ad00b0SAndriy Voskoboinyk 			RTWN_UNLOCK(sc);
266*b8ad00b0SAndriy Voskoboinyk 			return;
267*b8ad00b0SAndriy Voskoboinyk 		}
268*b8ad00b0SAndriy Voskoboinyk 		RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR,
269*b8ad00b0SAndriy Voskoboinyk 		    "%s: radar detection was re-enabled\n", __func__);
270*b8ad00b0SAndriy Voskoboinyk 
271*b8ad00b0SAndriy Voskoboinyk 		taskqueue_enqueue_timeout(taskqueue_thread,
272*b8ad00b0SAndriy Voskoboinyk 		    &rs->rs_chan_check, R21AU_RADAR_CHECK_PERIOD);
273*b8ad00b0SAndriy Voskoboinyk 	}
274*b8ad00b0SAndriy Voskoboinyk 	RTWN_UNLOCK(sc);
275*b8ad00b0SAndriy Voskoboinyk 
276*b8ad00b0SAndriy Voskoboinyk 	rs->rs_scan_end(ic);
277*b8ad00b0SAndriy Voskoboinyk }
278