From 39ecc01d1bbe3de2cf5f01a81e176ea5160d3b95 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Feb 2013 12:11:00 +0100 Subject: mac80211: pass queue bitmap to flush operation There are a number of situations in which mac80211 only really needs to flush queues for one virtual interface, and in fact during this frames might be transmitted on other virtual interfaces. Calculate and pass a queue bitmap to the driver so it knows which queues to flush. Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath9k/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6e66f9c6782b..24650fd41694 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1745,7 +1745,7 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) mutex_unlock(&sc->mutex); } -static void ath9k_flush(struct ieee80211_hw *hw, bool drop) +static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) { struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; -- cgit v1.2.3 From 55f39e67399d3d4cf0c9b2833da797afeafd537b Mon Sep 17 00:00:00 2001 From: Zefir Kurtisi Date: Fri, 22 Mar 2013 12:58:23 +0100 Subject: ath9k: trivial: change spectral relayfs buffering The spectral data provided via relay-fs introduces a buffering latency given by the subbuf_size. To meet the requirements for delay-sensitive applications (like real-time spectral plotter), reduce subbuf_size and increase n_subbufs. Signed-off-by: Zefir Kurtisi Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 67a2a4b3b883..e6307b86363a 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -2072,7 +2072,7 @@ int ath9k_init_debug(struct ath_hw *ah) &fops_modal_eeprom); sc->rfs_chan_spec_scan = relay_open("spectral_scan", sc->debug.debugfs_phy, - 262144, 4, &rfs_spec_scan_cb, + 1024, 256, &rfs_spec_scan_cb, NULL); debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, -- cgit v1.2.3 From 05005c5f290cf0c4f1d4173d18fc90ea2223a043 Mon Sep 17 00:00:00 2001 From: Robert Shade Date: Wed, 27 Mar 2013 11:46:27 -0400 Subject: Show actual timeout value in failed calibration messages. The messages are currently hard coding "1ms", which does not match the actual timeout being used. Signed-off-by: Robert Shade Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_calib.c | 9 ++++++--- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index c55e5bbafc46..9f589744a9f9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -731,7 +731,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { ath_dbg(common, CALIBRATE, - "offset calibration failed to complete in 1ms; noisy environment?\n"); + "offset calibration failed to complete in %d ms; noisy environment?\n", + AH_WAIT_TIMEOUT / 1000); return false; } REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); @@ -745,7 +746,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { ath_dbg(common, CALIBRATE, - "offset calibration failed to complete in 1ms; noisy environment?\n"); + "offset calibration failed to complete in %d ms; noisy environment?\n", + AH_WAIT_TIMEOUT / 1000); return false; } @@ -841,7 +843,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { ath_dbg(common, CALIBRATE, - "offset calibration failed to complete in 1ms; noisy environment?\n"); + "offset calibration failed to complete in %d ms; noisy environment?\n", + AH_WAIT_TIMEOUT / 1000); return false; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 4cc13940c895..e1770e60be25 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1125,7 +1125,8 @@ skip_tx_iqcal: ar9003_hw_rtt_disable(ah); ath_dbg(common, CALIBRATE, - "offset calibration failed to complete in 1ms; noisy environment?\n"); + "offset calibration failed to complete in %d ms; noisy environment?\n", + AH_WAIT_TIMEOUT / 1000); return false; } -- cgit v1.2.3 From f50b1cd37446ad32c432f0f73bbed67a1c076eae Mon Sep 17 00:00:00 2001 From: Robert Shade Date: Tue, 2 Apr 2013 19:52:45 -0400 Subject: ath9k: Re-enable interrupts after a channel change failure ath_complete_reset will not be called if ath9k_hw_reset is unsuccessful, so we need to re-enable intertupts to balence the previous ath_prepare_reset call. Also schedule a reset as a best effort method to recover the chip from whatever state caused the channel change failure. Fixes https://bugzilla.kernel.org/show_bug.cgi?id=55771 Signed-off-by: Robert Shade Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6e66f9c6782b..988372d218a4 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -280,6 +280,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) if (r) { ath_err(common, "Unable to reset channel, reset status %d\n", r); + + ath9k_hw_enable_interrupts(ah); + ath9k_queue_reset(sc, RESET_TYPE_BB_HANG); + goto out; } -- cgit v1.2.3 From e9cdedf693ac0c8e0bedb8896371bf565bf5d68b Mon Sep 17 00:00:00 2001 From: Zefir Kurtisi Date: Wed, 3 Apr 2013 18:31:29 +0200 Subject: ath9k: add interface combinations for DFS master Signed-off-by: Simon Wunderlich Signed-off-by: Zefir Kurtisi Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index af932c9444de..385c59a735a8 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -727,12 +727,28 @@ static const struct ieee80211_iface_limit if_limits[] = { BIT(NL80211_IFTYPE_P2P_GO) }, }; -static const struct ieee80211_iface_combination if_comb = { - .limits = if_limits, - .n_limits = ARRAY_SIZE(if_limits), - .max_interfaces = 2048, - .num_different_channels = 1, - .beacon_int_infra_match = true, + +static const struct ieee80211_iface_limit if_dfs_limits[] = { + { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, +}; + +static const struct ieee80211_iface_combination if_comb[] = { + { + .limits = if_limits, + .n_limits = ARRAY_SIZE(if_limits), + .max_interfaces = 2048, + .num_different_channels = 1, + .beacon_int_infra_match = true, + }, + { + .limits = if_dfs_limits, + .n_limits = ARRAY_SIZE(if_dfs_limits), + .max_interfaces = 1, + .num_different_channels = 1, + .beacon_int_infra_match = true, + .radar_detect_widths = BIT(NL80211_CHAN_NO_HT) | + BIT(NL80211_CHAN_HT20), + } }; void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) @@ -763,8 +779,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); - hw->wiphy->iface_combinations = &if_comb; - hw->wiphy->n_iface_combinations = 1; + hw->wiphy->iface_combinations = if_comb; + hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); if (AR_SREV_5416(sc->sc_ah)) hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; -- cgit v1.2.3 From e39282ee1b0f639fd9eebd3547803f1694e8c370 Mon Sep 17 00:00:00 2001 From: Zefir Kurtisi Date: Wed, 3 Apr 2013 18:31:30 +0200 Subject: ath9k: add debugfs based DFS radar simulation This helps testing DFS without radar generating equipment and is required for certification. Signed-off-by: Simon Wunderlich Signed-off-by: Zefir Kurtisi Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/dfs_debug.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c index 55d28072adeb..b7611b7bbe43 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.c +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c @@ -105,6 +105,24 @@ static ssize_t write_file_dfs(struct file *file, const char __user *user_buf, return count; } +static ssize_t write_file_simulate_radar(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + + ieee80211_radar_detected(sc->hw); + + return count; +} + +static const struct file_operations fops_simulate_radar = { + .write = write_file_simulate_radar, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static const struct file_operations fops_dfs_stats = { .read = read_file_dfs, .write = write_file_dfs, @@ -117,4 +135,6 @@ void ath9k_dfs_init_debug(struct ath_softc *sc) { debugfs_create_file("dfs_stats", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_dfs_stats); + debugfs_create_file("dfs_simulate_radar", S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_simulate_radar); } -- cgit v1.2.3 From 73e4937d489072a26a0077c72c7d50ef2d0bf02b Mon Sep 17 00:00:00 2001 From: Zefir Kurtisi Date: Wed, 3 Apr 2013 18:31:31 +0200 Subject: ath9k: add support for DFS master mode These are the remaining knobs in ath9k to support DFS: * mark AR9280 and AR9580 as DFS tested * synchronize DFS regulatory domain to reg notifyer * set required RX filter flags for radar detection * process radar PHY errors at DFS detector * notify DFS master on radar detection DFS support requires CONFIG_ATH9K_DFS_CERTIFIED to be set. Signed-off-by: Zefir Kurtisi Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/dfs.c | 4 +--- drivers/net/wireless/ath/ath9k/hw.c | 3 +++ drivers/net/wireless/ath/ath9k/init.c | 4 ++++ drivers/net/wireless/ath/ath9k/main.c | 25 +++++++++++++++++++++---- drivers/net/wireless/ath/ath9k/recv.c | 7 +++++++ 5 files changed, 36 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c index ecc81792f2dc..508f8b33f0ef 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.c +++ b/drivers/net/wireless/ath/ath9k/dfs.c @@ -193,9 +193,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, DFS_STAT_INC(sc, pulses_processed); if (pd != NULL && pd->add_pulse(pd, &pe)) { DFS_STAT_INC(sc, radar_detected); - /* - * TODO: forward radar event to DFS management layer - */ + ieee80211_radar_detected(sc->hw); } } } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4fa2bb167050..3473a797651a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2380,8 +2380,11 @@ static bool ath9k_hw_dfs_tested(struct ath_hw *ah) { switch (ah->hw_version.macVersion) { + /* for temporary testing DFS with 9280 */ + case AR_SREV_VERSION_9280: /* AR9580 will likely be our first target to get testing on */ case AR_SREV_VERSION_9580: + return true; default: return false; } diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 385c59a735a8..3be2eb0da84a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -319,6 +319,10 @@ static void ath9k_reg_notifier(struct wiphy *wiphy, ath9k_ps_wakeup(sc); ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; + /* synchronize DFS detector if regulatory domain changed */ + if (sc->dfs_detector != NULL) + sc->dfs_detector->set_dfs_domain(sc->dfs_detector, + request->dfs_region); ath9k_ps_restore(sc); } } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 24650fd41694..2d251483da22 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1245,10 +1245,27 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (old_pos >= 0) ath_update_survey_nf(sc, old_pos); - /* perform spectral scan if requested. */ - if (sc->scanning && sc->spectral_mode == SPECTRAL_CHANSCAN) - ath9k_spectral_scan_trigger(hw); - + /* + * Enable radar pulse detection if on a DFS channel. Spectral + * scanning and radar detection can not be used concurrently. + */ + if (hw->conf.radar_enabled) { + u32 rxfilter; + + /* set HW specific DFS configuration */ + ath9k_hw_set_radar_params(ah); + rxfilter = ath9k_hw_getrxfilter(ah); + rxfilter |= ATH9K_RX_FILTER_PHYRADAR | + ATH9K_RX_FILTER_PHYERR; + ath9k_hw_setrxfilter(ah, rxfilter); + ath_dbg(common, DFS, "DFS enabled at freq %d\n", + curchan->center_freq); + } else { + /* perform spectral scan if requested. */ + if (sc->scanning && + sc->spectral_mode == SPECTRAL_CHANSCAN) + ath9k_spectral_scan_trigger(hw); + } } if (changed & IEEE80211_CONF_CHANGE_POWER) { diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ee156e543147..ee7ca5aecdb0 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -381,6 +381,10 @@ u32 ath_calcrxfilter(struct ath_softc *sc) rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | ATH9K_RX_FILTER_MCAST; + /* if operating on a DFS channel, enable radar pulse detection */ + if (sc->hw->conf.radar_enabled) + rfilt |= ATH9K_RX_FILTER_PHYRADAR | ATH9K_RX_FILTER_PHYERR; + if (sc->rx.rxfilter & FIF_PROBE_REQ) rfilt |= ATH9K_RX_FILTER_PROBEREQ; @@ -1228,6 +1232,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) rxs->mactime += 0x100000000ULL; + if (rs.rs_phyerr == ATH9K_PHYERR_RADAR) + ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime); + if (rs.rs_status & ATH9K_RXERR_PHY) { if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) { RX_STAT_INC(rx_spectral); -- cgit v1.2.3