/* * Return the centre frequency for the current operating channel and * event. * * This is for post-Owl 11n chips which report pri/extension channel * events. */ static inline uint16_t dfs_get_event_freqcentre(struct ath_dfs *dfs, int is_pri, int is_ext, int is_dc) { struct ieee80211com *ic; int chan_offset = 0, chan_width; /* Handle edge cases during startup/transition, shouldn't happen! */ if (dfs == NULL) return (0); if (dfs->ic == NULL || dfs->ic->ic_curchan == NULL) return (0); ic = dfs->ic; /* * * For wide channels, DC and ext frequencies need a bit of hand-holding * based on whether it's an upper or lower channel. */ chan_width = dfs_get_event_freqwidth(dfs); if (IEEE80211_IS_CHAN_11N_HT40PLUS(ic->ic_curchan)) chan_offset = chan_width; else if (IEEE80211_IS_CHAN_11N_HT40MINUS(ic->ic_curchan)) chan_offset = -chan_width; else chan_offset = 0; /* * Check for DC events first - the sowl code may just set all * the bits together.. */ if (is_dc) { /* * XXX TODO: Should DC events be considered 40MHz wide here? */ return (ieee80211_chan2freq(ic, ic->ic_curchan) + (chan_offset / 2)); } /* * For non-wide channels, the centre frequency is just ic_freq. * The centre frequency for pri events is still ic_freq. */ if (is_pri) { return (ieee80211_chan2freq(ic, ic->ic_curchan)); } if (is_ext) { return (ieee80211_chan2freq(ic, ic->ic_curchan) + chan_width); } /* XXX shouldn't get here */ return (ieee80211_chan2freq(ic, ic->ic_curchan)); }
/* * 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); }