FreeBSD kernel ATH device code
ar5416_radar.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (c) 2010-2011 Atheros Communications, Inc.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $FreeBSD$
19 */
20#include "opt_ah.h"
21
22#include "ah.h"
23#include "ah_internal.h"
24#include "ah_devid.h"
25#include "ah_desc.h" /* NB: for HAL_PHYERR* */
26
27#include "ar5416/ar5416.h"
28#include "ar5416/ar5416reg.h"
29#include "ar5416/ar5416phy.h"
30
31#include "ah_eeprom_v14.h" /* for owl_get_ntxchains() */
32
33/*
34 * These are default parameters for the AR5416 and
35 * later 802.11n NICs. They simply enable some
36 * radar pulse event generation.
37 *
38 * These are very likely not valid for the AR5212 era
39 * NICs.
40 *
41 * Since these define signal sizing and threshold
42 * parameters, they may need changing based on the
43 * specific antenna and receive amplifier
44 * configuration.
45 */
46#define AR5416_DFS_FIRPWR -33
47#define AR5416_DFS_RRSSI 20
48#define AR5416_DFS_HEIGHT 10
49#define AR5416_DFS_PRSSI 15
50#define AR5416_DFS_INBAND 15
51#define AR5416_DFS_RELPWR 8
52#define AR5416_DFS_RELSTEP 12
53#define AR5416_DFS_MAXLEN 255
54
57{
58
59 /*
60 * These are general examples of the parameter values
61 * to use when configuring radar pulse detection for
62 * the AR5416, AR91xx, AR92xx NICs. They are only
63 * for testing and do require tuning depending upon the
64 * hardware and deployment specifics.
65 */
74
75 return (AH_TRUE);
76}
77
78/*
79 * Get the radar parameter values and return them in the pe
80 * structure
81 */
82void
84{
85 uint32_t val, temp;
86
87 val = OS_REG_READ(ah, AR_PHY_RADAR_0);
88
89 temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
90 temp |= 0xFFFFFF80;
91 pe->pe_firpwr = temp;
96
97 /* RADAR_1 values */
98 val = OS_REG_READ(ah, AR_PHY_RADAR_1);
102
105
112 pe->pe_enabled = !!
114 pe->pe_enrelpwr = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
118}
119
120/*
121 * Enable radar detection and set the radar parameters per the
122 * values in pe
123 */
124void
126{
127 uint32_t val;
128
129 val = OS_REG_READ(ah, AR_PHY_RADAR_0);
130
132 val &= ~AR_PHY_RADAR_0_FIRPWR;
134 }
135 if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
136 val &= ~AR_PHY_RADAR_0_RRSSI;
137 val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
138 }
140 val &= ~AR_PHY_RADAR_0_HEIGHT;
142 }
143 if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
144 val &= ~AR_PHY_RADAR_0_PRSSI;
145 val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
146 }
148 val &= ~AR_PHY_RADAR_0_INBAND;
150 }
151
152 /*Enable FFT data*/
155
156 /* Implicitly enable */
157 if (pe->pe_enabled == 1)
159 else if (pe->pe_enabled == 0)
161
162 if (pe->pe_usefir128 == 1)
164 else if (pe->pe_usefir128 == 0)
166
167 if (pe->pe_enmaxrssi == 1)
169 else if (pe->pe_enmaxrssi == 0)
171
172 if (pe->pe_blockradar == 1)
174 else if (pe->pe_blockradar == 0)
176
178 val = OS_REG_READ(ah, AR_PHY_RADAR_1);
179 val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
182 }
184 val = OS_REG_READ(ah, AR_PHY_RADAR_1);
185 val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
188 }
189
190 if (pe->pe_en_relstep_check == 1)
193 else if (pe->pe_en_relstep_check == 0)
196
197 if (pe->pe_enrelpwr == 1)
200 else if (pe->pe_enrelpwr == 0)
203
205 val = OS_REG_READ(ah, AR_PHY_RADAR_1);
206 val &= ~AR_PHY_RADAR_1_MAXLEN;
209 }
210
211 /*
212 * Enable HT/40 if the upper layer asks;
213 * it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS
214 * is available.
215 */
216 if (pe->pe_extchannel == 1)
218 else if (pe->pe_extchannel == 0)
220}
221
222/*
223 * Extract the radar event information from the given phy error.
224 *
225 * Returns AH_TRUE if the phy error was actually a phy error,
226 * AH_FALSE if the phy error wasn't a phy error.
227 */
228
229/* Flags for pulse_bw_info */
230#define PRI_CH_RADAR_FOUND 0x01
231#define EXT_CH_RADAR_FOUND 0x02
232#define EXT_CH_RADAR_EARLY_FOUND 0x04
233
236 uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
237{
238 HAL_BOOL doDfsExtCh;
239 HAL_BOOL doDfsEnhanced;
240 HAL_BOOL doDfsCombinedRssi;
241
242 uint8_t rssi = 0, ext_rssi = 0;
243 uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0;
244 uint32_t dur = 0;
245 int pri_found = 1, ext_found = 0;
246 int early_ext = 0;
247 int is_dc = 0;
248 uint16_t datalen; /* length from the RX status field */
249
250 /* Check whether the given phy error is a radar event */
251 if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&
253 return AH_FALSE;
254 }
255
256 /* Grab copies of the capabilities; just to make the code clearer */
257 doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport;
258 doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport;
259 doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi;
260
261 datalen = rxs->rs_datalen;
262
263 /* If hardware supports it, use combined RSSI, else use chain 0 RSSI */
264 if (doDfsCombinedRssi)
265 rssi = (uint8_t) rxs->rs_rssi;
266 else
267 rssi = (uint8_t) rxs->rs_rssi_ctl[0];
268
269 /* Set this; but only use it if doDfsExtCh is set */
270 ext_rssi = (uint8_t) rxs->rs_rssi_ext[0];
271
272 /* Cap it at 0 if the RSSI is a negative number */
273 if (rssi & 0x80)
274 rssi = 0;
275
276 if (ext_rssi & 0x80)
277 ext_rssi = 0;
278
279 /*
280 * Fetch the relevant data from the frame
281 */
282 if (doDfsExtCh) {
283 if (datalen < 3)
284 return AH_FALSE;
285
286 /* Last three bytes of the frame are of interest */
287 pulse_length_pri = *(buf + datalen - 3);
288 pulse_length_ext = *(buf + datalen - 2);
289 pulse_bw_info = *(buf + datalen - 1);
290 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d,"
291 " pulse_length_ext=%d, pulse_bw_info=%x\n",
292 __func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext,
293 pulse_bw_info);
294 } else {
295 /* The pulse width is byte 0 of the data */
296 if (datalen >= 1)
297 dur = ((uint8_t) buf[0]) & 0xff;
298 else
299 dur = 0;
300
301 if (dur == 0 && rssi == 0) {
302 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__);
303 return AH_FALSE;
304 }
305
306 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur);
307
308 /* Single-channel only */
309 pri_found = 1;
310 ext_found = 0;
311 }
312
313 /*
314 * If doing extended channel data, pulse_bw_info must
315 * have one of the flags set.
316 */
317 if (doDfsExtCh && pulse_bw_info == 0x0)
318 return AH_FALSE;
319
320 /*
321 * If the extended channel data is available, calculate
322 * which to pay attention to.
323 */
324 if (doDfsExtCh) {
325 /* If pulse is on DC, take the larger duration of the two */
326 if ((pulse_bw_info & EXT_CH_RADAR_FOUND) &&
327 (pulse_bw_info & PRI_CH_RADAR_FOUND)) {
328 is_dc = 1;
329 if (pulse_length_ext > pulse_length_pri) {
330 dur = pulse_length_ext;
331 pri_found = 0;
332 ext_found = 1;
333 } else {
334 dur = pulse_length_pri;
335 pri_found = 1;
336 ext_found = 0;
337 }
338 } else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) {
339 dur = pulse_length_ext;
340 pri_found = 0;
341 ext_found = 1;
342 early_ext = 1;
343 } else if (pulse_bw_info & PRI_CH_RADAR_FOUND) {
344 dur = pulse_length_pri;
345 pri_found = 1;
346 ext_found = 0;
347 } else if (pulse_bw_info & EXT_CH_RADAR_FOUND) {
348 dur = pulse_length_ext;
349 pri_found = 0;
350 ext_found = 1;
351 }
352
353 }
354
355 /*
356 * For enhanced DFS (Merlin and later), pulse_bw_info has
357 * implications for selecting the correct RSSI value.
358 */
359 if (doDfsEnhanced) {
360 switch (pulse_bw_info & 0x03) {
361 case 0:
362 /* No radar? */
363 rssi = 0;
364 break;
366 /* Radar in primary channel */
367 /* Cannot use ctrl channel RSSI if ext channel is stronger */
368 if (ext_rssi >= (rssi + 3)) {
369 rssi = 0;
370 }
371 break;
373 /* Radar in extended channel */
374 /* Cannot use ext channel RSSI if ctrl channel is stronger */
375 if (rssi >= (ext_rssi + 12)) {
376 rssi = 0;
377 } else {
378 rssi = ext_rssi;
379 }
380 break;
382 /* When both are present, use stronger one */
383 if (rssi < ext_rssi)
384 rssi = ext_rssi;
385 break;
386 }
387 }
388
389 /*
390 * If not doing enhanced DFS, choose the ext channel if
391 * it is stronger than the main channel
392 */
393 if (doDfsExtCh && !doDfsEnhanced) {
394 if ((ext_rssi > rssi) && (ext_rssi < 128))
395 rssi = ext_rssi;
396 }
397
398 /*
399 * XXX what happens if the above code decides the RSSI
400 * XXX wasn't valid, an sets it to 0?
401 */
402
403 /*
404 * Fill out dfs_event structure.
405 */
406 event->re_full_ts = fulltsf;
407 event->re_ts = rxs->rs_tstamp;
408 event->re_rssi = rssi;
409 event->re_dur = dur;
410
411 event->re_flags = 0;
412 if (pri_found)
413 event->re_flags |= HAL_DFS_EVENT_PRICH;
414 if (ext_found)
415 event->re_flags |= HAL_DFS_EVENT_EXTCH;
416 if (early_ext)
417 event->re_flags |= HAL_DFS_EVENT_EXTEARLY;
418 if (is_dc)
419 event->re_flags |= HAL_DFS_EVENT_ISDC;
420
421 return AH_TRUE;
422}
423
424/*
425 * Return whether fast-clock is currently enabled for this
426 * channel.
427 */
430{
431 struct ath_hal_private *ahp = AH_PRIVATE(ah);
432
433 return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan);
434}
#define HAL_PHYERR_PARAM_NOVAL
Definition: ah.h:1027
#define HAL_DFS_EVENT_ISDC
Definition: ah.h:1100
#define HAL_DFS_EVENT_PRICH
Definition: ah.h:1097
#define HAL_DFS_EVENT_EXTEARLY
Definition: ah.h:1099
#define HAL_DFS_EVENT_EXTCH
Definition: ah.h:1098
HAL_BOOL
Definition: ah.h:93
@ AH_FALSE
Definition: ah.h:94
@ AH_TRUE
Definition: ah.h:95
@ HAL_DEBUG_DFS
Definition: ah_debug.h:50
@ HAL_PHYERR_RADAR
Definition: ah_desc.h:185
@ HAL_PHYERR_FALSE_RADAR_EXT
Definition: ah_desc.h:196
#define OS_REG_SET_BIT(_a, _r, _f)
Definition: ah_internal.h:594
#define SM(_v, _f)
Definition: ah_internal.h:587
#define MS(_v, _f)
Definition: ah_internal.h:588
#define OS_REG_CLR_BIT(_a, _r, _f)
Definition: ah_internal.h:596
#define AH_PRIVATE(_ah)
Definition: ah_internal.h:442
#define IS_5GHZ_FAST_CLOCK_EN(_ah, _c)
Definition: ah_internal.h:996
#define HALDEBUG(_ah, __m,...)
Definition: ah_internal.h:658
#define OS_REG_WRITE(_ah, _reg, _val)
Definition: ah_osdep.h:139
#define OS_REG_READ(_ah, _reg)
Definition: ah_osdep.h:140
#define AR_PHY_RADAR_0
Definition: ar5211phy.h:81
#define AR_PHY_RADAR_0_ENA
Definition: ar5211phy.h:82
#define AR_PHY_RADAR_0_INBAND
Definition: ar5212phy.h:214
#define AR_PHY_RADAR_0_PRSSI
Definition: ar5212phy.h:216
#define AR_PHY_RADAR_0_HEIGHT
Definition: ar5212phy.h:218
#define AR_PHY_RADAR_0_RRSSI
Definition: ar5212phy.h:220
#define AR_PHY_RADAR_0_FIRPWR
Definition: ar5212phy.h:222
#define AR5416_DFS_HEIGHT
Definition: ar5416_radar.c:48
#define PRI_CH_RADAR_FOUND
Definition: ar5416_radar.c:230
#define EXT_CH_RADAR_FOUND
Definition: ar5416_radar.c:231
#define AR5416_DFS_RRSSI
Definition: ar5416_radar.c:47
#define AR5416_DFS_RELSTEP
Definition: ar5416_radar.c:52
#define EXT_CH_RADAR_EARLY_FOUND
Definition: ar5416_radar.c:232
#define AR5416_DFS_INBAND
Definition: ar5416_radar.c:50
#define AR5416_DFS_RELPWR
Definition: ar5416_radar.c:51
void ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
Definition: ar5416_radar.c:125
HAL_BOOL ar5416GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
Definition: ar5416_radar.c:56
void ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
Definition: ar5416_radar.c:83
HAL_BOOL ar5416IsFastClockEnabled(struct ath_hal *ah)
Definition: ar5416_radar.c:429
#define AR5416_DFS_PRSSI
Definition: ar5416_radar.c:49
#define AR5416_DFS_FIRPWR
Definition: ar5416_radar.c:46
#define AR5416_DFS_MAXLEN
Definition: ar5416_radar.c:53
HAL_BOOL ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
Definition: ar5416_radar.c:235
#define AR_PHY_RADAR_EXT
Definition: ar5416phy.h:96
#define AR_PHY_RADAR_1_RELSTEP_CHECK
Definition: ar5416phy.h:108
#define AR_PHY_RADAR_0_FFT_ENA
Definition: ar5416phy.h:94
#define AR_PHY_RADAR_1_RELPWR_THRESH
Definition: ar5416phy.h:104
#define AR_PHY_RADAR_1_RELPWR_ENA
Definition: ar5416phy.h:102
#define AR_PHY_RADAR_1
Definition: ar5416phy.h:99
#define AR_PHY_RADAR_1_USE_FIR128
Definition: ar5416phy.h:103
#define AR_PHY_RADAR_1_BLOCK_CHECK
Definition: ar5416phy.h:106
#define AR_PHY_RADAR_1_MAX_RRSSI
Definition: ar5416phy.h:107
#define AR_PHY_RADAR_EXT_ENA
Definition: ar5416phy.h:97
#define AR_PHY_RADAR_1_RELSTEP_THRESH
Definition: ar5416phy.h:109
#define AR_PHY_RADAR_1_MAXLEN
Definition: ar5416phy.h:111
int32_t pe_extchannel
Definition: ah.h:1021
int32_t pe_en_relstep_check
Definition: ah.h:1024
u_int32_t pe_relpwr
Definition: ah.h:1008
int32_t pe_height
Definition: ah.h:1003
int32_t pe_blockradar
Definition: ah.h:1012
int32_t pe_usefir128
Definition: ah.h:1011
u_int32_t pe_maxlen
Definition: ah.h:1010
u_int32_t pe_relstep
Definition: ah.h:1009
int32_t pe_enrelpwr
Definition: ah.h:1023
int32_t pe_enmaxrssi
Definition: ah.h:1017
int32_t pe_prssi
Definition: ah.h:1004
int32_t pe_firpwr
Definition: ah.h:1001
int32_t pe_rrssi
Definition: ah.h:1002
int32_t pe_inband
Definition: ah.h:1005
int32_t pe_enabled
Definition: ah.h:1022
const struct ieee80211_channel * ah_curchan
Definition: ah_internal.h:401
Definition: ah.h:1219
int8_t rs_rssi_ext[3]
Definition: ah_desc.h:111
uint16_t rs_datalen
Definition: ah_desc.h:100
uint8_t rs_phyerr
Definition: ah_desc.h:102
int8_t rs_rssi_ctl[3]
Definition: ah_desc.h:110
int8_t rs_rssi
Definition: ah_desc.h:103
uint32_t rs_tstamp
Definition: ah_desc.h:107