/* * Calculate the channel centre in MHz. */ static int tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs) { uint32_t chan_centre; uint32_t chan_width; int chan_offset; /* * For now, just handle up to VHT80 correctly. */ if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL) { DFS_PRINTK("%s: dfs->ic=%p, that or curchan is null?\n", __func__, dfs->ic); return (0); /* * For now, the only 11ac channel with freq1/freq2 setup is * VHT80. * * XXX should have a flag macro to check this! */ } else if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) { /* 11AC, so cfreq1/cfreq2 are setup */ /* * XXX if it's 80+80 this won't work - need to use seg * appropriately! */ chan_centre = dfs->ic->ic_ieee2mhz( dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1, dfs->ic->ic_curchan->ic_flags); } else { /* HT20/HT40 */ /* * XXX this is hard-coded - it should be 5 or 10 for * half/quarter appropriately. */ chan_width = 20; /* Grab default channel centre */ chan_centre = ieee80211_chan2freq(dfs->ic, dfs->ic->ic_curchan); /* Calculate offset based on HT40U/HT40D and VHT40U/VHT40D */ if (IEEE80211_IS_CHAN_11N_HT40PLUS(dfs->ic->ic_curchan) || dfs->ic->ic_curchan->ic_flags & IEEE80211_CHAN_VHT40PLUS) chan_offset = chan_width; else if (IEEE80211_IS_CHAN_11N_HT40MINUS(dfs->ic->ic_curchan) || dfs->ic->ic_curchan->ic_flags & IEEE80211_CHAN_VHT40MINUS) chan_offset = -chan_width; else chan_offset = 0; /* Calculate new _real_ channel centre */ chan_centre += (chan_offset / 2); } /* * XXX half/quarter rate support! */ /* Return ev_chan_centre in MHz */ return (chan_centre); }
/* * 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; } }