diff options
Diffstat (limited to 'package/kernel/mac80211/patches/304-ath9k-DFS-add-pulse-chirp-detection-for-FCC.patch')
-rw-r--r-- | package/kernel/mac80211/patches/304-ath9k-DFS-add-pulse-chirp-detection-for-FCC.patch | 211 |
1 files changed, 0 insertions, 211 deletions
diff --git a/package/kernel/mac80211/patches/304-ath9k-DFS-add-pulse-chirp-detection-for-FCC.patch b/package/kernel/mac80211/patches/304-ath9k-DFS-add-pulse-chirp-detection-for-FCC.patch deleted file mode 100644 index 3437f139f7..0000000000 --- a/package/kernel/mac80211/patches/304-ath9k-DFS-add-pulse-chirp-detection-for-FCC.patch +++ /dev/null @@ -1,211 +0,0 @@ -From: Zefir Kurtisi <zefir.kurtisi@neratec.com> -Date: Tue, 16 Jun 2015 12:52:16 +0200 -Subject: [PATCH] ath9k: DFS - add pulse chirp detection for FCC - -FCC long pulse radar (type 5) requires pulses to be -checked for chirping. This patch implements chirp -detection based on the FFT data provided for long -pulses. - -A chirp is detected when a set of criteria defined -by FCC pulse characteristics is met, including -* have at least 4 FFT samples -* max_bin index moves equidistantly between samples -* the gradient is within defined range - -The chirp detection has been tested with reference -radar generating devices and proved to work reliably. - -Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com> ---- - ---- a/drivers/net/wireless/ath/ath9k/dfs.c -+++ b/drivers/net/wireless/ath/ath9k/dfs.c -@@ -30,6 +30,157 @@ struct ath_radar_data { - u8 pulse_length_pri; - }; - -+/**** begin: CHIRP ************************************************************/ -+ -+/* min and max gradients for defined FCC chirping pulses, given by -+ * - 20MHz chirp width over a pulse width of 50us -+ * - 5MHz chirp width over a pulse width of 100us -+ */ -+static const int BIN_DELTA_MIN = 1; -+static const int BIN_DELTA_MAX = 10; -+ -+/* we need at least 3 deltas / 4 samples for a reliable chirp detection */ -+#define NUM_DIFFS 3 -+static const int FFT_NUM_SAMPLES = (NUM_DIFFS + 1); -+ -+/* Threshold for difference of delta peaks */ -+static const int MAX_DIFF = 2; -+ -+/* width range to be checked for chirping */ -+static const int MIN_CHIRP_PULSE_WIDTH = 20; -+static const int MAX_CHIRP_PULSE_WIDTH = 110; -+ -+struct ath9k_dfs_fft_20 { -+ u8 bin[28]; -+ u8 lower_bins[3]; -+} __packed; -+struct ath9k_dfs_fft_40 { -+ u8 bin[64]; -+ u8 lower_bins[3]; -+ u8 upper_bins[3]; -+} __packed; -+ -+static inline int fft_max_index(u8 *bins) -+{ -+ return (bins[2] & 0xfc) >> 2; -+} -+static inline int fft_max_magnitude(u8 *bins) -+{ -+ return (bins[0] & 0xc0) >> 6 | bins[1] << 2 | (bins[2] & 0x03) << 10; -+} -+static inline u8 fft_bitmap_weight(u8 *bins) -+{ -+ return bins[0] & 0x3f; -+} -+ -+static int ath9k_get_max_index_ht40(struct ath9k_dfs_fft_40 *fft, -+ bool is_ctl, bool is_ext) -+{ -+ const int DFS_UPPER_BIN_OFFSET = 64; -+ /* if detected radar on both channels, select the significant one */ -+ if (is_ctl && is_ext) { -+ /* first check wether channels have 'strong' bins */ -+ is_ctl = fft_bitmap_weight(fft->lower_bins) != 0; -+ is_ext = fft_bitmap_weight(fft->upper_bins) != 0; -+ -+ /* if still unclear, take higher magnitude */ -+ if (is_ctl && is_ext) { -+ int mag_lower = fft_max_magnitude(fft->lower_bins); -+ int mag_upper = fft_max_magnitude(fft->upper_bins); -+ if (mag_upper > mag_lower) -+ is_ctl = false; -+ else -+ is_ext = false; -+ } -+ } -+ if (is_ctl) -+ return fft_max_index(fft->lower_bins); -+ return fft_max_index(fft->upper_bins) + DFS_UPPER_BIN_OFFSET; -+} -+static bool ath9k_check_chirping(struct ath_softc *sc, u8 *data, -+ int datalen, bool is_ctl, bool is_ext) -+{ -+ int i; -+ int max_bin[FFT_NUM_SAMPLES]; -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ int prev_delta; -+ -+ if (IS_CHAN_HT40(ah->curchan)) { -+ struct ath9k_dfs_fft_40 *fft = (struct ath9k_dfs_fft_40 *) data; -+ int num_fft_packets = datalen / sizeof(*fft); -+ if (num_fft_packets == 0) -+ return false; -+ -+ ath_dbg(common, DFS, "HT40: datalen=%d, num_fft_packets=%d\n", -+ datalen, num_fft_packets); -+ if (num_fft_packets < (FFT_NUM_SAMPLES)) { -+ ath_dbg(common, DFS, "not enough packets for chirp\n"); -+ return false; -+ } -+ /* HW sometimes adds 2 garbage bytes in front of FFT samples */ -+ if ((datalen % sizeof(*fft)) == 2) { -+ fft = (struct ath9k_dfs_fft_40 *) (data + 2); -+ ath_dbg(common, DFS, "fixing datalen by 2\n"); -+ } -+ if (IS_CHAN_HT40MINUS(ah->curchan)) { -+ int temp = is_ctl; -+ is_ctl = is_ext; -+ is_ext = temp; -+ } -+ for (i = 0; i < FFT_NUM_SAMPLES; i++) -+ max_bin[i] = ath9k_get_max_index_ht40(fft + i, is_ctl, -+ is_ext); -+ } else { -+ struct ath9k_dfs_fft_20 *fft = (struct ath9k_dfs_fft_20 *) data; -+ int num_fft_packets = datalen / sizeof(*fft); -+ if (num_fft_packets == 0) -+ return false; -+ ath_dbg(common, DFS, "HT20: datalen=%d, num_fft_packets=%d\n", -+ datalen, num_fft_packets); -+ if (num_fft_packets < (FFT_NUM_SAMPLES)) { -+ ath_dbg(common, DFS, "not enough packets for chirp\n"); -+ return false; -+ } -+ /* in ht20, this is a 6-bit signed number => shift it to 0 */ -+ for (i = 0; i < FFT_NUM_SAMPLES; i++) -+ max_bin[i] = fft_max_index(fft[i].lower_bins) ^ 0x20; -+ } -+ ath_dbg(common, DFS, "bin_max = [%d, %d, %d, %d]\n", -+ max_bin[0], max_bin[1], max_bin[2], max_bin[3]); -+ -+ /* Check for chirp attributes within specs -+ * a) delta of adjacent max_bins is within range -+ * b) delta of adjacent deltas are within tolerance -+ */ -+ prev_delta = 0; -+ for (i = 0; i < NUM_DIFFS; i++) { -+ int ddelta = -1; -+ int delta = max_bin[i + 1] - max_bin[i]; -+ -+ /* ensure gradient is within valid range */ -+ if (abs(delta) < BIN_DELTA_MIN || abs(delta) > BIN_DELTA_MAX) { -+ ath_dbg(common, DFS, "CHIRP: invalid delta %d " -+ "in sample %d\n", delta, i); -+ return false; -+ } -+ if (i == 0) -+ goto done; -+ ddelta = delta - prev_delta; -+ if (abs(ddelta) > MAX_DIFF) { -+ ath_dbg(common, DFS, "CHIRP: ddelta %d too high\n", -+ ddelta); -+ return false; -+ } -+done: -+ ath_dbg(common, DFS, "CHIRP - %d: delta=%d, ddelta=%d\n", -+ i, delta, ddelta); -+ prev_delta = delta; -+ } -+ return true; -+} -+/**** end: CHIRP **************************************************************/ -+ - /* convert pulse duration to usecs, considering clock mode */ - static u32 dur_to_usecs(struct ath_hw *ah, u32 dur) - { -@@ -113,12 +264,6 @@ ath9k_postprocess_radar_event(struct ath - return false; - } - -- /* -- * TODO: check chirping pulses -- * checks for chirping are dependent on the DFS regulatory domain -- * used, which is yet TBD -- */ -- - /* convert duration to usecs */ - pe->width = dur_to_usecs(sc->sc_ah, dur); - pe->rssi = rssi; -@@ -190,6 +335,16 @@ void ath9k_dfs_process_phyerr(struct ath - if (!ath9k_postprocess_radar_event(sc, &ard, &pe)) - return; - -+ if (pe.width > MIN_CHIRP_PULSE_WIDTH && -+ pe.width < MAX_CHIRP_PULSE_WIDTH) { -+ bool is_ctl = !!(ard.pulse_bw_info & PRI_CH_RADAR_FOUND); -+ bool is_ext = !!(ard.pulse_bw_info & EXT_CH_RADAR_FOUND); -+ int clen = datalen - 3; -+ pe.chirp = ath9k_check_chirping(sc, data, clen, is_ctl, is_ext); -+ } else { -+ pe.chirp = false; -+ } -+ - ath_dbg(common, DFS, - "ath9k_dfs_process_phyerr: type=%d, freq=%d, ts=%llu, " - "width=%d, rssi=%d, delta_ts=%llu\n", |