/* * Parse the radar summary frame. * * The frame contents _minus_ the TLV are passed in. */ static void radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len, struct rx_radar_status *rsu) { uint32_t rs[2]; /* Drop out if we have < 2 DWORDs available */ if (len < sizeof(rs)) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | ATH_DEBUG_DFS_PHYERR_SUM, "%s: len (%d) < expected (%d)!\n", __func__, len, sizeof(rs)); } /* * Since the TLVs may be unaligned for some reason * we take a private copy into aligned memory. * This enables us to use the HAL-like accessor macros * into the DWORDs to access sub-DWORD fields. */ OS_MEMCPY(rs, buf, sizeof(rs)); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: two 32 bit values are: %08x %08x\n", __func__, rs[0], rs[1]); // DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s (p=%p):\n", __func__, buf); /* Populate the fields from the summary report */ rsu->tsf_offset = MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_TSF_OFFSET); rsu->pulse_duration = MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_DUR); rsu->is_chirp = MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_IS_CHIRP); rsu->sidx = sign_extend_32( MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_SIDX), 10); rsu->freq_offset = calc_freq_offset(rsu->sidx, PERE_IS_OVERSAMPLING(dfs)); /* These are only relevant if the pulse is a chirp */ rsu->delta_peak = sign_extend_32( MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_PEAK), 6); rsu->delta_diff = MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_DIFF); }
static void radar_summary_print(struct ath_dfs *dfs, struct rx_radar_status *rsu) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " pulsedur=%d\n", rsu->pulse_duration); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " rssi=%d\n", rsu->rssi); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " ischirp=%d\n", rsu->is_chirp); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " sidx=%d\n", rsu->sidx); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " raw tsf=%d\n", rsu->raw_tsf); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " tsf_offset=%d\n", rsu->tsf_offset); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " cooked tsf=%d\n", rsu->raw_tsf - rsu->tsf_offset); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " frequency offset=%d.%d MHz (oversampling=%d)\n", (int) (rsu->freq_offset / 1000), (int) abs(rsu->freq_offset % 1000), PERE_IS_OVERSAMPLING(dfs)); }
/* * Calculate the centre frequency and low/high range for a radar pulse event. * * XXX TODO: Handle half/quarter rates correctly! * XXX TODO: handle VHT160 correctly! * XXX TODO: handle VHT80+80 correctly! */ static int tlv_calc_event_freq_pulse(struct ath_dfs *dfs, struct rx_radar_status *rs, uint32_t *freq_centre, uint32_t *freq_lo, uint32_t *freq_hi) { int chan_width; int chan_centre; /* Fetch the channel centre frequency in MHz */ chan_centre = tlv_calc_freq_info(dfs, rs); /* Convert to KHz */ chan_centre *= 1000; /* * XXX hard-code event width to be 2 * bin size for now; * XXX this needs to take into account the core clock speed * XXX for half/quarter rate mode. */ if (PERE_IS_OVERSAMPLING(dfs)) chan_width = (44000 * 2 / 128); else chan_width = (40000 * 2 / 128); /* XXX adjust chan_width for half/quarter rate! */ /* * Now we can do the math to figure out the correct channel range. */ (*freq_centre) = (uint32_t) (chan_centre + rs->freq_offset); (*freq_lo) = (uint32_t) ((chan_centre + rs->freq_offset) - chan_width); (*freq_hi) = (uint32_t) ((chan_centre + rs->freq_offset) + chan_width); return (1); }
/* * The chirp bandwidth in KHz is defined as: * * totalBW(KHz) = delta_peak(mean) * * [ (bin resolution in KHz) / (radar_fft_long_period in uS) ] * * pulse_duration (us) * * The bin resolution depends upon oversampling. * * For now, we treat the radar_fft_long_period as a hard-coded 8uS. */ static int tlv_calc_event_freq_chirp(struct ath_dfs *dfs, struct rx_radar_status *rs, uint32_t *freq_centre, uint32_t *freq_lo, uint32_t *freq_hi) { int32_t bin_resolution; /* KHz * 100 */ int32_t radar_fft_long_period = 8; /* microseconds */ int32_t delta_peak; int32_t pulse_duration; int32_t total_bw; int32_t chan_centre; int32_t freq_1, freq_2; /* * KHz isn't enough resolution here! * So treat it as deci-hertz (10Hz) and convert back to KHz * later. */ if (PERE_IS_OVERSAMPLING(dfs)) bin_resolution = (44000 * 100) / 128; else bin_resolution = (40000 * 100) / 128; delta_peak = rs->delta_peak; pulse_duration = rs->pulse_duration; total_bw = delta_peak * (bin_resolution / radar_fft_long_period) * pulse_duration; DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | ATH_DEBUG_DFS_PHYERR_SUM, "%s: delta_peak=%d, pulse_duration=%d, bin_resolution=%d.%dKHz, " "radar_fft_long_period=%d, total_bw=%d.%dKHz\n", __func__, delta_peak, pulse_duration, bin_resolution / 1000, bin_resolution % 1000, radar_fft_long_period, total_bw / 100, abs(total_bw % 100)); total_bw /= 100; /* back to KHz */ /* Grab the channel centre frequency in MHz */ chan_centre = tlv_calc_freq_info(dfs, rs); /* Early abort! */ if (chan_centre == 0) { (*freq_centre) = 0; return (0); } /* Convert to KHz */ chan_centre *= 1000; /* * sidx is the starting frequency; total_bw is a signed value and * for negative chirps (ie, moving down in frequency rather than up) * the end frequency may be less than the start frequency. */ if (total_bw > 0) { freq_1 = chan_centre + rs->freq_offset; freq_2 = chan_centre + rs->freq_offset + total_bw; } else { freq_1 = chan_centre + rs->freq_offset + total_bw; freq_2 = chan_centre + rs->freq_offset; } (*freq_lo) = (uint32_t)(freq_1); (*freq_hi) = (uint32_t)(freq_2); (*freq_centre) = (uint32_t) (freq_1 + (abs(total_bw) / 2)); return (1); }
/* * Parse the radar summary frame. * * The frame contents _minus_ the TLV are passed in. */ static void radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len, struct rx_radar_status *rsu) { uint32_t rs[2]; int freq_centre, freq; /* Drop out if we have < 2 DWORDs available */ if (len < sizeof(rs)) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | ATH_DEBUG_DFS_PHYERR_SUM, "%s: len (%zu) < expected (%zu)!", __func__, len, sizeof(rs)); } /* * Since the TLVs may be unaligned for some reason * we take a private copy into aligned memory. * This enables us to use the HAL-like accessor macros * into the DWORDs to access sub-DWORD fields. */ OS_MEMCPY(rs, buf, sizeof(rs)); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: two 32 bit values are: %08x %08x", __func__, rs[0], rs[1]); // DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s (p=%p):", __func__, buf); /* Populate the fields from the summary report */ rsu->tsf_offset = MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_TSF_OFFSET); rsu->pulse_duration = MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_DUR); rsu->is_chirp = MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_IS_CHIRP); rsu->sidx = sign_extend_32( MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_SIDX), 10); rsu->freq_offset = calc_freq_offset(rsu->sidx, PERE_IS_OVERSAMPLING(dfs)); /* These are only relevant if the pulse is a chirp */ rsu->delta_peak = sign_extend_32( MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_PEAK), 6); rsu->delta_diff = MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_DIFF); /* WAR for FCC Type 4*/ /* * HW is giving longer pulse duration (in case of VHT80, with traffic) * which fails to detect FCC type4 radar pulses. Added a work around to * fix the pulse duration and duration delta. * * IF VHT80 * && (primary_channel==30MHz || primary_channel== -30MHz) * && -4 <= pulse_index <= 4 * && !chirp * && pulse duration > 20 us * THEN * Set pulse duration to 20 us */ freq = ieee80211_chan2freq(dfs->ic, dfs->ic->ic_curchan); freq_centre = dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1; if ((IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan) && (abs(freq - freq_centre) == 30) && !rsu->is_chirp && abs(rsu->sidx) <= 4 && rsu->pulse_duration > 20)){ rsu->pulse_duration = 20; } }