2 * This software is distributed under the terms of the
3 * GNU General Public License ("GPL") version 2 as published by the Free
7 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
8 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
10 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
11 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
12 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
14 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
15 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
16 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
17 * THE POSSIBILITY OF SUCH DAMAGES.
19 * $Id: if_ath_radar.c 2464 2007-06-15 22:51:56Z mtaylor $
23 #include "if_ath_debug.h"
25 #ifndef AUTOCONF_INCLUDED
26 #include <linux/config.h>
28 #include <linux/version.h>
29 #include <linux/module.h>
30 #include <linux/init.h>
31 #include <linux/skbuff.h>
32 #include <linux/netdevice.h>
33 #include <linux/etherdevice.h>
34 #include <linux/random.h>
35 #include <linux/delay.h>
36 #include <linux/cache.h>
37 #include <linux/sysctl.h>
38 #include <linux/proc_fs.h>
39 #include <linux/if_arp.h>
40 #include <linux/rtnetlink.h>
41 #include <linux/time.h>
42 #include <asm/uaccess.h>
43 #include <linux/param.h>
45 #include "if_ethersubr.h" /* for ETHER_IS_MULTICAST */
49 #include <net80211/ieee80211_radiotap.h>
50 #include <net80211/ieee80211_var.h>
51 #include <net80211/ieee80211_monitor.h>
52 #include <net80211/ieee80211_rate.h>
54 #ifdef USE_HEADERLEN_RESV
55 #include <net80211/if_llc.h>
58 #include "net80211/if_athproto.h"
59 #include "if_athvar.h"
63 #include "ah_devid.h" /* XXX to identify chipset */
65 #ifdef ATH_PCI /* PCI BUS */
66 #include "if_ath_pci.h"
68 #ifdef ATH_AHB /* AHB BUS */
69 #include "if_ath_ahb.h"
73 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
76 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
79 #include "if_ath_hal.h"
86 #include "if_ath_radar.h"
88 #define sizetab(t) (sizeof(t)/sizeof(t[0]))
89 #define nofloat_pct(_value, _pct) \
90 ( (_value * (1000 + _pct)) / 1000 )
92 struct radar_pattern_specification
{
93 /* The name of the rule/specification (i.e. what did we detect) */
95 /* Interval MIN = 1000000 / FREQ - 2%
96 * (a.k.a. Pulse/Burst Repetition Interval) */
97 u_int32_t min_rep_int
;
98 /* Interval MAX = 1000000 / FREQ + 2%
99 * (a.k.a. Pulse/Burst Repetition Interval) */
100 u_int32_t max_rep_int
;
101 /* Do we adjust the min/max interval values dynamically
102 * based upon running mean interval? */
104 /* Fuzz factor dynamic matching, as unsigned integer percentage
105 * of variation (i.e. 2 for +/- 2% timing) */
107 /* Match MIN (Minimum Pulse/Burst events required) */
109 /* Match MIN duration (Minimum Pulse/Burst events
110 * required including missed) */
112 /* Match MAX duration (Maximum Pulse/Burst events
113 * required including missed) */
115 /* Maximum consecutive missing pulses */
116 u_int32_t max_consecutive_missing
;
117 /* Maximum missing pulses */
118 u_int32_t max_missing
;
119 /* Match on absolute distance to PRI/PRF midpoint */
120 HAL_BOOL match_midpoint
;
123 static struct radar_pattern_specification radar_patterns
[] = {
124 #ifdef DFS_DOMAIN_ETSI
125 {"ETSI [ 200]", 4900, 5100, AH_FALSE
, 20, 3, 4, 10, 4, 8, AH_TRUE
},
126 {"ETSI [ 300]", 3267, 3399, AH_FALSE
, 20, 3, 4, 10, 4, 6, AH_TRUE
},
127 {"ETSI [ 500]", 1960, 2040, AH_FALSE
, 20, 4, 4, 10, 4, 8, AH_TRUE
},
128 {"ETSI [ 750]", 1307, 1359, AH_FALSE
, 20, 5, 4, 15, 4, 13, AH_TRUE
},
129 {"ETSI [ 800]", 1225, 1275, AH_FALSE
, 20, 4, 4, 10, 4, 8, AH_TRUE
},
130 {"ETSI [1000]", 980, 1020, AH_FALSE
, 20, 4, 4, 10, 4, 8, AH_TRUE
},
131 {"ETSI [1200]", 817, 849, AH_FALSE
, 20, 5, 4, 15, 4, 13, AH_TRUE
},
132 {"ETSI [1500]", 653, 679, AH_FALSE
, 20, 5, 4, 15, 4, 6, AH_TRUE
},
133 {"ETSI [1600]", 613, 637, AH_FALSE
, 20, 5, 4, 15, 4, 7, AH_TRUE
},
134 {"ETSI [2000]", 490, 510, AH_FALSE
, 20, 7, 4, 20, 4, 10, AH_TRUE
},
135 {"ETSI [2300]", 426, 442, AH_FALSE
, 20, 9, 4, 25, 6, 20, AH_TRUE
},
136 {"ETSI [3000]", 327, 339, AH_FALSE
, 20, 7, 4, 20, 5, 20, AH_TRUE
},
137 {"ETSI [3500]", 280, 290, AH_FALSE
, 20, 9, 4, 25, 2, 20, AH_TRUE
},
138 {"ETSI [4000]", 245, 255, AH_FALSE
, 20, 7, 4, 20, 5, 20, AH_TRUE
},
140 #ifdef DFS_DOMAIN_FCC
141 {"FCC [1,1399-1714]", 1399, 1714, AH_TRUE
, 10, 5, 10, 18, 4, 6, AH_FALSE
},
142 {"FCC [2,147-235]", 147, 235, AH_TRUE
, 10, 8, 10, 29, 6, 12, AH_FALSE
},
143 {"FCC [3-4,196-273]", 196, 273, AH_TRUE
, 10, 8, 8, 18, 2, 16, AH_FALSE
},
144 {"FCC [3-4,275-352]", 275, 352, AH_TRUE
, 10, 8, 8, 18, 2, 16, AH_FALSE
},
145 {"FCC [3-4,354-431]", 354, 431, AH_TRUE
, 10, 8, 8, 18, 2, 16, AH_FALSE
},
146 {"FCC [3-4,433-510]", 433, 510, AH_TRUE
, 10, 8, 8, 18, 2, 16, AH_FALSE
},
147 {"FCC [3-4,235-313]", 235, 313, AH_TRUE
, 10, 8, 8, 18, 2, 16, AH_FALSE
},
148 {"FCC [3-4,314-392]", 314, 392, AH_TRUE
, 10, 8, 8, 18, 2, 16, AH_FALSE
},
149 {"FCC [3-4,393-471]", 393, 471, AH_TRUE
, 10, 8, 8, 18, 2, 16, AH_FALSE
}
154 static u_int32_t
interval_to_frequency(u_int32_t pri
);
155 #endif /* AR_DEBUG */
157 /* Returns true if radar detection is enabled. */
158 int ath_radar_is_enabled(struct ath_softc
*sc
)
160 struct ath_hal
*ah
= sc
->sc_ah
;
161 if (ar_device(sc
->devid
) >= 5211)
162 return ((OS_REG_READ(ah
, AR5K_AR5212_PHY_ERR_FIL
) &
163 AR5K_AR5212_PHY_ERR_FIL_RADAR
) &&
164 (sc
->sc_imask
& HAL_INT_RXPHY
) &&
165 (ath_hal_intrget(ah
) & HAL_INT_RXPHY
));
167 return ((sc
->sc_imask
& HAL_INT_RXPHY
) &&
168 (ath_hal_intrget(ah
) & HAL_INT_RXPHY
));
172 /* Read the radar pulse detection parameters. */
173 void ath_radar_get_params(struct ath_softc
*sc
, RADAR_PARAM
*rp
)
175 u_int32_t radar
= ath_reg_read(sc
, AR5K_PHY_RADAR
);
176 rp
->rp_fir_filter_output_power_thr
=
177 (radar
& AR5K_PHY_RADAR_FIRPWROUTTHR
) >>
178 AR5K_PHY_RADAR_FIRPWROUTTHR_S
;
179 rp
->rp_radar_rssi_thr
=
180 (radar
& AR5K_PHY_RADAR_PULSERSSITHR
) >>
181 AR5K_PHY_RADAR_PULSERSSITHR_S
;
182 rp
->rp_pulse_height_thr
=
183 (radar
& AR5K_PHY_RADAR_PULSEHEIGHTTHR
) >>
184 AR5K_PHY_RADAR_PULSEHEIGHTTHR_S
;
185 rp
->rp_pulse_rssi_thr
=
186 (radar
& AR5K_PHY_RADAR_RADARRSSITHR
) >>
187 AR5K_PHY_RADAR_RADARRSSITHR_S
;
189 (radar
& AR5K_PHY_RADAR_INBANDTHR
) >>
190 AR5K_PHY_RADAR_INBANDTHR_S
;
193 /* Update the radar pulse detection parameters.
194 * If rp is NULL, defaults are used for all fields.
195 * If any member of rp is set to RADAR_PARAM_USE_DEFAULT, the default
196 * is used for that field. */
197 void ath_radar_set_params(struct ath_softc
*sc
, RADAR_PARAM
*rp
)
199 #define BUILD_PHY_RADAR_FIELD(_MASK,_SHIFT,_FIELD) \
200 ((NULL == rp || (rp->_FIELD == RADAR_PARAM_USE_DEFAULT)) ? \
201 ((AR5K_PHY_RADAR_ENABLED_AR5213 & (_MASK))) : \
202 ((rp->_FIELD << (_SHIFT)) & (_MASK)))
203 ath_reg_write(sc
, AR5K_PHY_RADAR
,
204 BUILD_PHY_RADAR_FIELD(AR5K_PHY_RADAR_FIRPWROUTTHR
,
205 AR5K_PHY_RADAR_FIRPWROUTTHR_S
,
206 rp_fir_filter_output_power_thr
) |
207 BUILD_PHY_RADAR_FIELD(AR5K_PHY_RADAR_RADARRSSITHR
,
208 AR5K_PHY_RADAR_RADARRSSITHR_S
,
210 BUILD_PHY_RADAR_FIELD(AR5K_PHY_RADAR_PULSEHEIGHTTHR
,
211 AR5K_PHY_RADAR_PULSEHEIGHTTHR_S
,
212 rp_pulse_height_thr
) |
213 BUILD_PHY_RADAR_FIELD(AR5K_PHY_RADAR_PULSERSSITHR
,
214 AR5K_PHY_RADAR_PULSERSSITHR_S
, rp_radar_rssi_thr
) |
215 BUILD_PHY_RADAR_FIELD(AR5K_PHY_RADAR_INBANDTHR
,
216 AR5K_PHY_RADAR_INBANDTHR_S
,
219 #undef BUILD_PHY_RADAR_FIELD
222 /* This is called on channel change to enable radar detection for 5211+ chips.
223 * NOTE: AR5210 doesn't have radar pulse detection support. */
224 int ath_radar_update(struct ath_softc
*sc
)
227 struct ath_hal
*ah
= sc
->sc_ah
;
228 struct ieee80211com
*ic
= &sc
->sc_ic
;
231 /* Do not attempt to change radar state when bg scanning is
233 if (ic
->ic_flags
& IEEE80211_F_SCAN
)
236 /* Update the DFS flags (as a sanity check) */
237 if (ath_radar_correct_dfs_flags(sc
, &sc
->sc_curchan
))
238 DPRINTF(sc
, ATH_DEBUG_DOTH
, "%s: %s: channel required "
239 "corrections to private flags.\n",
240 SC_DEV_NAME(sc
), __func__
);
241 required
= ath_radar_is_dfs_required(sc
, &sc
->sc_curchan
) &&
242 (ic
->ic_flags
& IEEE80211_F_DOTH
);
243 /* configure radar pulse detector register using default values, but do
244 * not toggle the enable bit. XXX: allow tweaking?? */
245 ath_radar_set_params(sc
, NULL
);
246 if (ar_device(sc
->devid
) >= 5211) {
247 HAL_INT old_ier
= ath_hal_intrget(ah
);
248 HAL_INT new_ier
= old_ier
;
249 unsigned int old_radar
= OS_REG_READ(ah
, AR5K_PHY_RADAR
);
250 unsigned int old_filter
=
251 OS_REG_READ(ah
, AR5K_AR5212_PHY_ERR_FIL
);
252 unsigned int old_rxfilt
= ath_hal_getrxfilter(ah
);
253 unsigned int old_mask
= sc
->sc_imask
;
254 unsigned int new_radar
= old_radar
;
255 unsigned int new_filter
= old_filter
;
256 unsigned int new_mask
= old_mask
;
257 unsigned int new_rxfilt
= old_rxfilt
;
259 ath_hal_intrset(ah
, old_ier
& ~HAL_INT_GLOBAL
);
261 new_radar
|= AR5K_PHY_RADAR_ENABLE
;
262 new_filter
|= AR5K_AR5212_PHY_ERR_FIL_RADAR
;
263 new_rxfilt
|= (HAL_RX_FILTER_PHYERR
|
264 HAL_RX_FILTER_PHYRADAR
);
265 new_mask
|= HAL_INT_RXPHY
;
266 new_ier
|= HAL_INT_RXPHY
;
268 new_radar
&= ~AR5K_PHY_RADAR_ENABLE
;
269 new_filter
&= ~AR5K_AR5212_PHY_ERR_FIL_RADAR
;
270 new_rxfilt
&= ~HAL_RX_FILTER_PHYRADAR
;
271 new_mask
&= ~HAL_INT_RXPHY
;
272 new_ier
&= ~HAL_INT_RXPHY
;
275 if (old_filter
!= new_filter
)
276 OS_REG_WRITE(ah
, AR5K_AR5212_PHY_ERR_FIL
, new_filter
);
277 if (old_radar
!= new_radar
)
278 OS_REG_WRITE(ah
, AR5K_PHY_RADAR
, new_radar
);
279 if (old_rxfilt
!= new_rxfilt
)
280 ath_hal_setrxfilter(ah
, new_rxfilt
);
282 sc
->sc_imask
= new_mask
;
283 if (DFLAG_ISSET(sc
, ATH_DEBUG_DOTH
) &&
284 ((old_radar
!= new_radar
) ||
285 (old_filter
!= new_filter
) ||
286 (old_rxfilt
!= new_rxfilt
) ||
287 (old_mask
!= new_mask
) ||
288 (old_ier
!= new_ier
))) {
289 DPRINTF(sc
, ATH_DEBUG_DOTH
,
290 "%s: %s: Radar detection %s.\n", SC_DEV_NAME(sc
),
291 __func__
, required
? "enabled" : "disabled");
293 ath_hal_intrset(ah
, new_ier
);
296 return (required
== ath_radar_is_enabled(sc
));
299 /* Update channel's DFS flags based upon whether DFS is required. Return
300 * true if the value was repaired. */
301 int ath_radar_correct_dfs_flags(struct ath_softc
*sc
, HAL_CHANNEL
*hchan
)
303 u_int32_t old_channelFlags
= hchan
->channelFlags
;
304 u_int32_t old_privFlags
= hchan
->privFlags
;
305 if (ath_radar_is_dfs_required(sc
, hchan
)) {
306 hchan
->channelFlags
|= CHANNEL_PASSIVE
;
307 hchan
->privFlags
|= CHANNEL_DFS
;
309 hchan
->channelFlags
&= ~CHANNEL_PASSIVE
;
310 hchan
->privFlags
&= ~CHANNEL_DFS
;
312 return ((old_privFlags
!= hchan
->privFlags
) ||
313 (old_channelFlags
!= hchan
->channelFlags
));
316 /* Returns true if DFS is required for the regulatory domain, country and
317 * combination in use.
318 * XXX: Need to add regulatory rules in here. This is too conservative! */
319 int ath_radar_is_dfs_required(struct ath_softc
*sc
, HAL_CHANNEL
*hchan
)
321 /* For FCC: 5250 to 5350MHz (channel 52 to 60) and for Europe added
322 * 5470 to 5725 MHz (channel 100 to 140).
323 * Being conservative, go with the entire band from 5250-5725 MHz. */
324 return ((hchan
->channel
>= 5250) && (hchan
->channel
<= 5725)) ? 1 : 0;
327 static struct ath_rp
*pulse_head(struct ath_softc
*sc
)
329 return list_entry(sc
->sc_rp_list
.next
,
330 struct ath_rp
, list
);
333 static struct ath_rp
*pulse_tail(struct ath_softc
*sc
)
335 return list_entry(sc
->sc_rp_list
.prev
,
336 struct ath_rp
, list
);
339 static struct ath_rp
*pulse_prev(struct ath_rp
*pulse
)
341 return list_entry(pulse
->list
.prev
,
342 struct ath_rp
, list
);
345 #define CR_FALLTHROUGH 0
347 #define CR_EXCESS_INTERVALS 2
348 #define CR_INTERVALS 3
349 #define CR_EXCESS_DURATION 4
350 #define CR_DURATION 5
353 #define CR_MIDPOINT_A 8
354 #define CR_MIDPOINT_B 9
355 #define CR_MIDPOINT_C 10
359 #define MR_FAIL_MIN_INTERVALS 1
360 #define MR_FAIL_REQD_MATCHES 2
361 #define MR_FAIL_MAX_MISSES 3
362 #define MR_FAIL_MIN_PERIOD 4
363 #define MR_FAIL_MAX_PERIOD 5
366 static const char *get_match_result_desc(u_int32_t code
)
371 case MR_FAIL_MIN_INTERVALS
:
373 case MR_FAIL_REQD_MATCHES
:
375 case MR_FAIL_MAX_MISSES
:
377 case MR_FAIL_MIN_PERIOD
:
379 case MR_FAIL_MAX_PERIOD
:
385 #endif /* AR_DEBUG */
387 static int32_t match_radar(
390 u_int32_t mean_period
,
394 u_int32_t min_rep_int
,
395 u_int32_t max_rep_int
,
397 u_int32_t max_misses
)
399 /* Not a match: insufficient overall burst length */
400 if ( (matched
+ missed
) < min_evts
)
401 return MR_FAIL_MIN_INTERVALS
;
403 /* Not a match: insufficient match count */
404 if (matched
< min_pulse
)
405 return MR_FAIL_REQD_MATCHES
;
407 /* Not a match: too many missies */
408 if (missed
> max_misses
)
409 return MR_FAIL_MAX_MISSES
;
411 /* Not a match, PRI out of range */
412 if (mean_period
< min_rep_int
)
413 return MR_FAIL_MIN_PERIOD
;
415 /* Not a match, PRI out of range */
416 if (mean_period
> max_rep_int
)
417 return MR_FAIL_MAX_PERIOD
;
422 static int32_t compare_radar_matches(
425 int32_t a_mean_period
,
429 int32_t a_min_rep_int
,
430 int32_t a_max_rep_int
,
432 int32_t a_max_misses
,
433 HAL_BOOL a_match_midpoint
,
436 int32_t b_mean_period
,
440 int32_t b_min_rep_int
,
441 int32_t b_max_rep_int
,
443 int32_t b_max_misses
,
444 HAL_BOOL b_match_midpoint
447 /* Intermediate calculations */
448 int32_t a_total
= a_matched
+ a_missed
;
449 int32_t b_total
= b_matched
+ b_missed
;
450 int32_t a_excess_total
=
451 MAX((int32_t)(a_total
- (int32_t)a_max_evts
), 0);
452 int32_t b_excess_total
=
453 MAX((int32_t)(b_total
- (int32_t)b_max_evts
), 0);
454 u_int64_t a_duration
= a_total
* a_mean_period
;
455 u_int64_t b_duration
= b_total
* b_mean_period
;
456 u_int64_t a_excess_duration
= a_excess_total
* a_mean_period
;
457 u_int64_t b_excess_duration
= b_excess_total
* b_mean_period
;
458 u_int64_t a_dist_from_pri_mid
= labs(a_mean_period
-
460 ((a_max_rep_int
- a_min_rep_int
) / 2)));
461 u_int64_t b_dist_from_pri_mid
= labs(b_mean_period
-
463 ((b_max_rep_int
- b_min_rep_int
) / 2)));
464 /* Did one radar have fewer excess total pulse intervals than the
466 if (a_excess_total
!= b_excess_total
)
467 return ((a_excess_total
< b_excess_total
) ? 1 : -1) *
469 /* Was one pulse longer chronologically, even though totals matched? */
470 else if (a_excess_duration
!= b_excess_duration
)
471 return ((a_excess_duration
< b_excess_duration
) ? 1 : -1) *
473 /* Did one get more matches? */
474 if (a_matched
!= b_matched
)
475 return (a_matched
> b_matched
? 1 : -1) * CR_PULSES
;
476 /* Both waveforms are the same length, same total.
477 * Did one get more misses? */
478 if (a_missed
!= b_missed
)
479 return (a_missed
< b_missed
? 1 : -1) * CR_MISSES
;
480 /* Did one get more noise? */
481 if (a_noise
!= b_noise
)
482 return (a_noise
< b_noise
? 1 : -1) * CR_NOISE
;
483 /* If both waveforms were not too long in terms of intervals */
484 if (0 == (a_excess_total
+b_excess_total
)) {
485 /* Did one waveform have to match more events than the other? */
486 if (a_total
!= b_total
)
487 return ((a_total
> b_total
) ? 1 : -1) * CR_INTERVALS
;
488 /* Was one waveform longer than the other */
489 if (a_duration
!= b_duration
)
490 return ((a_duration
> b_duration
) ? 1 : -1) * CR_DURATION
;
492 /* both durations are legal, but one is closer to the original PRF/PRI */
493 if (a_dist_from_pri_mid
!= b_dist_from_pri_mid
) {
494 if (a_match_midpoint
&& b_match_midpoint
) {
495 /* Which pattern is closer to midpoint? */
496 return ((a_dist_from_pri_mid
< b_dist_from_pri_mid
) ? 1 : -1) *
499 else if (a_match_midpoint
) {
500 /* If not within spitting distance of midpoint, reject */
501 return ((a_dist_from_pri_mid
< 3) ? 1 : -1) *
505 else if (b_match_midpoint
) {
506 /* If not within spitting distance of midpoint, reject */
507 return ((b_dist_from_pri_mid
>= 3) ? 1 : -1) *
511 return -CR_FALLTHROUGH
;
514 #ifdef ATH_RADAR_LONG_PULSE
517 u_int32_t lpb_num_pulses
;
518 u_int32_t lpb_num_noise
;
519 u_int32_t lpb_tsf_delta
;
520 u_int64_t lpb_tsf_rel
;
521 u_int64_t lpb_min_possible_tsf
; /* noise vs real pulses */
522 u_int64_t lpb_max_possible_tsf
; /* noise vs real pulses */
525 static const u_int32_t LP_MIN_BC
= 8;
526 static const u_int32_t LP_MAX_BC
= 20;
527 static const u_int32_t LP_NUM_BC
= 13; /* (LP_MAX_BC - LP_MIN_BC + 1); */
528 static const u_int64_t LP_TSF_FUZZ_US
= 32768; /* (1<<15) because rs_tstamp
530 static const u_int32_t LP_MIN_PRI
= 1000;
531 static const u_int32_t LP_MAX_PRI
= 2000;
533 static void rp_analyze_long_pulse_bscan(
534 struct ath_softc
*sc
,
535 struct ath_rp
*last_pulse
,
536 u_int32_t
*num_bursts
,
537 size_t bursts_buflen
,
538 struct lp_burst
*bursts
)
541 struct ath_rp
*newer
= NULL
;
542 struct ath_rp
*cur
= last_pulse
;
543 struct ath_rp
*older
= pulse_prev(last_pulse
);
544 u_int32_t waveform_num_bursts
= 0;
550 /* check if we are at the end of the list */
551 if (&cur
->list
== &sc
->sc_rp_head
)
553 if (!cur
->rp_allocated
)
557 u_int64_t tsf_delta
= 0;
558 u_int64_t tsf_adjustment
= 0;
560 /* Figure out TSF delta, taking into account
561 * up to one multiple of (1<<15) of clock jitter
562 * due to interrupt latency */
563 tsf_delta
= newer
->rp_tsf
- cur
->rp_tsf
;
564 if ((tsf_delta
- LP_TSF_FUZZ_US
) >= LP_MIN_PRI
&&
565 (tsf_delta
- LP_TSF_FUZZ_US
) <= LP_MAX_PRI
) {
566 tsf_adjustment
= LP_TSF_FUZZ_US
;
567 tsf_delta
-= tsf_adjustment
;
570 /* If we are in range for pulse, assume it is a pulse. */
571 if ((tsf_delta
>= LP_MIN_PRI
) && (tsf_delta
<= LP_MAX_PRI
)) {
572 bursts
[waveform_num_bursts
].lpb_num_pulses
++;
573 bursts
[waveform_num_bursts
].lpb_min_possible_tsf
=
574 cur
->rp_tsf
- tsf_adjustment
;
576 else if (tsf_delta
< LP_MIN_PRI
) {
577 bursts
[waveform_num_bursts
].lpb_num_noise
++;
578 /* It may have been THE pulse after all... */
579 bursts
[waveform_num_bursts
].lpb_min_possible_tsf
=
580 cur
->rp_tsf
- tsf_adjustment
;
582 else /* tsf_delta > LP_MAX_PRI */ {
583 bursts
[waveform_num_bursts
].lpb_num_pulses
++;
584 bursts
[waveform_num_bursts
].lpb_min_possible_tsf
=
586 /* Do not overrun bursts_buflen */
587 if ((waveform_num_bursts
+1) >= bursts_buflen
) {
590 waveform_num_bursts
++;
591 bursts
[waveform_num_bursts
].lpb_tsf_delta
= tsf_delta
;
592 bursts
[waveform_num_bursts
].lpb_min_possible_tsf
=
594 bursts
[waveform_num_bursts
].lpb_max_possible_tsf
=
599 bursts
[waveform_num_bursts
].lpb_max_possible_tsf
=
603 /* advance to next pulse */
605 cur
= pulse_prev(cur
);
606 older
= pulse_prev(cur
);
609 bursts
[waveform_num_bursts
].lpb_num_pulses
++;
610 waveform_num_bursts
++;
611 *num_bursts
= waveform_num_bursts
;
613 for (i
= 0; i
< waveform_num_bursts
; i
++)
614 bursts
[i
].lpb_tsf_rel
=
615 bursts
[i
].lpb_max_possible_tsf
-
616 bursts
[waveform_num_bursts
-1].lpb_min_possible_tsf
;
619 static HAL_BOOL
rp_analyze_long_pulse(
620 struct ath_softc
*sc
, struct ath_rp
*last_pulse
,
622 u_int32_t
*matched
, u_int32_t
*missed
,
623 u_int32_t
*noise
, u_int32_t
*pulses
)
626 int32_t found_radar
= 0;
627 int32_t found_burst_count
= 0;
628 int32_t matching_burst_count
= 0;
629 u_int32_t best_bc
= 0;
630 u_int32_t best_matched
= 0;
631 u_int32_t best_missed
= 0;
632 u_int32_t best_noise
= 0;
633 u_int32_t best_pulses
= 0;
635 struct lp_burst bursts
[LP_MAX_BC
];
636 memset(&bursts
, 0, sizeof(bursts
));
647 rp_analyze_long_pulse_bscan(sc
, last_pulse
,
649 LP_MAX_BC
, &bursts
[0]);
650 /* Find the matches */
651 for (matching_burst_count
= LP_MAX_BC
;
652 matching_burst_count
>= LP_MIN_BC
;
653 matching_burst_count
--) {
654 int32_t first_matched_index
= -1;
655 int32_t last_matched_index
= -1;
656 int32_t match_burst_index
= 0;
657 int32_t found_burst_index
= 0;
658 int32_t burst_period
= (12000000 / matching_burst_count
);
659 int32_t waveform_offset
= 0;
660 int32_t total_big_gaps
= 0;
661 int32_t matched_span
= 0;
662 int32_t missed_bursts
= 0;
663 int32_t matched_bursts
= 0;
664 for (i
= 0; i
< matching_burst_count
; i
++) {
665 int32_t d
= bursts
[i
].lpb_tsf_delta
;
666 while (d
>= burst_period
)
669 waveform_offset
= MAX(waveform_offset
, d
);
671 waveform_offset
*= -1;
673 found_burst_index
= 0;
674 for (match_burst_index
= 0;
675 match_burst_index
< matching_burst_count
;
676 match_burst_index
++) {
677 int64_t limit_high
= (burst_period
*
678 (matching_burst_count
- 1 -
679 match_burst_index
+ 1)) +
680 (2 * LP_TSF_FUZZ_US
);
681 int64_t limit_low
= (burst_period
*
682 (matching_burst_count
- 1 -
683 match_burst_index
)) -
684 (2 * LP_TSF_FUZZ_US
);
685 /* If the burst is too old, skip it... it's noise too... */
686 while ((((int64_t)bursts
[found_burst_index
].lpb_tsf_rel
+
689 if (found_burst_index
< (found_burst_count
- 1))
694 if ((((int64_t)bursts
[found_burst_index
].lpb_tsf_rel
+
697 (((int64_t)bursts
[found_burst_index
].lpb_tsf_rel
+
698 waveform_offset
) >= limit_low
)) {
699 if (-1 == first_matched_index
) {
700 first_matched_index
= match_burst_index
;
703 if (last_matched_index
< match_burst_index
) {
704 last_matched_index
= match_burst_index
;
706 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
707 "LP %2dp] [%2d/%2d] %10lld "
708 "in {%lld:%lld}] PASS\n",
709 matching_burst_count
,
712 (int64_t)bursts
[found_burst_index
].lpb_tsf_rel
-
714 limit_low
, limit_high
);
719 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
720 "LP %2dp] [%2d/%2d] %10lld "
721 "in {%lld:%lld}] MISSED\n",
722 matching_burst_count
,
725 (int64_t)bursts
[found_burst_index
].lpb_tsf_rel
-
727 limit_low
, limit_high
);
731 matched_span
= last_matched_index
- first_matched_index
;
732 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
, "LP %2dp] burst_period=%10d, "
733 "waveform_offset=%10d, matches=%2d/%2d, "
735 matching_burst_count
, burst_period
, waveform_offset
,
736 matched_span
, matching_burst_count
,
737 (matching_burst_count
== matched_span
) ?
740 /* XXX - Add comparison logic rather than taking first/last
741 * match based upon ATH_DEBUG_DOTHFILTNOSC? */
742 if (matched_span
>= (matching_burst_count
- 4)) {
744 best_bc
= matching_burst_count
;
745 best_matched
= matched_bursts
;
746 best_missed
= missed_bursts
;
749 for (i
= 0; i
<= found_burst_index
; i
++) {
750 best_noise
+= bursts
[match_burst_index
].lpb_num_noise
;
751 best_pulses
+= bursts
[match_burst_index
].lpb_num_pulses
;
753 if (!DFLAG_ISSET(sc
, ATH_DEBUG_DOTHFILTNOSC
))
761 *matched
= best_matched
;
763 *missed
= best_missed
;
767 *pulses
= best_pulses
;
769 return found_radar
? AH_TRUE
: AH_FALSE
;
771 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
773 static HAL_BOOL
rp_analyze_short_pulse(
774 struct ath_softc
*sc
, struct ath_rp
*last_pulse
,
775 u_int32_t
*index
, u_int32_t
*pri
, u_int32_t
*matching_pulses
,
776 u_int32_t
*missed_pulses
, u_int32_t
*noise_pulses
)
780 unsigned int best_matched
= 0;
781 unsigned int best_noise
= 0;
782 unsigned int best_missed
= 0;
783 unsigned int best_pri
= 0;
784 unsigned int best_cr
= 0;
786 u_int64_t t0_min
, t0_max
, t1
, t_min
, t_max
;
787 u_int32_t noise
= 0, matched
= 0, missed
= 0, partial_miss
= 0;
788 struct ath_rp
*pulse
;
789 u_int32_t pulse_count_minimum
= 0;
790 struct radar_pattern_specification
*pattern
= NULL
;
791 struct radar_pattern_specification
*best_pattern
= NULL
;
793 u_int32_t new_period
= 0;
794 u_int64_t last_tsf
= 0;
795 u_int32_t last_seen_period
= 0;
796 u_int32_t sum_periods
= 0;
797 u_int32_t mean_period
= 0;
798 u_int32_t adjusted_max_rep_int
= 0;
799 u_int32_t adjusted_min_rep_int
= 0;
808 *matching_pulses
= 0;
812 /* we need at least sc_rp_min (>2 pulses) */
813 pulse_count_minimum
= sc
->sc_rp_min
;
814 if ((sc
->sc_rp_num
< pulse_count_minimum
) ||
820 * - since we have a limited and known number of radar patterns, we
821 * loop on all possible radar pulse period
823 * - we start the search from the last timestamp (t1), going
824 * backward in time, up to the point for the first possible radar
825 * pulse, ie t0_min - PERIOD * BURST_MAX
827 * - on this timescale, we matched the number of hit/missed using T -
828 * PERIOD * n taking into account the 2% error margin (using
829 * min_rep_int, max_rep_int)
831 * At the end, we have a number of pulse hit for each PRF
833 * TSF will roll over after just over 584,542 years of operation
836 * This exceeds all known Atheros MTBF so, forget about TSF roll over.
839 /* t1 is the timestamp of the last radar pulse */
840 t1
= (u_int64_t
)last_pulse
->rp_tsf
;
842 /* loop through all patterns */
843 for (i
= 0; i
< sizetab(radar_patterns
); i
++) {
844 pattern
= &radar_patterns
[i
];
847 if ((pattern
->min_rep_int
*
848 (pattern
->min_evts
- 1)) >= t1
) {
849 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
850 "%s: %s skipped (last pulse isn't old enough to"
851 " match this pattern). %10llu >= %10llu.\n",
852 SC_DEV_NAME(sc
), pattern
->name
,
854 pattern
->min_rep_int
*
860 /* this min formula is to check for underflow. It's the
861 * minimum needed duration to gather specified number of
862 * matches, assuming minimum match interval. */
863 t0_min
= (pattern
->min_rep_int
*
864 pattern
->min_evts
) < t1
?
865 t1
- (pattern
->min_rep_int
*
866 pattern
->min_evts
) : 0;
868 /* this max formula is to stop when we exceed maximum time
869 * period for the pattern. It's the oldest possible TSF that
871 t0_max
= (pattern
->max_rep_int
*
872 pattern
->max_evts
) < t1
?
873 t1
- (pattern
->max_rep_int
*
874 pattern
->max_evts
) : 0;
876 /* we directly start with the timestamp before t1 */
877 pulse
= pulse_prev(last_pulse
);
879 /* initial values for t_min, t_max */
880 t_min
= pattern
->max_rep_int
< t1
?
881 t1
- pattern
->max_rep_int
: 0;
882 t_max
= pattern
->min_rep_int
< t1
?
883 t1
- pattern
->min_rep_int
: 0;
886 last_seen_period
= 0;
893 adjusted_max_rep_int
=
894 pattern
->max_rep_int
;
895 adjusted_min_rep_int
=
896 pattern
->min_rep_int
;
899 if (mean_period
&& pattern
->dyn_ints
) {
900 u_int32_t fuzz_pct
= pattern
->fuzz_pct
;
901 adjusted_max_rep_int
=
902 MIN(nofloat_pct(mean_period
, fuzz_pct
),
903 pattern
->max_rep_int
);
905 adjusted_min_rep_int
=
906 MAX(nofloat_pct(mean_period
, -fuzz_pct
),
907 pattern
->min_rep_int
);
910 adjusted_max_rep_int
= pattern
->max_rep_int
;
911 adjusted_min_rep_int
= pattern
->min_rep_int
;
914 /* check if we are at the end of the list */
915 if (&pulse
->list
== &sc
->sc_rp_list
)
917 if (!pulse
->rp_allocated
)
920 /* Do not go too far... this is an optimization to not
921 * keep checking after we hit maximum time span for the
923 if (pulse
->rp_tsf
< t0_max
) {
924 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
925 "%s: %s matching stopped (pulse->rp_tsf"
926 " < t0_max). t1=%10llu t0_max=%10llu "
927 "t_min=%10llu t_max=%10llu matched=%u "
928 "missed=%u\n", SC_DEV_NAME(sc
),
929 pattern
->name
, t1
, t0_max
,
930 t_min
, t_max
, matched
, missed
);
933 /* if we missed more than specified number of pulses,
934 * we stop searching */
936 pattern
->max_consecutive_missing
) {
937 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
938 "%s: %s matching stopped (too many "
939 "consecutive pulses missing). %d>%d "
940 "matched=%u. missed=%u.\n",
941 SC_DEV_NAME(sc
), pattern
->name
,
943 pattern
->max_consecutive_missing
,
948 new_period
= (u_int64_t
)
949 (last_tsf
&& last_tsf
> pulse
->rp_tsf
) ?
950 last_tsf
- pulse
->rp_tsf
: 0;
951 if (pulse
->rp_tsf
> t_max
) {
952 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
953 "%s: %-17s [%2d] %5s [**:**] tsf: "
954 "%10llu [range: %5llu-%5llu]. width: "
955 "%3d. period: %4llu. last_period: %4llu"
956 ". mean_period: %4llu. last_tsf: %10llu"
962 (u_int64_t
)pulse
->rp_tsf
,
965 (u_int8_t
)pulse
->rp_width
,
966 (u_int64_t
)new_period
,
967 (u_int64_t
)last_seen_period
,
968 (u_int64_t
)mean_period
,
969 (u_int64_t
)last_tsf
);
970 /* this event is noise, ignore it */
971 pulse
= pulse_prev(pulse
);
973 } else if (pulse
->rp_tsf
>= t_min
) {
974 /* we found a match */
977 new_period
/= (partial_miss
+ 1);
978 missed
+= partial_miss
;
980 sum_periods
+= new_period
;
981 mean_period
= matched
?
982 (sum_periods
/ matched
) :
987 pattern
->max_rep_int
||
989 pattern
->min_rep_int
)) {
990 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
991 "%s: %s mean period deviated "
992 "from original range [period: "
993 "%4u, range: %4u-%4u]\n",
997 pattern
->min_rep_int
,
998 pattern
->max_rep_int
);
1002 /* Remember we are scanning backwards... */
1003 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
1004 "%s: %-17s [%2d] %5s [%2d:%-2d] tsf: "
1005 "%10llu [range: %5llu-%5llu]. width: "
1006 "%3d. period: %4llu. last_period: %4llu"
1007 ". mean_period: %4llu. last_tsf: %10llu"
1013 MAX(matched
+ missed
+ partial_miss
- 1,
1015 (matched
+ missed
+ partial_miss
),
1016 (u_int64_t
)pulse
->rp_tsf
,
1019 (u_int8_t
)pulse
->rp_width
,
1020 (u_int64_t
)new_period
,
1021 (u_int64_t
)last_seen_period
,
1022 (u_int64_t
)mean_period
,
1023 (u_int64_t
)last_tsf
);
1025 /* record tsf and period */
1026 last_seen_period
= new_period
;
1027 last_tsf
= pulse
->rp_tsf
;
1029 /* advance to next pulse */
1030 pulse
= pulse_prev(pulse
);
1033 t_min
= adjusted_max_rep_int
< last_tsf
?
1034 last_tsf
- adjusted_max_rep_int
:
1036 t_max
= adjusted_min_rep_int
< last_tsf
?
1037 last_tsf
- adjusted_min_rep_int
:
1041 /* if we missed more than specified number of
1042 * pulses, we stop searching */
1043 if ((missed
+ partial_miss
) >
1044 pattern
->max_missing
) {
1045 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
1046 "%s: %s matching stopped (too "
1047 "many total pulses missing). "
1048 "%d>%d matched=%u. missed=%u."
1053 pattern
->max_missing
,
1058 /* Default mean period to approximate center
1059 * of range. Remember we are scanning
1061 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
1062 "%s: %-17s [**] %5s [%2d:%-2d] tsf: "
1063 "(missing) [range: %5llu-%5llu]. "
1064 "width: ***. period: ****. last_period:"
1065 " %4llu. mean_period: %4llu. last_tsf: "
1070 MAX(matched
+ missed
+ partial_miss
- 1,
1072 (matched
+ missed
+ partial_miss
),
1075 (u_int64_t
)last_seen_period
,
1076 (u_int64_t
)mean_period
,
1077 (u_int64_t
)last_tsf
);
1080 t_min
= adjusted_max_rep_int
< t_min
?
1081 t_min
- adjusted_max_rep_int
:
1083 t_max
= adjusted_min_rep_int
< t_max
?
1084 t_max
- adjusted_min_rep_int
:
1089 /* print counters for this PRF */
1091 int compare_result
= CR_FALLTHROUGH
;
1092 int match_result
= MR_MATCH
;
1093 /* we add one to the matched since we counted only the
1094 * time differences */
1095 /* matched++; not sure... */
1097 /* check if PRF counters match a known radar, if we are
1098 * confident enought */
1099 if (MR_MATCH
== (match_result
= match_radar(
1106 pattern
->min_rep_int
,
1107 pattern
->max_rep_int
,
1109 pattern
->max_missing
))) {
1110 compare_result
= (NULL
== best_pattern
) ? CR_NULL
:
1111 compare_radar_matches(
1118 pattern
->min_rep_int
,
1119 pattern
->max_rep_int
,
1121 pattern
->max_missing
,
1122 pattern
->match_midpoint
,
1127 best_pattern
->min_evts
,
1128 best_pattern
->max_evts
,
1129 best_pattern
->min_rep_int
,
1130 best_pattern
->max_rep_int
,
1131 best_pattern
->min_pulse
,
1132 best_pattern
->max_missing
,
1133 best_pattern
->match_midpoint
);
1135 if (DFLAG_ISSET(sc
, ATH_DEBUG_DOTHFILT
)) {
1136 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1137 "%s: [%02d] %13s: %-17s [match=%2u {%2u"
1138 "..%2u},missed=%2u/%2u,dur=%2d {%2u.."
1139 "%2u},noise=%2u/%2u,cr:%d]\n",
1141 last_pulse
->rp_index
,
1142 compare_result
> CR_FALLTHROUGH
?
1144 get_match_result_desc(match_result
),
1150 pattern
->max_missing
,
1159 if (compare_result
> CR_FALLTHROUGH
) {
1160 best_matched
= matched
;
1161 best_missed
= missed
;
1163 best_pattern
= pattern
;
1164 best_pri
= mean_period
;
1166 best_cr
= compare_result
;
1168 else if (compare_result
<= CR_FALLTHROUGH
) {
1169 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
1170 "%s: %s match not better than best so "
1171 "far. cr: %d matched: %d missed: "
1172 "%d min_evts: %d\n",
1182 if (-1 != best_index
) {
1183 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
1184 "%s: [%02d] %10s: %-17s [match=%2u {%2u..%2u},missed="
1185 "%2u/%2u,dur=%2d {%2u..%2u},noise=%2u/%2u,cr=%2d] "
1186 "RI=%-9u RF=%-4u\n",
1188 last_pulse
->rp_index
,
1192 best_pattern
->min_pulse
,
1193 best_pattern
->max_evts
,
1195 best_pattern
->max_missing
,
1196 (best_matched
+ best_missed
),
1197 best_pattern
->min_evts
,
1198 best_pattern
->max_evts
,
1200 (best_matched
+ best_noise
),
1203 interval_to_frequency(best_pri
));
1205 *index
= best_index
;
1208 if (matching_pulses
)
1209 *matching_pulses
= best_matched
;
1211 *noise_pulses
= best_noise
;
1213 *missed_pulses
= best_missed
;
1216 return (-1 != best_index
) ? AH_TRUE
: AH_FALSE
;
1220 static u_int32_t
interval_to_frequency(u_int32_t interval
)
1222 /* Calculate BRI from PRI */
1223 u_int32_t frequency
= interval
? (1000000 / interval
) : 0;
1224 /* Round to nearest multiple of 50 */
1225 return frequency
+ ((frequency
% 50) >= 25 ? 50 : 0) - (frequency
% 50);
1227 #endif /* AR_DEBUG */
1229 #ifdef ATH_RADAR_LONG_PULSE
1230 static const char *get_longpulse_desc(int lp
)
1233 case 8: return "FCC [5, 8 pulses]";
1234 case 9: return "FCC [5, 9 pulses]";
1235 case 10: return "FCC [5, 10 pulses]";
1236 case 11: return "FCC [5, 11 pulses]";
1237 case 12: return "FCC [5, 12 pulses]";
1238 case 13: return "FCC [5, 13 pulses]";
1239 case 14: return "FCC [5, 14 pulses]";
1240 case 15: return "FCC [5, 15 pulses]";
1241 case 16: return "FCC [5, 16 pulses]";
1242 case 17: return "FCC [5, 17 pulses]";
1243 case 18: return "FCC [5, 18 pulses]";
1244 case 19: return "FCC [5, 19 pulses]";
1245 case 20: return "FCC [5, 20 pulses]";
1246 default: return "FCC [5, invalid pulses]";
1249 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1251 static HAL_BOOL
rp_analyze(struct ath_softc
*sc
)
1254 struct ath_rp
*pulse
;
1256 /* Best short pulse match */
1257 int32_t best_index
= -1;
1258 u_int32_t best_pri
= 0;
1259 u_int32_t best_matched
= 0;
1260 u_int32_t best_missed
= 0;
1261 u_int32_t best_noise
= 0;
1262 int32_t best_cr
= 0;
1264 #ifdef ATH_RADAR_LONG_PULSE
1265 /* Best long pulse match */
1266 u_int32_t best_lp_bc
= 0;
1267 u_int32_t best_lp_matched
= 0;
1268 u_int32_t best_lp_missed
= 0;
1269 u_int32_t best_lp_noise
= 0;
1270 u_int32_t best_lp_pulses
= 0;
1271 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1273 struct radar_pattern_specification
*best_pattern
= NULL
;
1275 /* start the analysis by the last pulse since it might speed up
1276 * things and then move backward for all non-analyzed pulses.
1277 * For debugging ONLY - we continue to run this scan after radar is
1278 * detected, processing all pulses... even when they come in after an
1279 * iteration of all pulses that were present when this function was
1280 * invoked. This can happen at some radar waveforms where we will
1281 * match the first few pulses and then the rest of the burst will come
1282 * in, but never be analyzed.
1285 while (pulse_tail(sc
)->rp_allocated
&&
1286 !pulse_tail(sc
)->rp_analyzed
&&
1287 (AH_FALSE
== radar
||
1288 (DFLAG_ISSET(sc
, ATH_DEBUG_DOTHFILT
) && ++pass
<= 3))) {
1290 list_for_each_entry_reverse(pulse
, &sc
->sc_rp_list
, list
) {
1291 if (!pulse
->rp_allocated
)
1293 if (pulse
->rp_analyzed
)
1296 /* Skip pulse analysis after we have confirmed radar
1297 * presence unless we are debugging and have
1298 * disabled short-circuit logic. In this case,
1299 * we'll go through ALL the signatures and find
1300 * the best match to convince ourselves this code works.
1302 if (AH_FALSE
== radar
||
1303 DFLAG_ISSET(sc
, ATH_DEBUG_DOTHFILTNOSC
)) {
1304 /* short pulse match status */
1305 u_int32_t index
= 0;
1307 u_int32_t matched
= 0;
1308 u_int32_t missed
= 0;
1309 u_int32_t noise
= 0;
1310 #ifdef ATH_RADAR_LONG_PULSE
1312 /* long pulse match status */
1313 u_int32_t lp_bc
= 0;
1314 u_int32_t lp_matched
= 0;
1315 u_int32_t lp_missed
= 0;
1316 u_int32_t lp_noise
= 0;
1317 u_int32_t lp_pulses
= 0;
1318 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1319 if (rp_analyze_short_pulse(sc
, pulse
, &index
,
1320 &pri
, &matched
, &missed
,
1322 int compare_result
= (!radar
|| best_index
== -1) ?
1324 compare_radar_matches(
1329 radar_patterns
[index
].min_evts
,
1330 radar_patterns
[index
].max_evts
,
1331 radar_patterns
[index
].min_rep_int
,
1332 radar_patterns
[index
].max_rep_int
,
1333 radar_patterns
[index
].min_pulse
,
1334 radar_patterns
[index
].max_missing
,
1335 radar_patterns
[index
].match_midpoint
,
1340 radar_patterns
[best_index
].min_evts
,
1341 radar_patterns
[best_index
].max_evts
,
1342 radar_patterns
[best_index
].min_rep_int
,
1343 radar_patterns
[best_index
].max_rep_int
,
1344 radar_patterns
[best_index
].min_pulse
,
1345 radar_patterns
[best_index
].max_missing
,
1346 radar_patterns
[best_index
].match_midpoint
1348 if (compare_result
> CR_FALLTHROUGH
) {
1349 /* Update best match */
1350 best_matched
= matched
;
1351 best_missed
= missed
;
1356 best_cr
= compare_result
;
1358 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1359 "%s: %10s: %-17s [match=%2u "
1360 "{%2u..%2u}, missed=%2u/%2u, "
1361 "dur=%2d {%2u..%2u}, "
1362 "noise=%2u/%2u, cr=%2d] "
1363 "RI=%-9u RF=%-4u\n",
1364 DEV_NAME(sc
->sc_dev
),
1365 (compare_result
> CR_FALLTHROUGH
) ?
1367 radar_patterns
[index
].name
,
1369 radar_patterns
[index
].min_pulse
,
1370 radar_patterns
[index
].max_evts
,
1372 radar_patterns
[index
].max_missing
,
1374 radar_patterns
[index
].min_evts
,
1375 radar_patterns
[index
].max_evts
,
1380 interval_to_frequency(pri
));
1382 #ifdef ATH_RADAR_LONG_PULSE
1383 if (rp_analyze_long_pulse(sc
, pulse
,
1389 /* XXX: Do we care about best match?? */
1392 best_lp_matched
= lp_matched
;
1393 best_lp_missed
= lp_missed
;
1394 best_lp_noise
= lp_noise
;
1395 best_lp_pulses
= lp_pulses
;
1397 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1399 pulse
->rp_analyzed
= 1;
1402 if (AH_TRUE
== radar
) {
1403 #ifdef ATH_RADAR_LONG_PULSE
1405 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1407 &radar_patterns
[best_index
];
1408 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1409 "%s: %10s: %-17s [match=%2u {%2u..%2u},missed="
1410 "%2u/%2u,dur=%2d {%2u..%2u},noise=%2u/%2u,cr=%2d] "
1411 "RI=%-9u RF=%-4u\n",
1412 DEV_NAME(sc
->sc_dev
),
1416 best_pattern
->min_pulse
,
1417 best_pattern
->max_evts
,
1419 best_pattern
->max_missing
,
1420 (best_matched
+ best_missed
),
1421 best_pattern
->min_evts
,
1422 best_pattern
->max_evts
,
1424 (best_matched
+ best_noise
),
1427 interval_to_frequency(best_pri
));
1428 #ifdef ATH_RADAR_LONG_PULSE
1431 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1432 "%s: %10s: %-17s [match=%2u {%2u..%2u},missed="
1433 "%2u/%2u,noise=%2u/%2u]\n",
1434 DEV_NAME(sc
->sc_dev
),
1436 get_longpulse_desc(best_lp_bc
),
1441 (best_lp_bc
-(best_lp_bc
-4)),
1443 (best_lp_pulses
+ best_lp_noise
)
1446 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1447 if (DFLAG_ISSET(sc
, ATH_DEBUG_DOTHFILT
)) {
1448 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1449 "%s: ========================================\n",
1450 DEV_NAME(sc
->sc_dev
));
1451 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1452 "%s: ==BEGIN RADAR SAMPLE====================\n",
1453 DEV_NAME(sc
->sc_dev
));
1454 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1455 "%s: ========================================\n",
1456 DEV_NAME(sc
->sc_dev
));
1458 #ifdef ATH_RADAR_LONG_PULSE
1460 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1462 &radar_patterns
[best_index
];
1463 DPRINTF(sc
, ATH_DEBUG_DOTHPULSES
,
1464 "%s: Sample contains data matching %s "
1465 "[match=%2u {%2u..%2u}, "
1466 "missed=%2u/%2u, dur=%2d {%2u..%2u}, "
1467 "noise=%2u/%2u,cr=%d] RI=%-9u RF=%-4u\n",
1468 DEV_NAME(sc
->sc_dev
),
1471 best_pattern
->min_pulse
,
1472 best_pattern
->max_evts
,
1474 best_pattern
->max_missing
,
1475 best_matched
+ best_missed
,
1476 best_pattern
->min_evts
,
1477 best_pattern
->max_evts
,
1479 best_noise
+ best_matched
,
1482 interval_to_frequency(best_pri
));
1483 #ifdef ATH_RADAR_LONG_PULSE
1485 DPRINTF(sc
, ATH_DEBUG_DOTHPULSES
,
1486 "%s: Sample contains data matching %s\n",
1487 DEV_NAME(sc
->sc_dev
),
1488 get_longpulse_desc(best_lp_bc
));
1490 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1492 ath_rp_print(sc
, 0 /* analyzed pulses only */ );
1493 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1494 "%s: ========================================\n",
1495 DEV_NAME(sc
->sc_dev
));
1496 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1497 "%s: ==END RADAR SAMPLE======================\n",
1498 DEV_NAME(sc
->sc_dev
));
1499 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1500 "%s: ========================================\n",
1501 DEV_NAME(sc
->sc_dev
));
1503 #ifdef ATH_RADAR_LONG_PULSE
1505 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1506 ath_radar_detected(sc
, radar_patterns
[best_index
].name
);
1507 #ifdef ATH_RADAR_LONG_PULSE
1509 ath_radar_detected(sc
, get_longpulse_desc(best_lp_bc
));
1510 #endif /* #ifdef ATH_RADAR_LONG_PULSE */
1515 /* initialize ath_softc members so sensible values */
1516 static void ath_rp_clear(struct ath_softc
*sc
)
1519 INIT_LIST_HEAD(&sc
->sc_rp_list
);
1521 sc
->sc_rp_analyze
= NULL
;
1524 static void ath_rp_tasklet(TQUEUE_ARG data
)
1526 struct net_device
*dev
= (struct net_device
*)data
;
1527 struct ath_softc
*sc
= dev
->priv
;
1529 if (sc
->sc_rp_analyze
!= NULL
)
1530 sc
->sc_rp_analyze(sc
);
1533 void ath_rp_init(struct ath_softc
*sc
)
1535 struct net_device
*dev
= sc
->sc_dev
;
1540 sc
->sc_rp
= (struct ath_rp
*)kzalloc(
1541 sizeof(struct ath_rp
) *
1542 ATH_RADAR_PULSE_NR
, GFP_KERNEL
);
1544 if (sc
->sc_rp
== NULL
)
1547 /* initialize the circular list */
1548 INIT_LIST_HEAD(&sc
->sc_rp_list
);
1549 for (i
= 0; i
< ATH_RADAR_PULSE_NR
; i
++) {
1550 sc
->sc_rp
[i
].rp_index
= i
;
1551 list_add_tail(&sc
->sc_rp
[i
].list
,
1556 sc
->sc_rp_analyze
= rp_analyze
;
1558 /* compute sc_rp_min */
1560 for (i
= 0; i
< sizetab(radar_patterns
); i
++)
1563 radar_patterns
[i
].min_pulse
);
1565 /* default values is properly handle pulses and detected radars */
1566 sc
->sc_rp_ignored
= 0;
1567 sc
->sc_radar_ignored
= 0;
1569 ATH_INIT_TQUEUE(&sc
->sc_rp_tq
, ath_rp_tasklet
, dev
);
1572 void ath_rp_done(struct ath_softc
*sc
)
1574 /* free what we allocated in ath_rp_init() */
1580 void ath_rp_record(struct ath_softc
*sc
, u_int64_t tsf
, u_int8_t rssi
,
1581 u_int8_t width
, HAL_BOOL is_simulated
)
1583 struct ath_rp
*pulse
;
1585 DPRINTF(sc
, ATH_DEBUG_DOTHPULSES
, "%s: ath_rp_record: "
1586 "tsf=%10llu rssi=%3u width=%3u%s\n",
1587 SC_DEV_NAME(sc
), tsf
, rssi
, width
,
1588 sc
->sc_rp_ignored
? " (ignored)" : "");
1590 if (sc
->sc_rp_ignored
) {
1594 /* pulses width 255 seems to trigger false detection of radar. we
1595 * ignored it then. */
1602 /* check if the new radar pulse is after the last one recorded, or
1603 * else, we flush the history */
1604 pulse
= pulse_tail(sc
);
1605 if (tsf
< pulse
->rp_tsf
) {
1606 if (is_simulated
== AH_TRUE
&& 0 == tsf
) {
1607 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
1608 "%s: %s: ath_rp_flush: simulated tsf "
1609 "reset. tsf =%10llu, rptsf =%10llu\n",
1610 SC_DEV_NAME(sc
), __func__
, tsf
, pulse
->rp_tsf
);
1612 } else if ((pulse
->rp_tsf
- tsf
) > (1 << 15)) {
1613 DPRINTF(sc
, ATH_DEBUG_DOTHFILTVBSE
,
1614 "%s: %s: ath_rp_flush: tsf reset. "
1615 "(rp_tsf - tsf > 0x8000) tsf=%10llu, rptsf="
1617 SC_DEV_NAME(sc
), __func__
, tsf
, pulse
->rp_tsf
);
1620 DPRINTF(sc
, ATH_DEBUG_DOTHFILT
,
1621 "%s: %s: tsf jitter/bug detected: tsf =%10llu, "
1622 "rptsf =%10llu, rp_tsf - tsf = %10llu\n",
1623 SC_DEV_NAME(sc
), __func__
, tsf
, pulse
->rp_tsf
,
1624 pulse
->rp_tsf
- tsf
);
1628 /* remove the head of the list */
1629 pulse
= pulse_head(sc
);
1630 list_del(&pulse
->list
);
1632 pulse
->rp_tsf
= tsf
;
1633 pulse
->rp_rssi
= rssi
;
1634 pulse
->rp_width
= width
;
1635 pulse
->rp_allocated
= 1;
1636 pulse
->rp_analyzed
= 0;
1638 /* add at the tail of the list */
1639 list_add_tail(&pulse
->list
, &sc
->sc_rp_list
);
1640 if (ATH_RADAR_PULSE_NR
> sc
->sc_rp_num
)
1644 void ath_rp_print_mem(struct ath_softc
*sc
, int analyzed_pulses_only
)
1646 struct ath_rp
*pulse
;
1647 u_int64_t oldest_tsf
= ~0;
1649 IPRINTF(sc
, "Pulse dump of %spulses using sc_rp containing "
1650 "%d allocated pulses.\n",
1651 analyzed_pulses_only
? "analyzed " : "", sc
->sc_rp_num
);
1653 /* Find oldest TSF value so we can print relative times */
1654 for (i
= 0; i
< ATH_RADAR_PULSE_NR
; i
++) {
1655 pulse
= &sc
->sc_rp
[i
];
1656 if (pulse
->rp_allocated
&& pulse
->rp_tsf
< oldest_tsf
)
1657 oldest_tsf
= pulse
->rp_tsf
;
1660 for (i
= 0; i
< ATH_RADAR_PULSE_NR
; i
++) {
1661 pulse
= &sc
->sc_rp
[i
];
1662 if (!pulse
->rp_allocated
)
1664 if ((!analyzed_pulses_only
) || pulse
->rp_analyzed
)
1665 IPRINTF(sc
, "Pulse [%3d, %p] : relative_tsf=%10llu "
1666 "tsf=%10llu rssi=%3u width=%3u allocated=%d "
1667 "analyzed=%d next=%p prev=%p\n",
1670 pulse
->rp_tsf
- oldest_tsf
,
1674 pulse
->rp_allocated
,
1681 void ath_rp_print(struct ath_softc
*sc
, int analyzed_pulses_only
)
1683 struct ath_rp
*pulse
;
1684 u_int64_t oldest_tsf
= ~0;
1686 IPRINTF(sc
, "Pulse dump of %spulses from ring buffer containing %d "
1688 analyzed_pulses_only
? "analyzed " : "",
1691 /* Find oldest TSF value so we can print relative times */
1693 list_for_each_entry_reverse(pulse
, &sc
->sc_rp_list
, list
)
1694 if (pulse
->rp_allocated
&& pulse
->rp_tsf
< oldest_tsf
)
1695 oldest_tsf
= pulse
->rp_tsf
;
1697 list_for_each_entry_reverse(pulse
, &sc
->sc_rp_list
, list
) {
1698 if (!pulse
->rp_allocated
)
1700 if ((!analyzed_pulses_only
) || pulse
->rp_analyzed
)
1701 IPRINTF(sc
, "Pulse [%3d, %p] : relative_tsf=%10llu "
1702 "tsf=%10llu rssi=%3u width=%3u allocated=%d "
1703 "analyzed=%d next=%p prev=%p\n",
1706 pulse
->rp_tsf
- oldest_tsf
,
1710 pulse
->rp_allocated
,
1717 void ath_rp_flush(struct ath_softc
*sc
)
1719 struct ath_rp
*pulse
;
1720 list_for_each_entry_reverse(pulse
, &sc
->sc_rp_list
, list
)
1721 pulse
->rp_allocated
= 0;