From 4e6ce4dc7ce71d0886908d55129d5d6482a27ff9 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Thu, 6 Nov 2014 10:52:23 +0530 Subject: ath9k: Fix RTC_DERIVED_CLK usage Based on the reference clock, which could be 25MHz or 40MHz, AR_RTC_DERIVED_CLK is programmed differently for AR9340 and AR9550. But, when a chip reset is done, processing the initvals sets the register back to the default value. Fix this by moving the code in ath9k_hw_init_pll() to ar9003_hw_override_ini(). Also, do this override for AR9531. Cc: stable@vger.kernel.org Signed-off-by: Miaoqing Pan Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 13 +++++++++++++ drivers/net/wireless/ath/ath9k/hw.c | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 697c4ae90af0..1e8ea5e4d4ca 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -664,6 +664,19 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) ah->enabled_cals |= TX_CL_CAL; else ah->enabled_cals &= ~TX_CL_CAL; + + if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) { + if (ah->is_clk_25mhz) { + REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); + REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); + REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); + } else { + REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); + REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); + REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); + } + udelay(100); + } } static void ar9003_hw_prog_ini(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8be4b1453394..2ad605760e21 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -861,19 +861,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, udelay(RTC_PLL_SETTLE_DELAY); REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); - - if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { - if (ah->is_clk_25mhz) { - REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); - REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); - REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); - } else { - REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); - REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); - REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); - } - udelay(100); - } } static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, -- cgit v1.2.3 From d385c5c2860075e1f3e03074f043dd8a828b2862 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 4 Nov 2014 16:56:57 +0100 Subject: ath9k: add support for reporting tx power to mac80211 Track it per channel context instead of in the softc Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath/ath9k/init.c | 25 ++++++++++++++----------- drivers/net/wireless/ath/ath9k/main.c | 29 +++++++++++++++++++++++++---- 3 files changed, 40 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 85d74ff0767c..adb49a9813f1 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -347,6 +347,7 @@ struct ath_chanctx { int flush_timeout; u16 txpower; + u16 cur_txpower; bool offchannel; bool stopped; bool active; @@ -987,7 +988,6 @@ struct ath_softc { u8 gtt_cnt; u32 intrstatus; u16 ps_flags; /* PS_* */ - u16 curtxpow; bool ps_enabled; bool ps_idle; short nbcnvifs; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 2294109f79e9..8d3c3364326a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -172,17 +172,20 @@ static void ath9k_reg_notifier(struct wiphy *wiphy, ath_reg_notifier_apply(wiphy, request, reg); /* Set tx power */ - if (ah->curchan) { - sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power; - ath9k_ps_wakeup(sc); - ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, 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); - } + if (!ah->curchan) + return; + + sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power; + ath9k_ps_wakeup(sc); + ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false); + ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower, + sc->cur_chan->txpower, + &sc->cur_chan->cur_txpower); + /* 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 45465d8e3f0a..3ab5f630062b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -233,8 +233,9 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) ath9k_calculate_summary_state(sc, sc->cur_chan); ath_startrecv(sc); - ath9k_cmn_update_txpow(ah, sc->curtxpow, - sc->cur_chan->txpower, &sc->curtxpow); + ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower, + sc->cur_chan->txpower, + &sc->cur_chan->cur_txpower); clear_bit(ATH_OP_HW_RESET, &common->op_flags); if (!sc->cur_chan->offchannel && start) { @@ -1468,8 +1469,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_POWER) { ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level); sc->cur_chan->txpower = 2 * conf->power_level; - ath9k_cmn_update_txpow(ah, sc->curtxpow, - sc->cur_chan->txpower, &sc->curtxpow); + ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower, + sc->cur_chan->txpower, + &sc->cur_chan->cur_txpower); } mutex_unlock(&sc->mutex); @@ -2591,6 +2593,24 @@ void ath9k_fill_chanctx_ops(void) #endif +static int ath9k_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int *dbm) +{ + struct ath_softc *sc = hw->priv; + struct ath_vif *avp = (void *)vif->drv_priv; + + mutex_lock(&sc->mutex); + if (avp->chanctx) + *dbm = avp->chanctx->cur_txpower; + else + *dbm = sc->cur_chan->cur_txpower; + mutex_unlock(&sc->mutex); + + *dbm /= 2; + + return 0; +} + struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -2637,4 +2657,5 @@ struct ieee80211_ops ath9k_ops = { #endif .sw_scan_start = ath9k_sw_scan_start, .sw_scan_complete = ath9k_sw_scan_complete, + .get_txpower = ath9k_get_txpower, }; -- cgit v1.2.3 From 911ea79f435302fabefa305d3649efd4e205672b Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:18 +0100 Subject: ath9k: add struct ath_spec_scan_priv and move rfs_chan_spec_scan to this struct. We will need it for common spectral scan code. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath/ath9k/spectral.c | 12 ++++++------ drivers/net/wireless/ath/ath9k/spectral.h | 3 +++ 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index adb49a9813f1..d6e4eb5f8441 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -1029,9 +1029,9 @@ struct ath_softc { u64 dfs_prev_pulse_ts; u32 wow_enabled; /* relay(fs) channel for spectral scan */ - struct rchan *rfs_chan_spec_scan; enum spectral_mode spectral_mode; struct ath_spec_scan spec_config; + struct ath_spec_scan_priv spec_priv; struct ieee80211_vif *tx99_vif; struct sk_buff *tx99_skb; diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index 8f68426ca653..348dddd38952 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c @@ -28,12 +28,12 @@ static void ath_debug_send_fft_sample(struct ath_softc *sc, struct fft_sample_tlv *fft_sample_tlv) { int length; - if (!sc->rfs_chan_spec_scan) + if (!sc->spec_priv.rfs_chan_spec_scan) return; length = __be16_to_cpu(fft_sample_tlv->length) + sizeof(*fft_sample_tlv); - relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length); + relay_write(sc->spec_priv.rfs_chan_spec_scan, fft_sample_tlv, length); } /* returns 1 if this was a spectral frame, even if not handled. */ @@ -508,15 +508,15 @@ static struct rchan_callbacks rfs_spec_scan_cb = { void ath9k_spectral_deinit_debug(struct ath_softc *sc) { - if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { - relay_close(sc->rfs_chan_spec_scan); - sc->rfs_chan_spec_scan = NULL; + if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->spec_priv.rfs_chan_spec_scan) { + relay_close(sc->spec_priv.rfs_chan_spec_scan); + sc->spec_priv.rfs_chan_spec_scan = NULL; } } void ath9k_spectral_init_debug(struct ath_softc *sc) { - sc->rfs_chan_spec_scan = relay_open("spectral_scan", + sc->spec_priv.rfs_chan_spec_scan = relay_open("spectral_scan", sc->debug.debugfs_phy, 1024, 256, &rfs_spec_scan_cb, NULL); diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h index 7b410c6858b0..533d8a1a8a9d 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/spectral.h @@ -92,6 +92,9 @@ struct ath_ht20_40_fft_packet { struct ath_radar_info radar_info; } __packed; +struct ath_spec_scan_priv { + struct rchan *rfs_chan_spec_scan; +}; #define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) -- cgit v1.2.3 From 8391f60194bd0d9ab489105381df6455afe1f39a Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:19 +0100 Subject: ath9k: move spectral_mode to ath_spec_scan_priv Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/channel.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 4 ++-- drivers/net/wireless/ath/ath9k/spectral.c | 2 +- drivers/net/wireless/ath/ath9k/spectral.h | 1 + 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index d6e4eb5f8441..859f93e9900e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -1029,7 +1029,6 @@ struct ath_softc { u64 dfs_prev_pulse_ts; u32 wow_enabled; /* relay(fs) channel for spectral scan */ - enum spectral_mode spectral_mode; struct ath_spec_scan spec_config; struct ath_spec_scan_priv spec_priv; diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index c7234d5dda34..25a21fa389ff 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -92,7 +92,7 @@ static int ath_set_channel(struct ath_softc *sc) } else { /* perform spectral scan if requested. */ if (test_bit(ATH_OP_SCANNING, &common->op_flags) && - sc->spectral_mode == SPECTRAL_CHANSCAN) + sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) ath9k_spectral_scan_trigger(hw); } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3ab5f630062b..c074658dbf54 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1363,7 +1363,7 @@ void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) * configuration, otherwise the register will have its values reset * (on my ar9220 to value 0x01002310) */ - ath9k_spectral_scan_config(hw, sc->spectral_mode); + ath9k_spectral_scan_config(hw, sc->spec_priv.spectral_mode); ath9k_hw_ops(ah)->spectral_scan_trigger(ah); ath9k_ps_restore(sc); } @@ -1404,7 +1404,7 @@ int ath9k_spectral_scan_config(struct ieee80211_hw *hw, ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config); ath9k_ps_restore(sc); - sc->spectral_mode = spectral_mode; + sc->spec_priv.spectral_mode = spectral_mode; return 0; } diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index 348dddd38952..3a394e1fefdc 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c @@ -215,7 +215,7 @@ static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, char *mode = ""; unsigned int len; - switch (sc->spectral_mode) { + switch (sc->spec_priv.spectral_mode) { case SPECTRAL_DISABLED: mode = "disable"; break; diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h index 533d8a1a8a9d..0acdc432c771 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/spectral.h @@ -94,6 +94,7 @@ struct ath_ht20_40_fft_packet { struct ath_spec_scan_priv { struct rchan *rfs_chan_spec_scan; + enum spectral_mode spectral_mode; }; #define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) -- cgit v1.2.3 From 21af25d00b8bdf03a899b316d41d31ac3eafaf78 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:20 +0100 Subject: ath9k: move spec_config to ath_spec_scan_priv Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 3 +-- drivers/net/wireless/ath/ath9k/init.c | 12 ++++++------ drivers/net/wireless/ath/ath9k/main.c | 12 ++++++------ drivers/net/wireless/ath/ath9k/spectral.c | 16 ++++++++-------- drivers/net/wireless/ath/ath9k/spectral.h | 2 ++ 5 files changed, 23 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 859f93e9900e..dee1f2a58538 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -1028,8 +1028,7 @@ struct ath_softc { struct dfs_pattern_detector *dfs_detector; u64 dfs_prev_pulse_ts; u32 wow_enabled; - /* relay(fs) channel for spectral scan */ - struct ath_spec_scan spec_config; + struct ath_spec_scan_priv spec_priv; struct ieee80211_vif *tx99_vif; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 8d3c3364326a..aebafaa28dce 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -351,12 +351,12 @@ static void ath9k_init_misc(struct ath_softc *sc) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; - sc->spec_config.enabled = 0; - sc->spec_config.short_repeat = true; - sc->spec_config.count = 8; - sc->spec_config.endless = false; - sc->spec_config.period = 0xFF; - sc->spec_config.fft_period = 0xF; + sc->spec_priv.spec_config.enabled = 0; + sc->spec_priv.spec_config.short_repeat = true; + sc->spec_priv.spec_config.count = 8; + sc->spec_priv.spec_config.endless = false; + sc->spec_priv.spec_config.period = 0xFF; + sc->spec_priv.spec_config.fft_period = 0xF; } static void ath9k_init_pcoem_platform(struct ath_softc *sc) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c074658dbf54..f9641ee6aeb6 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1382,26 +1382,26 @@ int ath9k_spectral_scan_config(struct ieee80211_hw *hw, switch (spectral_mode) { case SPECTRAL_DISABLED: - sc->spec_config.enabled = 0; + sc->spec_priv.spec_config.enabled = 0; break; case SPECTRAL_BACKGROUND: /* send endless samples. * TODO: is this really useful for "background"? */ - sc->spec_config.endless = 1; - sc->spec_config.enabled = 1; + sc->spec_priv.spec_config.endless = 1; + sc->spec_priv.spec_config.enabled = 1; break; case SPECTRAL_CHANSCAN: case SPECTRAL_MANUAL: - sc->spec_config.endless = 0; - sc->spec_config.enabled = 1; + sc->spec_priv.spec_config.endless = 0; + sc->spec_priv.spec_config.enabled = 1; break; default: return -1; } ath9k_ps_wakeup(sc); - ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config); + ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_priv.spec_config); ath9k_ps_restore(sc); sc->spec_priv.spectral_mode = spectral_mode; diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index 3a394e1fefdc..555fc2a6851e 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c @@ -292,7 +292,7 @@ static ssize_t read_file_spectral_short_repeat(struct file *file, char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_config.short_repeat); + len = sprintf(buf, "%d\n", sc->spec_priv.spec_config.short_repeat); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -316,7 +316,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, if (val > 1) return -EINVAL; - sc->spec_config.short_repeat = val; + sc->spec_priv.spec_config.short_repeat = val; return count; } @@ -340,7 +340,7 @@ static ssize_t read_file_spectral_count(struct file *file, char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_config.count); + len = sprintf(buf, "%d\n", sc->spec_priv.spec_config.count); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -364,7 +364,7 @@ static ssize_t write_file_spectral_count(struct file *file, if (val > 255) return -EINVAL; - sc->spec_config.count = val; + sc->spec_priv.spec_config.count = val; return count; } @@ -388,7 +388,7 @@ static ssize_t read_file_spectral_period(struct file *file, char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_config.period); + len = sprintf(buf, "%d\n", sc->spec_priv.spec_config.period); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -412,7 +412,7 @@ static ssize_t write_file_spectral_period(struct file *file, if (val > 255) return -EINVAL; - sc->spec_config.period = val; + sc->spec_priv.spec_config.period = val; return count; } @@ -436,7 +436,7 @@ static ssize_t read_file_spectral_fft_period(struct file *file, char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_config.fft_period); + len = sprintf(buf, "%d\n", sc->spec_priv.spec_config.fft_period); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -460,7 +460,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file, if (val > 15) return -EINVAL; - sc->spec_config.fft_period = val; + sc->spec_priv.spec_config.fft_period = val; return count; } diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h index 0acdc432c771..dfe6f68cf5a3 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/spectral.h @@ -93,8 +93,10 @@ struct ath_ht20_40_fft_packet { } __packed; struct ath_spec_scan_priv { + /* relay(fs) channel for spectral scan */ struct rchan *rfs_chan_spec_scan; enum spectral_mode spectral_mode; + struct ath_spec_scan spec_config; }; #define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) -- cgit v1.2.3 From c10b75af4344fe0e678d167cb401a94f565e978c Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:21 +0100 Subject: ath9k: use struct dentry by ath9k_spectral_init_debug this will alow us to make ath_softc independent code. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 2 +- drivers/net/wireless/ath/ath9k/spectral.c | 14 +++++++------- drivers/net/wireless/ath/ath9k/spectral.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (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 2a2a17df5fb3..f0a802e8b0de 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1330,7 +1330,7 @@ int ath9k_init_debug(struct ath_hw *ah) ath9k_dfs_init_debug(sc); ath9k_tx99_init_debug(sc); - ath9k_spectral_init_debug(sc); + ath9k_spectral_init_debug(sc, sc->debug.debugfs_phy); debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_dma); diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index 555fc2a6851e..d2723803494d 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c @@ -514,30 +514,30 @@ void ath9k_spectral_deinit_debug(struct ath_softc *sc) } } -void ath9k_spectral_init_debug(struct ath_softc *sc) +void ath9k_spectral_init_debug(struct ath_softc *sc, struct dentry *debugfs_phy) { sc->spec_priv.rfs_chan_spec_scan = relay_open("spectral_scan", - sc->debug.debugfs_phy, + debugfs_phy, 1024, 256, &rfs_spec_scan_cb, NULL); debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, sc, &fops_spec_scan_ctl); debugfs_create_file("spectral_short_repeat", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, sc, &fops_spectral_short_repeat); debugfs_create_file("spectral_count", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, sc, &fops_spectral_count); debugfs_create_file("spectral_period", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, sc, &fops_spectral_period); debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, + debugfs_phy, sc, &fops_spectral_fft_period); } diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h index dfe6f68cf5a3..22695892963f 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/spectral.h @@ -129,7 +129,7 @@ static inline u8 spectral_bitmap_weight(u8 *bins) return bins[0] & 0x3f; } -void ath9k_spectral_init_debug(struct ath_softc *sc); +void ath9k_spectral_init_debug(struct ath_softc *sc, struct dentry *debugfs_phy); void ath9k_spectral_deinit_debug(struct ath_softc *sc); void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); -- cgit v1.2.3 From dd7657be756551b23b3431d81e66a8d95a72c923 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:22 +0100 Subject: ath9k: add ath_hw to ath_spec_scan_priv spectral code mostly depends on ath_hw, not on ath_softc Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 1 + drivers/net/wireless/ath/ath9k/spectral.h | 1 + 2 files changed, 2 insertions(+) (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 aebafaa28dce..d4a6092d4ddb 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -351,6 +351,7 @@ static void ath9k_init_misc(struct ath_softc *sc) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; + sc->spec_priv.ah = sc->sc_ah; sc->spec_priv.spec_config.enabled = 0; sc->spec_priv.spec_config.short_repeat = true; sc->spec_priv.spec_config.count = 8; diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h index 22695892963f..638320d4e381 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/spectral.h @@ -93,6 +93,7 @@ struct ath_ht20_40_fft_packet { } __packed; struct ath_spec_scan_priv { + struct ath_hw *ah; /* relay(fs) channel for spectral scan */ struct rchan *rfs_chan_spec_scan; enum spectral_mode spectral_mode; -- cgit v1.2.3 From 1111d426ef6a62903a8427a80c2a20cdf0380349 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:23 +0100 Subject: ath9k: remove all struct ath_softc dependencies from spectral code Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 4 +- drivers/net/wireless/ath/ath9k/recv.c | 2 +- drivers/net/wireless/ath/ath9k/spectral.c | 87 ++++++++++++++++--------------- drivers/net/wireless/ath/ath9k/spectral.h | 8 +-- 4 files changed, 51 insertions(+), 50 deletions(-) (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 f0a802e8b0de..6492619851a0 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1310,7 +1310,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, void ath9k_deinit_debug(struct ath_softc *sc) { - ath9k_spectral_deinit_debug(sc); + ath9k_spectral_deinit_debug(&sc->spec_priv); } int ath9k_init_debug(struct ath_hw *ah) @@ -1330,7 +1330,7 @@ int ath9k_init_debug(struct ath_hw *ah) ath9k_dfs_init_debug(sc); ath9k_tx99_init_debug(sc); - ath9k_spectral_init_debug(sc, sc->debug.debugfs_phy); + ath9k_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_dma); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 6914e21816e4..e97c6936da0f 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -870,7 +870,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, */ if (rx_stats->rs_status & ATH9K_RXERR_PHY) { ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime); - if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime)) + if (ath_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime)) RX_STAT_INC(rx_spectral); return -EINVAL; diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index d2723803494d..50af6bcf18e5 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c @@ -24,23 +24,24 @@ static s8 fix_rssi_inv_only(u8 rssi_val) return (s8) rssi_val; } -static void ath_debug_send_fft_sample(struct ath_softc *sc, +static void ath_debug_send_fft_sample(struct ath_spec_scan_priv *spec_priv, struct fft_sample_tlv *fft_sample_tlv) { int length; - if (!sc->spec_priv.rfs_chan_spec_scan) + if (!spec_priv->rfs_chan_spec_scan) return; length = __be16_to_cpu(fft_sample_tlv->length) + sizeof(*fft_sample_tlv); - relay_write(sc->spec_priv.rfs_chan_spec_scan, fft_sample_tlv, length); + relay_write(spec_priv->rfs_chan_spec_scan, fft_sample_tlv, length); } /* returns 1 if this was a spectral frame, even if not handled. */ -int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, +int ath_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, struct ath_rx_status *rs, u64 tsf) { - struct ath_hw *ah = sc->sc_ah; + struct ath_hw *ah = spec_priv->ah; + struct ath_common *common = ath9k_hw_common(spec_priv->ah); u8 num_bins, *bins, *vdata = (u8 *)hdr; struct fft_sample_ht20 fft_sample_20; struct fft_sample_ht20_40 fft_sample_40; @@ -67,7 +68,7 @@ int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) return 0; - chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef); + chan_type = cfg80211_get_chandef_type(&common->hw->conf.chandef); if ((chan_type == NL80211_CHAN_HT40MINUS) || (chan_type == NL80211_CHAN_HT40PLUS)) { fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; @@ -199,7 +200,7 @@ int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, tlv = (struct fft_sample_tlv *)&fft_sample_20; } - ath_debug_send_fft_sample(sc, tlv); + ath_debug_send_fft_sample(spec_priv, tlv); return 1; } @@ -211,11 +212,11 @@ int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char *mode = ""; unsigned int len; - switch (sc->spec_priv.spectral_mode) { + switch (spec_priv->spectral_mode) { case SPECTRAL_DISABLED: mode = "disable"; break; @@ -237,8 +238,8 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_spec_scan_priv *spec_priv = file->private_data; + struct ath_common *common = ath9k_hw_common(spec_priv->ah); char buf[32]; ssize_t len; @@ -252,18 +253,18 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, buf[len] = '\0'; if (strncmp("trigger", buf, 7) == 0) { - ath9k_spectral_scan_trigger(sc->hw); + ath9k_spectral_scan_trigger(common->hw); } else if (strncmp("background", buf, 10) == 0) { - ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND); + ath9k_spectral_scan_config(common->hw, SPECTRAL_BACKGROUND); ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); } else if (strncmp("chanscan", buf, 8) == 0) { - ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN); + ath9k_spectral_scan_config(common->hw, SPECTRAL_CHANSCAN); ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); } else if (strncmp("manual", buf, 6) == 0) { - ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL); + ath9k_spectral_scan_config(common->hw, SPECTRAL_MANUAL); ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); } else if (strncmp("disable", buf, 7) == 0) { - ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED); + ath9k_spectral_scan_config(common->hw, SPECTRAL_DISABLED); ath_dbg(common, CONFIG, "spectral scan: disabled\n"); } else { return -EINVAL; @@ -288,11 +289,11 @@ static ssize_t read_file_spectral_short_repeat(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_priv.spec_config.short_repeat); + len = sprintf(buf, "%d\n", spec_priv->spec_config.short_repeat); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -300,7 +301,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; char buf[32]; ssize_t len; @@ -316,7 +317,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, if (val > 1) return -EINVAL; - sc->spec_priv.spec_config.short_repeat = val; + spec_priv->spec_config.short_repeat = val; return count; } @@ -336,11 +337,11 @@ static ssize_t read_file_spectral_count(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_priv.spec_config.count); + len = sprintf(buf, "%d\n", spec_priv->spec_config.count); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -348,7 +349,7 @@ static ssize_t write_file_spectral_count(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; char buf[32]; ssize_t len; @@ -364,7 +365,7 @@ static ssize_t write_file_spectral_count(struct file *file, if (val > 255) return -EINVAL; - sc->spec_priv.spec_config.count = val; + spec_priv->spec_config.count = val; return count; } @@ -384,11 +385,11 @@ static ssize_t read_file_spectral_period(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_priv.spec_config.period); + len = sprintf(buf, "%d\n", spec_priv->spec_config.period); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -396,7 +397,7 @@ static ssize_t write_file_spectral_period(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; char buf[32]; ssize_t len; @@ -412,7 +413,7 @@ static ssize_t write_file_spectral_period(struct file *file, if (val > 255) return -EINVAL; - sc->spec_priv.spec_config.period = val; + spec_priv->spec_config.period = val; return count; } @@ -432,11 +433,11 @@ static ssize_t read_file_spectral_fft_period(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; char buf[32]; unsigned int len; - len = sprintf(buf, "%d\n", sc->spec_priv.spec_config.fft_period); + len = sprintf(buf, "%d\n", spec_priv->spec_config.fft_period); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -444,7 +445,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct ath_softc *sc = file->private_data; + struct ath_spec_scan_priv *spec_priv = file->private_data; unsigned long val; char buf[32]; ssize_t len; @@ -460,7 +461,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file, if (val > 15) return -EINVAL; - sc->spec_priv.spec_config.fft_period = val; + spec_priv->spec_config.fft_period = val; return count; } @@ -506,38 +507,38 @@ static struct rchan_callbacks rfs_spec_scan_cb = { /* Debug Init/Deinit */ /*********************/ -void ath9k_spectral_deinit_debug(struct ath_softc *sc) +void ath9k_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) { - if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->spec_priv.rfs_chan_spec_scan) { - relay_close(sc->spec_priv.rfs_chan_spec_scan); - sc->spec_priv.rfs_chan_spec_scan = NULL; + if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { + relay_close(spec_priv->rfs_chan_spec_scan); + spec_priv->rfs_chan_spec_scan = NULL; } } -void ath9k_spectral_init_debug(struct ath_softc *sc, struct dentry *debugfs_phy) +void ath9k_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy) { - sc->spec_priv.rfs_chan_spec_scan = relay_open("spectral_scan", + spec_priv->rfs_chan_spec_scan = relay_open("spectral_scan", debugfs_phy, 1024, 256, &rfs_spec_scan_cb, NULL); debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, - debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spec_scan_ctl); debugfs_create_file("spectral_short_repeat", S_IRUSR | S_IWUSR, - debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spectral_short_repeat); debugfs_create_file("spectral_count", S_IRUSR | S_IWUSR, - debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spectral_count); debugfs_create_file("spectral_period", S_IRUSR | S_IWUSR, - debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spectral_period); debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR, - debugfs_phy, sc, + debugfs_phy, spec_priv, &fops_spectral_fft_period); } diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h index 638320d4e381..555fcbbbcddf 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/spectral.h @@ -130,18 +130,18 @@ static inline u8 spectral_bitmap_weight(u8 *bins) return bins[0] & 0x3f; } -void ath9k_spectral_init_debug(struct ath_softc *sc, struct dentry *debugfs_phy); -void ath9k_spectral_deinit_debug(struct ath_softc *sc); +void ath9k_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); +void ath9k_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); int ath9k_spectral_scan_config(struct ieee80211_hw *hw, enum spectral_mode spectral_mode); #ifdef CONFIG_ATH9K_DEBUGFS -int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, +int ath_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, struct ath_rx_status *rs, u64 tsf); #else -static inline int ath_process_fft(struct ath_softc *sc, +static inline int ath_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, struct ath_rx_status *rs, u64 tsf) { -- cgit v1.2.3 From 99d2217b731e664aa31001839f12944b1e114a08 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:25 +0100 Subject: ath9k: add ath_ps_ops bindings Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (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 d4a6092d4ddb..4124140a4d35 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -88,6 +88,21 @@ static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = { static void ath9k_deinit_softc(struct ath_softc *sc); +void ath9k_op_ps_wakeup(struct ath_common *common) +{ + ath9k_ps_wakeup((struct ath_softc *) common->priv); +} + +void ath9k_op_ps_restore(struct ath_common *common) +{ + ath9k_ps_restore((struct ath_softc *) common->priv); +} + +struct ath_ps_ops ath9k_ps_ops = { + .wakeup = ath9k_op_ps_wakeup, + .restore = ath9k_op_ps_restore, +}; + /* * Read and write, they both share the same lock. We do this to serialize * reads and writes on Atheros 802.11n PCI devices only. This is required @@ -543,6 +558,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, common->ops = &ah->reg_ops; common->bus_ops = bus_ops; + common->ps_ops = &ath9k_ps_ops; common->ah = ah; common->hw = sc->hw; common->priv = sc; -- cgit v1.2.3 From 934bdc73dd3029c1b91e1a3538268b4afccd58cf Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:26 +0100 Subject: ath9k: use ath_ps_ops in ath9k_spectral_scan_ Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (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 f9641ee6aeb6..412b0a632f26 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1352,7 +1352,7 @@ void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) return; } - ath9k_ps_wakeup(sc); + ath_ps_ops(common)->wakeup(common); rxfilter = ath9k_hw_getrxfilter(ah); ath9k_hw_setrxfilter(ah, rxfilter | ATH9K_RX_FILTER_PHYRADAR | @@ -1365,7 +1365,7 @@ void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) */ ath9k_spectral_scan_config(hw, sc->spec_priv.spectral_mode); ath9k_hw_ops(ah)->spectral_scan_trigger(ah); - ath9k_ps_restore(sc); + ath_ps_ops(common)->restore(common); } int ath9k_spectral_scan_config(struct ieee80211_hw *hw, @@ -1400,9 +1400,9 @@ int ath9k_spectral_scan_config(struct ieee80211_hw *hw, return -1; } - ath9k_ps_wakeup(sc); + ath_ps_ops(common)->wakeup(common); ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_priv.spec_config); - ath9k_ps_restore(sc); + ath_ps_ops(common)->restore(common); sc->spec_priv.spectral_mode = spectral_mode; -- cgit v1.2.3 From ef948da55f20edbb68dac427b7e067c805c852f5 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:27 +0100 Subject: ath9k: use ath_common instead of ieee80211_hw in ath9k_spectral_scan_ we don't have here any ieee80211_hw dependencies any way. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/channel.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 12 +++++------- drivers/net/wireless/ath/ath9k/spectral.c | 10 +++++----- drivers/net/wireless/ath/ath9k/spectral.h | 4 ++-- 4 files changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 25a21fa389ff..814178ad36a7 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -93,7 +93,7 @@ static int ath_set_channel(struct ath_softc *sc) /* perform spectral scan if requested. */ if (test_bit(ATH_OP_SCANNING, &common->op_flags) && sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) - ath9k_spectral_scan_trigger(hw); + ath9k_spectral_scan_trigger(common); } return 0; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 412b0a632f26..567fb5170d1b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1337,11 +1337,10 @@ static void ath9k_disable_ps(struct ath_softc *sc) ath_dbg(common, PS, "PowerSave disabled\n"); } -void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) +void ath9k_spectral_scan_trigger(struct ath_common *common) { - struct ath_softc *sc = hw->priv; + struct ath_softc *sc = common->priv; struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); u32 rxfilter; if (config_enabled(CONFIG_ATH9K_TX99)) @@ -1363,17 +1362,16 @@ void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) * configuration, otherwise the register will have its values reset * (on my ar9220 to value 0x01002310) */ - ath9k_spectral_scan_config(hw, sc->spec_priv.spectral_mode); + ath9k_spectral_scan_config(common, sc->spec_priv.spectral_mode); ath9k_hw_ops(ah)->spectral_scan_trigger(ah); ath_ps_ops(common)->restore(common); } -int ath9k_spectral_scan_config(struct ieee80211_hw *hw, +int ath9k_spectral_scan_config(struct ath_common *common, enum spectral_mode spectral_mode) { - struct ath_softc *sc = hw->priv; + struct ath_softc *sc = common->priv; struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { ath_err(common, "spectrum analyzer not implemented on this hardware\n"); diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index 50af6bcf18e5..4549dce60c16 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c @@ -253,18 +253,18 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, buf[len] = '\0'; if (strncmp("trigger", buf, 7) == 0) { - ath9k_spectral_scan_trigger(common->hw); + ath9k_spectral_scan_trigger(common); } else if (strncmp("background", buf, 10) == 0) { - ath9k_spectral_scan_config(common->hw, SPECTRAL_BACKGROUND); + ath9k_spectral_scan_config(common, SPECTRAL_BACKGROUND); ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); } else if (strncmp("chanscan", buf, 8) == 0) { - ath9k_spectral_scan_config(common->hw, SPECTRAL_CHANSCAN); + ath9k_spectral_scan_config(common, SPECTRAL_CHANSCAN); ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); } else if (strncmp("manual", buf, 6) == 0) { - ath9k_spectral_scan_config(common->hw, SPECTRAL_MANUAL); + ath9k_spectral_scan_config(common, SPECTRAL_MANUAL); ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); } else if (strncmp("disable", buf, 7) == 0) { - ath9k_spectral_scan_config(common->hw, SPECTRAL_DISABLED); + ath9k_spectral_scan_config(common, SPECTRAL_DISABLED); ath_dbg(common, CONFIG, "spectral scan: disabled\n"); } else { return -EINVAL; diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h index 555fcbbbcddf..53660e60dd25 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/spectral.h @@ -133,8 +133,8 @@ static inline u8 spectral_bitmap_weight(u8 *bins) void ath9k_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); void ath9k_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); -void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); -int ath9k_spectral_scan_config(struct ieee80211_hw *hw, +void ath9k_spectral_scan_trigger(struct ath_common *common); +int ath9k_spectral_scan_config(struct ath_common *common, enum spectral_mode spectral_mode); #ifdef CONFIG_ATH9K_DEBUGFS -- cgit v1.2.3 From 963916dfe2907d91eb8a250d12d2b5ae5a1bb343 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:28 +0100 Subject: ath9k: make ath9k_spectral_scan_ do not depend on ath_softc last preparation before moving ath9k_spectral_scan_ to spectral.c Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/channel.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 26 +++++++++++++------------- drivers/net/wireless/ath/ath9k/spectral.c | 10 +++++----- drivers/net/wireless/ath/ath9k/spectral.h | 4 +++- 4 files changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 814178ad36a7..32ce931c2404 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -93,7 +93,7 @@ static int ath_set_channel(struct ath_softc *sc) /* perform spectral scan if requested. */ if (test_bit(ATH_OP_SCANNING, &common->op_flags) && sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) - ath9k_spectral_scan_trigger(common); + ath9k_spectral_scan_trigger(common, &sc->spec_priv); } return 0; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 567fb5170d1b..54e3e41a591c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1337,10 +1337,10 @@ static void ath9k_disable_ps(struct ath_softc *sc) ath_dbg(common, PS, "PowerSave disabled\n"); } -void ath9k_spectral_scan_trigger(struct ath_common *common) +void ath9k_spectral_scan_trigger(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv) { - struct ath_softc *sc = common->priv; - struct ath_hw *ah = sc->sc_ah; + struct ath_hw *ah = spec_priv->ah; u32 rxfilter; if (config_enabled(CONFIG_ATH9K_TX99)) @@ -1362,16 +1362,16 @@ void ath9k_spectral_scan_trigger(struct ath_common *common) * configuration, otherwise the register will have its values reset * (on my ar9220 to value 0x01002310) */ - ath9k_spectral_scan_config(common, sc->spec_priv.spectral_mode); + ath9k_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode); ath9k_hw_ops(ah)->spectral_scan_trigger(ah); ath_ps_ops(common)->restore(common); } int ath9k_spectral_scan_config(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv, enum spectral_mode spectral_mode) { - struct ath_softc *sc = common->priv; - struct ath_hw *ah = sc->sc_ah; + struct ath_hw *ah = spec_priv->ah; if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { ath_err(common, "spectrum analyzer not implemented on this hardware\n"); @@ -1380,29 +1380,29 @@ int ath9k_spectral_scan_config(struct ath_common *common, switch (spectral_mode) { case SPECTRAL_DISABLED: - sc->spec_priv.spec_config.enabled = 0; + spec_priv->spec_config.enabled = 0; break; case SPECTRAL_BACKGROUND: /* send endless samples. * TODO: is this really useful for "background"? */ - sc->spec_priv.spec_config.endless = 1; - sc->spec_priv.spec_config.enabled = 1; + spec_priv->spec_config.endless = 1; + spec_priv->spec_config.enabled = 1; break; case SPECTRAL_CHANSCAN: case SPECTRAL_MANUAL: - sc->spec_priv.spec_config.endless = 0; - sc->spec_priv.spec_config.enabled = 1; + spec_priv->spec_config.endless = 0; + spec_priv->spec_config.enabled = 1; break; default: return -1; } ath_ps_ops(common)->wakeup(common); - ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_priv.spec_config); + ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config); ath_ps_ops(common)->restore(common); - sc->spec_priv.spectral_mode = spectral_mode; + spec_priv->spectral_mode = spectral_mode; return 0; } diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index 4549dce60c16..756d63ea6205 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c @@ -253,18 +253,18 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, buf[len] = '\0'; if (strncmp("trigger", buf, 7) == 0) { - ath9k_spectral_scan_trigger(common); + ath9k_spectral_scan_trigger(common, spec_priv); } else if (strncmp("background", buf, 10) == 0) { - ath9k_spectral_scan_config(common, SPECTRAL_BACKGROUND); + ath9k_spectral_scan_config(common, spec_priv, SPECTRAL_BACKGROUND); ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); } else if (strncmp("chanscan", buf, 8) == 0) { - ath9k_spectral_scan_config(common, SPECTRAL_CHANSCAN); + ath9k_spectral_scan_config(common, spec_priv, SPECTRAL_CHANSCAN); ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); } else if (strncmp("manual", buf, 6) == 0) { - ath9k_spectral_scan_config(common, SPECTRAL_MANUAL); + ath9k_spectral_scan_config(common, spec_priv, SPECTRAL_MANUAL); ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); } else if (strncmp("disable", buf, 7) == 0) { - ath9k_spectral_scan_config(common, SPECTRAL_DISABLED); + ath9k_spectral_scan_config(common, spec_priv, SPECTRAL_DISABLED); ath_dbg(common, CONFIG, "spectral scan: disabled\n"); } else { return -EINVAL; diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h index 53660e60dd25..77582cf743ac 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/spectral.h @@ -133,8 +133,10 @@ static inline u8 spectral_bitmap_weight(u8 *bins) void ath9k_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); void ath9k_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); -void ath9k_spectral_scan_trigger(struct ath_common *common); +void ath9k_spectral_scan_trigger(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv); int ath9k_spectral_scan_config(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv, enum spectral_mode spectral_mode); #ifdef CONFIG_ATH9K_DEBUGFS -- cgit v1.2.3 From f00a422cc81ef665f5098c0bc43cb0c616e55a9b Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:29 +0100 Subject: ath9k: move ath9k_spectral_scan_ from main.c to spectral.c Now we should be ready to make this code common. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 70 ------------------------------- drivers/net/wireless/ath/ath9k/spectral.c | 70 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 70 deletions(-) (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 54e3e41a591c..1a88614eb73e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1337,76 +1337,6 @@ static void ath9k_disable_ps(struct ath_softc *sc) ath_dbg(common, PS, "PowerSave disabled\n"); } -void ath9k_spectral_scan_trigger(struct ath_common *common, - struct ath_spec_scan_priv *spec_priv) -{ - struct ath_hw *ah = spec_priv->ah; - u32 rxfilter; - - if (config_enabled(CONFIG_ATH9K_TX99)) - return; - - if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { - ath_err(common, "spectrum analyzer not implemented on this hardware\n"); - return; - } - - ath_ps_ops(common)->wakeup(common); - rxfilter = ath9k_hw_getrxfilter(ah); - ath9k_hw_setrxfilter(ah, rxfilter | - ATH9K_RX_FILTER_PHYRADAR | - ATH9K_RX_FILTER_PHYERR); - - /* TODO: usually this should not be neccesary, but for some reason - * (or in some mode?) the trigger must be called after the - * configuration, otherwise the register will have its values reset - * (on my ar9220 to value 0x01002310) - */ - ath9k_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode); - ath9k_hw_ops(ah)->spectral_scan_trigger(ah); - ath_ps_ops(common)->restore(common); -} - -int ath9k_spectral_scan_config(struct ath_common *common, - struct ath_spec_scan_priv *spec_priv, - enum spectral_mode spectral_mode) -{ - struct ath_hw *ah = spec_priv->ah; - - if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { - ath_err(common, "spectrum analyzer not implemented on this hardware\n"); - return -1; - } - - switch (spectral_mode) { - case SPECTRAL_DISABLED: - spec_priv->spec_config.enabled = 0; - break; - case SPECTRAL_BACKGROUND: - /* send endless samples. - * TODO: is this really useful for "background"? - */ - spec_priv->spec_config.endless = 1; - spec_priv->spec_config.enabled = 1; - break; - case SPECTRAL_CHANSCAN: - case SPECTRAL_MANUAL: - spec_priv->spec_config.endless = 0; - spec_priv->spec_config.enabled = 1; - break; - default: - return -1; - } - - ath_ps_ops(common)->wakeup(common); - ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config); - ath_ps_ops(common)->restore(common); - - spec_priv->spectral_mode = spectral_mode; - - return 0; -} - static int ath9k_config(struct ieee80211_hw *hw, u32 changed) { struct ath_softc *sc = hw->priv; diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c index 756d63ea6205..bf85740ab84b 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/spectral.c @@ -234,6 +234,76 @@ static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, return simple_read_from_buffer(user_buf, count, ppos, mode, len); } +void ath9k_spectral_scan_trigger(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv) +{ + struct ath_hw *ah = spec_priv->ah; + u32 rxfilter; + + if (config_enabled(CONFIG_ATH9K_TX99)) + return; + + if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { + ath_err(common, "spectrum analyzer not implemented on this hardware\n"); + return; + } + + ath_ps_ops(common)->wakeup(common); + rxfilter = ath9k_hw_getrxfilter(ah); + ath9k_hw_setrxfilter(ah, rxfilter | + ATH9K_RX_FILTER_PHYRADAR | + ATH9K_RX_FILTER_PHYERR); + + /* TODO: usually this should not be neccesary, but for some reason + * (or in some mode?) the trigger must be called after the + * configuration, otherwise the register will have its values reset + * (on my ar9220 to value 0x01002310) + */ + ath9k_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode); + ath9k_hw_ops(ah)->spectral_scan_trigger(ah); + ath_ps_ops(common)->restore(common); +} + +int ath9k_spectral_scan_config(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv, + enum spectral_mode spectral_mode) +{ + struct ath_hw *ah = spec_priv->ah; + + if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { + ath_err(common, "spectrum analyzer not implemented on this hardware\n"); + return -1; + } + + switch (spectral_mode) { + case SPECTRAL_DISABLED: + spec_priv->spec_config.enabled = 0; + break; + case SPECTRAL_BACKGROUND: + /* send endless samples. + * TODO: is this really useful for "background"? + */ + spec_priv->spec_config.endless = 1; + spec_priv->spec_config.enabled = 1; + break; + case SPECTRAL_CHANSCAN: + case SPECTRAL_MANUAL: + spec_priv->spec_config.endless = 0; + spec_priv->spec_config.enabled = 1; + break; + default: + return -1; + } + + ath_ps_ops(common)->wakeup(common); + ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config); + ath_ps_ops(common)->restore(common); + + spec_priv->spectral_mode = spectral_mode; + + return 0; +} + static ssize_t write_file_spec_scan_ctl(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) -- cgit v1.2.3 From 67dc74f15f147b9f88702de2952d2951e3e000ec Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:30 +0100 Subject: ath9k: move spectral.* to common-spectral.* and rename exports from ath9k_spectral_* to ath9k_cmn_spectral_* Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 6 +- drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/channel.c | 2 +- drivers/net/wireless/ath/ath9k/common-spectral.c | 620 +++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/common-spectral.h | 154 ++++++ drivers/net/wireless/ath/ath9k/common.h | 1 + drivers/net/wireless/ath/ath9k/debug.c | 4 +- drivers/net/wireless/ath/ath9k/recv.c | 2 +- drivers/net/wireless/ath/ath9k/spectral.c | 614 ---------------------- drivers/net/wireless/ath/ath9k/spectral.h | 154 ------ 10 files changed, 782 insertions(+), 776 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/common-spectral.c create mode 100644 drivers/net/wireless/ath/ath9k/common-spectral.h delete mode 100644 drivers/net/wireless/ath/ath9k/spectral.c delete mode 100644 drivers/net/wireless/ath/ath9k/spectral.h (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 22b934b07bd4..473972288a84 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -16,8 +16,7 @@ ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o ath9k-$(CONFIG_ATH9K_TX99) += tx99.o ath9k-$(CONFIG_ATH9K_WOW) += wow.o -ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o \ - spectral.o +ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o ath9k-$(CONFIG_ATH9K_STATION_STATISTICS) += debug_sta.o @@ -59,7 +58,8 @@ obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o ath9k_common-y:= common.o \ common-init.o \ common-beacon.o \ - common-debug.o + common-debug.o \ + common-spectral.o ath9k_htc-y += htc_hst.o \ hif_usb.o \ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index dee1f2a58538..d5a2019921bd 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -28,7 +28,6 @@ #include "debug.h" #include "mci.h" #include "dfs.h" -#include "spectral.h" struct ath_node; struct ath_vif; diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 32ce931c2404..1dadf6d77a82 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -93,7 +93,7 @@ static int ath_set_channel(struct ath_softc *sc) /* perform spectral scan if requested. */ if (test_bit(ATH_OP_SCANNING, &common->op_flags) && sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) - ath9k_spectral_scan_trigger(common, &sc->spec_priv); + ath9k_cmn_spectral_scan_trigger(common, &sc->spec_priv); } return 0; diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c new file mode 100644 index 000000000000..ec93ddf0863a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "ath9k.h" + +static s8 fix_rssi_inv_only(u8 rssi_val) +{ + if (rssi_val == 128) + rssi_val = 0; + return (s8) rssi_val; +} + +static void ath_debug_send_fft_sample(struct ath_spec_scan_priv *spec_priv, + struct fft_sample_tlv *fft_sample_tlv) +{ + int length; + if (!spec_priv->rfs_chan_spec_scan) + return; + + length = __be16_to_cpu(fft_sample_tlv->length) + + sizeof(*fft_sample_tlv); + relay_write(spec_priv->rfs_chan_spec_scan, fft_sample_tlv, length); +} + +/* returns 1 if this was a spectral frame, even if not handled. */ +int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, + struct ath_rx_status *rs, u64 tsf) +{ + struct ath_hw *ah = spec_priv->ah; + struct ath_common *common = ath9k_hw_common(spec_priv->ah); + u8 num_bins, *bins, *vdata = (u8 *)hdr; + struct fft_sample_ht20 fft_sample_20; + struct fft_sample_ht20_40 fft_sample_40; + struct fft_sample_tlv *tlv; + struct ath_radar_info *radar_info; + int len = rs->rs_datalen; + int dc_pos; + u16 fft_len, length, freq = ah->curchan->chan->center_freq; + enum nl80211_channel_type chan_type; + + /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer + * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT + * yet, but this is supposed to be possible as well. + */ + if (rs->rs_phyerr != ATH9K_PHYERR_RADAR && + rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT && + rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL) + return 0; + + /* check if spectral scan bit is set. This does not have to be checked + * if received through a SPECTRAL phy error, but shouldn't hurt. + */ + radar_info = ((struct ath_radar_info *)&vdata[len]) - 1; + if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) + return 0; + + chan_type = cfg80211_get_chandef_type(&common->hw->conf.chandef); + if ((chan_type == NL80211_CHAN_HT40MINUS) || + (chan_type == NL80211_CHAN_HT40PLUS)) { + fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; + num_bins = SPECTRAL_HT20_40_NUM_BINS; + bins = (u8 *)fft_sample_40.data; + } else { + fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN; + num_bins = SPECTRAL_HT20_NUM_BINS; + bins = (u8 *)fft_sample_20.data; + } + + /* Variation in the data length is possible and will be fixed later */ + if ((len > fft_len + 2) || (len < fft_len - 1)) + return 1; + + switch (len - fft_len) { + case 0: + /* length correct, nothing to do. */ + memcpy(bins, vdata, num_bins); + break; + case -1: + /* first byte missing, duplicate it. */ + memcpy(&bins[1], vdata, num_bins - 1); + bins[0] = vdata[0]; + break; + case 2: + /* MAC added 2 extra bytes at bin 30 and 32, remove them. */ + memcpy(bins, vdata, 30); + bins[30] = vdata[31]; + memcpy(&bins[31], &vdata[33], num_bins - 31); + break; + case 1: + /* MAC added 2 extra bytes AND first byte is missing. */ + bins[0] = vdata[0]; + memcpy(&bins[1], vdata, 30); + bins[31] = vdata[31]; + memcpy(&bins[32], &vdata[33], num_bins - 32); + break; + default: + return 1; + } + + /* DC value (value in the middle) is the blind spot of the spectral + * sample and invalid, interpolate it. + */ + dc_pos = num_bins / 2; + bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; + + if ((chan_type == NL80211_CHAN_HT40MINUS) || + (chan_type == NL80211_CHAN_HT40PLUS)) { + s8 lower_rssi, upper_rssi; + s16 ext_nf; + u8 lower_max_index, upper_max_index; + u8 lower_bitmap_w, upper_bitmap_w; + u16 lower_mag, upper_mag; + struct ath9k_hw_cal_data *caldata = ah->caldata; + struct ath_ht20_40_mag_info *mag_info; + + if (caldata) + ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan, + caldata->nfCalHist[3].privNF); + else + ext_nf = ATH_DEFAULT_NOISE_FLOOR; + + length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv); + fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40; + fft_sample_40.tlv.length = __cpu_to_be16(length); + fft_sample_40.freq = __cpu_to_be16(freq); + fft_sample_40.channel_type = chan_type; + + if (chan_type == NL80211_CHAN_HT40PLUS) { + lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]); + upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]); + + fft_sample_40.lower_noise = ah->noise; + fft_sample_40.upper_noise = ext_nf; + } else { + lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]); + upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]); + + fft_sample_40.lower_noise = ext_nf; + fft_sample_40.upper_noise = ah->noise; + } + fft_sample_40.lower_rssi = lower_rssi; + fft_sample_40.upper_rssi = upper_rssi; + + mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1; + lower_mag = spectral_max_magnitude(mag_info->lower_bins); + upper_mag = spectral_max_magnitude(mag_info->upper_bins); + fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag); + fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag); + lower_max_index = spectral_max_index(mag_info->lower_bins); + upper_max_index = spectral_max_index(mag_info->upper_bins); + fft_sample_40.lower_max_index = lower_max_index; + fft_sample_40.upper_max_index = upper_max_index; + lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins); + upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins); + fft_sample_40.lower_bitmap_weight = lower_bitmap_w; + fft_sample_40.upper_bitmap_weight = upper_bitmap_w; + fft_sample_40.max_exp = mag_info->max_exp & 0xf; + + fft_sample_40.tsf = __cpu_to_be64(tsf); + + tlv = (struct fft_sample_tlv *)&fft_sample_40; + } else { + u8 max_index, bitmap_w; + u16 magnitude; + struct ath_ht20_mag_info *mag_info; + + length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv); + fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20; + fft_sample_20.tlv.length = __cpu_to_be16(length); + fft_sample_20.freq = __cpu_to_be16(freq); + + fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]); + fft_sample_20.noise = ah->noise; + + mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; + magnitude = spectral_max_magnitude(mag_info->all_bins); + fft_sample_20.max_magnitude = __cpu_to_be16(magnitude); + max_index = spectral_max_index(mag_info->all_bins); + fft_sample_20.max_index = max_index; + bitmap_w = spectral_bitmap_weight(mag_info->all_bins); + fft_sample_20.bitmap_weight = bitmap_w; + fft_sample_20.max_exp = mag_info->max_exp & 0xf; + + fft_sample_20.tsf = __cpu_to_be64(tsf); + + tlv = (struct fft_sample_tlv *)&fft_sample_20; + } + + ath_debug_send_fft_sample(spec_priv, tlv); + + return 1; +} +EXPORT_SYMBOL(ath_cmn_process_fft); + +/*********************/ +/* spectral_scan_ctl */ +/*********************/ + +static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + char *mode = ""; + unsigned int len; + + switch (spec_priv->spectral_mode) { + case SPECTRAL_DISABLED: + mode = "disable"; + break; + case SPECTRAL_BACKGROUND: + mode = "background"; + break; + case SPECTRAL_CHANSCAN: + mode = "chanscan"; + break; + case SPECTRAL_MANUAL: + mode = "manual"; + break; + } + len = strlen(mode); + return simple_read_from_buffer(user_buf, count, ppos, mode, len); +} + +void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv) +{ + struct ath_hw *ah = spec_priv->ah; + u32 rxfilter; + + if (config_enabled(CONFIG_ATH9K_TX99)) + return; + + if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { + ath_err(common, "spectrum analyzer not implemented on this hardware\n"); + return; + } + + ath_ps_ops(common)->wakeup(common); + rxfilter = ath9k_hw_getrxfilter(ah); + ath9k_hw_setrxfilter(ah, rxfilter | + ATH9K_RX_FILTER_PHYRADAR | + ATH9K_RX_FILTER_PHYERR); + + /* TODO: usually this should not be neccesary, but for some reason + * (or in some mode?) the trigger must be called after the + * configuration, otherwise the register will have its values reset + * (on my ar9220 to value 0x01002310) + */ + ath9k_cmn_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode); + ath9k_hw_ops(ah)->spectral_scan_trigger(ah); + ath_ps_ops(common)->restore(common); +} +EXPORT_SYMBOL(ath9k_cmn_spectral_scan_trigger); + +int ath9k_cmn_spectral_scan_config(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv, + enum spectral_mode spectral_mode) +{ + struct ath_hw *ah = spec_priv->ah; + + if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { + ath_err(common, "spectrum analyzer not implemented on this hardware\n"); + return -1; + } + + switch (spectral_mode) { + case SPECTRAL_DISABLED: + spec_priv->spec_config.enabled = 0; + break; + case SPECTRAL_BACKGROUND: + /* send endless samples. + * TODO: is this really useful for "background"? + */ + spec_priv->spec_config.endless = 1; + spec_priv->spec_config.enabled = 1; + break; + case SPECTRAL_CHANSCAN: + case SPECTRAL_MANUAL: + spec_priv->spec_config.endless = 0; + spec_priv->spec_config.enabled = 1; + break; + default: + return -1; + } + + ath_ps_ops(common)->wakeup(common); + ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config); + ath_ps_ops(common)->restore(common); + + spec_priv->spectral_mode = spectral_mode; + + return 0; +} +EXPORT_SYMBOL(ath9k_cmn_spectral_scan_config); + +static ssize_t write_file_spec_scan_ctl(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + struct ath_common *common = ath9k_hw_common(spec_priv->ah); + char buf[32]; + ssize_t len; + + if (config_enabled(CONFIG_ATH9K_TX99)) + return -EOPNOTSUPP; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + + if (strncmp("trigger", buf, 7) == 0) { + ath9k_cmn_spectral_scan_trigger(common, spec_priv); + } else if (strncmp("background", buf, 10) == 0) { + ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_BACKGROUND); + ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); + } else if (strncmp("chanscan", buf, 8) == 0) { + ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_CHANSCAN); + ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); + } else if (strncmp("manual", buf, 6) == 0) { + ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_MANUAL); + ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); + } else if (strncmp("disable", buf, 7) == 0) { + ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_DISABLED); + ath_dbg(common, CONFIG, "spectral scan: disabled\n"); + } else { + return -EINVAL; + } + + return count; +} + +static const struct file_operations fops_spec_scan_ctl = { + .read = read_file_spec_scan_ctl, + .write = write_file_spec_scan_ctl, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +/*************************/ +/* spectral_short_repeat */ +/*************************/ + +static ssize_t read_file_spectral_short_repeat(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + char buf[32]; + unsigned int len; + + len = sprintf(buf, "%d\n", spec_priv->spec_config.short_repeat); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_spectral_short_repeat(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + unsigned long val; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val > 1) + return -EINVAL; + + spec_priv->spec_config.short_repeat = val; + return count; +} + +static const struct file_operations fops_spectral_short_repeat = { + .read = read_file_spectral_short_repeat, + .write = write_file_spectral_short_repeat, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +/******************/ +/* spectral_count */ +/******************/ + +static ssize_t read_file_spectral_count(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + char buf[32]; + unsigned int len; + + len = sprintf(buf, "%d\n", spec_priv->spec_config.count); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_spectral_count(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + unsigned long val; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val > 255) + return -EINVAL; + + spec_priv->spec_config.count = val; + return count; +} + +static const struct file_operations fops_spectral_count = { + .read = read_file_spectral_count, + .write = write_file_spectral_count, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +/*******************/ +/* spectral_period */ +/*******************/ + +static ssize_t read_file_spectral_period(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + char buf[32]; + unsigned int len; + + len = sprintf(buf, "%d\n", spec_priv->spec_config.period); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_spectral_period(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + unsigned long val; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val > 255) + return -EINVAL; + + spec_priv->spec_config.period = val; + return count; +} + +static const struct file_operations fops_spectral_period = { + .read = read_file_spectral_period, + .write = write_file_spectral_period, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +/***********************/ +/* spectral_fft_period */ +/***********************/ + +static ssize_t read_file_spectral_fft_period(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + char buf[32]; + unsigned int len; + + len = sprintf(buf, "%d\n", spec_priv->spec_config.fft_period); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_spectral_fft_period(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_spec_scan_priv *spec_priv = file->private_data; + unsigned long val; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val > 15) + return -EINVAL; + + spec_priv->spec_config.fft_period = val; + return count; +} + +static const struct file_operations fops_spectral_fft_period = { + .read = read_file_spectral_fft_period, + .write = write_file_spectral_fft_period, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +/*******************/ +/* Relay interface */ +/*******************/ + +static struct dentry *create_buf_file_handler(const char *filename, + struct dentry *parent, + umode_t mode, + struct rchan_buf *buf, + int *is_global) +{ + struct dentry *buf_file; + + buf_file = debugfs_create_file(filename, mode, parent, buf, + &relay_file_operations); + *is_global = 1; + return buf_file; +} + +static int remove_buf_file_handler(struct dentry *dentry) +{ + debugfs_remove(dentry); + + return 0; +} + +static struct rchan_callbacks rfs_spec_scan_cb = { + .create_buf_file = create_buf_file_handler, + .remove_buf_file = remove_buf_file_handler, +}; + +/*********************/ +/* Debug Init/Deinit */ +/*********************/ + +void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) +{ + if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { + relay_close(spec_priv->rfs_chan_spec_scan); + spec_priv->rfs_chan_spec_scan = NULL; + } +} +EXPORT_SYMBOL(ath9k_cmn_spectral_deinit_debug); + +void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, + struct dentry *debugfs_phy) +{ + spec_priv->rfs_chan_spec_scan = relay_open("spectral_scan", + debugfs_phy, + 1024, 256, &rfs_spec_scan_cb, + NULL); + debugfs_create_file("spectral_scan_ctl", + S_IRUSR | S_IWUSR, + debugfs_phy, spec_priv, + &fops_spec_scan_ctl); + debugfs_create_file("spectral_short_repeat", + S_IRUSR | S_IWUSR, + debugfs_phy, spec_priv, + &fops_spectral_short_repeat); + debugfs_create_file("spectral_count", + S_IRUSR | S_IWUSR, + debugfs_phy, spec_priv, + &fops_spectral_count); + debugfs_create_file("spectral_period", + S_IRUSR | S_IWUSR, + debugfs_phy, spec_priv, + &fops_spectral_period); + debugfs_create_file("spectral_fft_period", + S_IRUSR | S_IWUSR, + debugfs_phy, spec_priv, + &fops_spectral_fft_period); +} +EXPORT_SYMBOL(ath9k_cmn_spectral_init_debug); diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.h b/drivers/net/wireless/ath/ath9k/common-spectral.h new file mode 100644 index 000000000000..214c3baf5023 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/common-spectral.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef SPECTRAL_H +#define SPECTRAL_H + +#include "../spectral_common.h" + +/* enum spectral_mode: + * + * @SPECTRAL_DISABLED: spectral mode is disabled + * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with + * something else. + * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples + * is performed manually. + * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels + * during a channel scan. + */ +enum spectral_mode { + SPECTRAL_DISABLED = 0, + SPECTRAL_BACKGROUND, + SPECTRAL_MANUAL, + SPECTRAL_CHANSCAN, +}; + +#define SPECTRAL_SCAN_BITMASK 0x10 +/* Radar info packet format, used for DFS and spectral formats. */ +struct ath_radar_info { + u8 pulse_length_pri; + u8 pulse_length_ext; + u8 pulse_bw_info; +} __packed; + +/* The HT20 spectral data has 4 bytes of additional information at it's end. + * + * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]} + * [7:0]: all bins max_magnitude[9:2] + * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]} + * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) + */ +struct ath_ht20_mag_info { + u8 all_bins[3]; + u8 max_exp; +} __packed; + +/* WARNING: don't actually use this struct! MAC may vary the amount of + * data by -1/+2. This struct is for reference only. + */ +struct ath_ht20_fft_packet { + u8 data[SPECTRAL_HT20_NUM_BINS]; + struct ath_ht20_mag_info mag_info; + struct ath_radar_info radar_info; +} __packed; + +#define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet)) + +/* Dynamic 20/40 mode: + * + * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]} + * [7:0]: lower bins max_magnitude[9:2] + * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]} + * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]} + * [7:0]: upper bins max_magnitude[9:2] + * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]} + * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) + */ +struct ath_ht20_40_mag_info { + u8 lower_bins[3]; + u8 upper_bins[3]; + u8 max_exp; +} __packed; + +/* WARNING: don't actually use this struct! MAC may vary the amount of + * data. This struct is for reference only. + */ +struct ath_ht20_40_fft_packet { + u8 data[SPECTRAL_HT20_40_NUM_BINS]; + struct ath_ht20_40_mag_info mag_info; + struct ath_radar_info radar_info; +} __packed; + +struct ath_spec_scan_priv { + struct ath_hw *ah; + /* relay(fs) channel for spectral scan */ + struct rchan *rfs_chan_spec_scan; + enum spectral_mode spectral_mode; + struct ath_spec_scan spec_config; +}; + +#define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) + +/* grabs the max magnitude from the all/upper/lower bins */ +static inline u16 spectral_max_magnitude(u8 *bins) +{ + return (bins[0] & 0xc0) >> 6 | + (bins[1] & 0xff) << 2 | + (bins[2] & 0x03) << 10; +} + +/* return the max magnitude from the all/upper/lower bins */ +static inline u8 spectral_max_index(u8 *bins) +{ + s8 m = (bins[2] & 0xfc) >> 2; + + /* TODO: this still doesn't always report the right values ... */ + if (m > 32) + m |= 0xe0; + else + m &= ~0xe0; + + return m + 29; +} + +/* return the bitmap weight from the all/upper/lower bins */ +static inline u8 spectral_bitmap_weight(u8 *bins) +{ + return bins[0] & 0x3f; +} + +void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); +void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); + +void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv); +int ath9k_cmn_spectral_scan_config(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv, + enum spectral_mode spectral_mode); + +#ifdef CONFIG_ATH9K_DEBUGFS +int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, + struct ath_rx_status *rs, u64 tsf); +#else +static inline int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, + struct ieee80211_hdr *hdr, + struct ath_rx_status *rs, u64 tsf) +{ + return 0; +} +#endif /* CONFIG_ATH9K_DEBUGFS */ + +#endif /* SPECTRAL_H */ diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index ffc454b18637..2b79a568e803 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -24,6 +24,7 @@ #include "common-init.h" #include "common-beacon.h" #include "common-debug.h" +#include "common-spectral.h" /* Common header for Atheros 802.11n base driver cores */ diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 6492619851a0..db388405bf0c 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1310,7 +1310,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, void ath9k_deinit_debug(struct ath_softc *sc) { - ath9k_spectral_deinit_debug(&sc->spec_priv); + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); } int ath9k_init_debug(struct ath_hw *ah) @@ -1330,7 +1330,7 @@ int ath9k_init_debug(struct ath_hw *ah) ath9k_dfs_init_debug(sc); ath9k_tx99_init_debug(sc); - ath9k_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); + ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_dma); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index e97c6936da0f..7395afbc5124 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -870,7 +870,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, */ if (rx_stats->rs_status & ATH9K_RXERR_PHY) { ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime); - if (ath_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime)) + if (ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime)) RX_STAT_INC(rx_spectral); return -EINVAL; diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c deleted file mode 100644 index bf85740ab84b..000000000000 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "ath9k.h" - -static s8 fix_rssi_inv_only(u8 rssi_val) -{ - if (rssi_val == 128) - rssi_val = 0; - return (s8) rssi_val; -} - -static void ath_debug_send_fft_sample(struct ath_spec_scan_priv *spec_priv, - struct fft_sample_tlv *fft_sample_tlv) -{ - int length; - if (!spec_priv->rfs_chan_spec_scan) - return; - - length = __be16_to_cpu(fft_sample_tlv->length) + - sizeof(*fft_sample_tlv); - relay_write(spec_priv->rfs_chan_spec_scan, fft_sample_tlv, length); -} - -/* returns 1 if this was a spectral frame, even if not handled. */ -int ath_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, - struct ath_rx_status *rs, u64 tsf) -{ - struct ath_hw *ah = spec_priv->ah; - struct ath_common *common = ath9k_hw_common(spec_priv->ah); - u8 num_bins, *bins, *vdata = (u8 *)hdr; - struct fft_sample_ht20 fft_sample_20; - struct fft_sample_ht20_40 fft_sample_40; - struct fft_sample_tlv *tlv; - struct ath_radar_info *radar_info; - int len = rs->rs_datalen; - int dc_pos; - u16 fft_len, length, freq = ah->curchan->chan->center_freq; - enum nl80211_channel_type chan_type; - - /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer - * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT - * yet, but this is supposed to be possible as well. - */ - if (rs->rs_phyerr != ATH9K_PHYERR_RADAR && - rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT && - rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL) - return 0; - - /* check if spectral scan bit is set. This does not have to be checked - * if received through a SPECTRAL phy error, but shouldn't hurt. - */ - radar_info = ((struct ath_radar_info *)&vdata[len]) - 1; - if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) - return 0; - - chan_type = cfg80211_get_chandef_type(&common->hw->conf.chandef); - if ((chan_type == NL80211_CHAN_HT40MINUS) || - (chan_type == NL80211_CHAN_HT40PLUS)) { - fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; - num_bins = SPECTRAL_HT20_40_NUM_BINS; - bins = (u8 *)fft_sample_40.data; - } else { - fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN; - num_bins = SPECTRAL_HT20_NUM_BINS; - bins = (u8 *)fft_sample_20.data; - } - - /* Variation in the data length is possible and will be fixed later */ - if ((len > fft_len + 2) || (len < fft_len - 1)) - return 1; - - switch (len - fft_len) { - case 0: - /* length correct, nothing to do. */ - memcpy(bins, vdata, num_bins); - break; - case -1: - /* first byte missing, duplicate it. */ - memcpy(&bins[1], vdata, num_bins - 1); - bins[0] = vdata[0]; - break; - case 2: - /* MAC added 2 extra bytes at bin 30 and 32, remove them. */ - memcpy(bins, vdata, 30); - bins[30] = vdata[31]; - memcpy(&bins[31], &vdata[33], num_bins - 31); - break; - case 1: - /* MAC added 2 extra bytes AND first byte is missing. */ - bins[0] = vdata[0]; - memcpy(&bins[1], vdata, 30); - bins[31] = vdata[31]; - memcpy(&bins[32], &vdata[33], num_bins - 32); - break; - default: - return 1; - } - - /* DC value (value in the middle) is the blind spot of the spectral - * sample and invalid, interpolate it. - */ - dc_pos = num_bins / 2; - bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; - - if ((chan_type == NL80211_CHAN_HT40MINUS) || - (chan_type == NL80211_CHAN_HT40PLUS)) { - s8 lower_rssi, upper_rssi; - s16 ext_nf; - u8 lower_max_index, upper_max_index; - u8 lower_bitmap_w, upper_bitmap_w; - u16 lower_mag, upper_mag; - struct ath9k_hw_cal_data *caldata = ah->caldata; - struct ath_ht20_40_mag_info *mag_info; - - if (caldata) - ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan, - caldata->nfCalHist[3].privNF); - else - ext_nf = ATH_DEFAULT_NOISE_FLOOR; - - length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv); - fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40; - fft_sample_40.tlv.length = __cpu_to_be16(length); - fft_sample_40.freq = __cpu_to_be16(freq); - fft_sample_40.channel_type = chan_type; - - if (chan_type == NL80211_CHAN_HT40PLUS) { - lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]); - upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]); - - fft_sample_40.lower_noise = ah->noise; - fft_sample_40.upper_noise = ext_nf; - } else { - lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]); - upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]); - - fft_sample_40.lower_noise = ext_nf; - fft_sample_40.upper_noise = ah->noise; - } - fft_sample_40.lower_rssi = lower_rssi; - fft_sample_40.upper_rssi = upper_rssi; - - mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1; - lower_mag = spectral_max_magnitude(mag_info->lower_bins); - upper_mag = spectral_max_magnitude(mag_info->upper_bins); - fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag); - fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag); - lower_max_index = spectral_max_index(mag_info->lower_bins); - upper_max_index = spectral_max_index(mag_info->upper_bins); - fft_sample_40.lower_max_index = lower_max_index; - fft_sample_40.upper_max_index = upper_max_index; - lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins); - upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins); - fft_sample_40.lower_bitmap_weight = lower_bitmap_w; - fft_sample_40.upper_bitmap_weight = upper_bitmap_w; - fft_sample_40.max_exp = mag_info->max_exp & 0xf; - - fft_sample_40.tsf = __cpu_to_be64(tsf); - - tlv = (struct fft_sample_tlv *)&fft_sample_40; - } else { - u8 max_index, bitmap_w; - u16 magnitude; - struct ath_ht20_mag_info *mag_info; - - length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv); - fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20; - fft_sample_20.tlv.length = __cpu_to_be16(length); - fft_sample_20.freq = __cpu_to_be16(freq); - - fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]); - fft_sample_20.noise = ah->noise; - - mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; - magnitude = spectral_max_magnitude(mag_info->all_bins); - fft_sample_20.max_magnitude = __cpu_to_be16(magnitude); - max_index = spectral_max_index(mag_info->all_bins); - fft_sample_20.max_index = max_index; - bitmap_w = spectral_bitmap_weight(mag_info->all_bins); - fft_sample_20.bitmap_weight = bitmap_w; - fft_sample_20.max_exp = mag_info->max_exp & 0xf; - - fft_sample_20.tsf = __cpu_to_be64(tsf); - - tlv = (struct fft_sample_tlv *)&fft_sample_20; - } - - ath_debug_send_fft_sample(spec_priv, tlv); - - return 1; -} - -/*********************/ -/* spectral_scan_ctl */ -/*********************/ - -static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - char *mode = ""; - unsigned int len; - - switch (spec_priv->spectral_mode) { - case SPECTRAL_DISABLED: - mode = "disable"; - break; - case SPECTRAL_BACKGROUND: - mode = "background"; - break; - case SPECTRAL_CHANSCAN: - mode = "chanscan"; - break; - case SPECTRAL_MANUAL: - mode = "manual"; - break; - } - len = strlen(mode); - return simple_read_from_buffer(user_buf, count, ppos, mode, len); -} - -void ath9k_spectral_scan_trigger(struct ath_common *common, - struct ath_spec_scan_priv *spec_priv) -{ - struct ath_hw *ah = spec_priv->ah; - u32 rxfilter; - - if (config_enabled(CONFIG_ATH9K_TX99)) - return; - - if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { - ath_err(common, "spectrum analyzer not implemented on this hardware\n"); - return; - } - - ath_ps_ops(common)->wakeup(common); - rxfilter = ath9k_hw_getrxfilter(ah); - ath9k_hw_setrxfilter(ah, rxfilter | - ATH9K_RX_FILTER_PHYRADAR | - ATH9K_RX_FILTER_PHYERR); - - /* TODO: usually this should not be neccesary, but for some reason - * (or in some mode?) the trigger must be called after the - * configuration, otherwise the register will have its values reset - * (on my ar9220 to value 0x01002310) - */ - ath9k_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode); - ath9k_hw_ops(ah)->spectral_scan_trigger(ah); - ath_ps_ops(common)->restore(common); -} - -int ath9k_spectral_scan_config(struct ath_common *common, - struct ath_spec_scan_priv *spec_priv, - enum spectral_mode spectral_mode) -{ - struct ath_hw *ah = spec_priv->ah; - - if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { - ath_err(common, "spectrum analyzer not implemented on this hardware\n"); - return -1; - } - - switch (spectral_mode) { - case SPECTRAL_DISABLED: - spec_priv->spec_config.enabled = 0; - break; - case SPECTRAL_BACKGROUND: - /* send endless samples. - * TODO: is this really useful for "background"? - */ - spec_priv->spec_config.endless = 1; - spec_priv->spec_config.enabled = 1; - break; - case SPECTRAL_CHANSCAN: - case SPECTRAL_MANUAL: - spec_priv->spec_config.endless = 0; - spec_priv->spec_config.enabled = 1; - break; - default: - return -1; - } - - ath_ps_ops(common)->wakeup(common); - ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config); - ath_ps_ops(common)->restore(common); - - spec_priv->spectral_mode = spectral_mode; - - return 0; -} - -static ssize_t write_file_spec_scan_ctl(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - struct ath_common *common = ath9k_hw_common(spec_priv->ah); - char buf[32]; - ssize_t len; - - if (config_enabled(CONFIG_ATH9K_TX99)) - return -EOPNOTSUPP; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - - if (strncmp("trigger", buf, 7) == 0) { - ath9k_spectral_scan_trigger(common, spec_priv); - } else if (strncmp("background", buf, 10) == 0) { - ath9k_spectral_scan_config(common, spec_priv, SPECTRAL_BACKGROUND); - ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); - } else if (strncmp("chanscan", buf, 8) == 0) { - ath9k_spectral_scan_config(common, spec_priv, SPECTRAL_CHANSCAN); - ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); - } else if (strncmp("manual", buf, 6) == 0) { - ath9k_spectral_scan_config(common, spec_priv, SPECTRAL_MANUAL); - ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); - } else if (strncmp("disable", buf, 7) == 0) { - ath9k_spectral_scan_config(common, spec_priv, SPECTRAL_DISABLED); - ath_dbg(common, CONFIG, "spectral scan: disabled\n"); - } else { - return -EINVAL; - } - - return count; -} - -static const struct file_operations fops_spec_scan_ctl = { - .read = read_file_spec_scan_ctl, - .write = write_file_spec_scan_ctl, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -/*************************/ -/* spectral_short_repeat */ -/*************************/ - -static ssize_t read_file_spectral_short_repeat(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - char buf[32]; - unsigned int len; - - len = sprintf(buf, "%d\n", spec_priv->spec_config.short_repeat); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_spectral_short_repeat(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; - - if (val > 1) - return -EINVAL; - - spec_priv->spec_config.short_repeat = val; - return count; -} - -static const struct file_operations fops_spectral_short_repeat = { - .read = read_file_spectral_short_repeat, - .write = write_file_spectral_short_repeat, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -/******************/ -/* spectral_count */ -/******************/ - -static ssize_t read_file_spectral_count(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - char buf[32]; - unsigned int len; - - len = sprintf(buf, "%d\n", spec_priv->spec_config.count); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_spectral_count(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; - - if (val > 255) - return -EINVAL; - - spec_priv->spec_config.count = val; - return count; -} - -static const struct file_operations fops_spectral_count = { - .read = read_file_spectral_count, - .write = write_file_spectral_count, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -/*******************/ -/* spectral_period */ -/*******************/ - -static ssize_t read_file_spectral_period(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - char buf[32]; - unsigned int len; - - len = sprintf(buf, "%d\n", spec_priv->spec_config.period); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_spectral_period(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; - - if (val > 255) - return -EINVAL; - - spec_priv->spec_config.period = val; - return count; -} - -static const struct file_operations fops_spectral_period = { - .read = read_file_spectral_period, - .write = write_file_spectral_period, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -/***********************/ -/* spectral_fft_period */ -/***********************/ - -static ssize_t read_file_spectral_fft_period(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - char buf[32]; - unsigned int len; - - len = sprintf(buf, "%d\n", spec_priv->spec_config.fft_period); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_spectral_fft_period(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_spec_scan_priv *spec_priv = file->private_data; - unsigned long val; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - - buf[len] = '\0'; - if (kstrtoul(buf, 0, &val)) - return -EINVAL; - - if (val > 15) - return -EINVAL; - - spec_priv->spec_config.fft_period = val; - return count; -} - -static const struct file_operations fops_spectral_fft_period = { - .read = read_file_spectral_fft_period, - .write = write_file_spectral_fft_period, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -/*******************/ -/* Relay interface */ -/*******************/ - -static struct dentry *create_buf_file_handler(const char *filename, - struct dentry *parent, - umode_t mode, - struct rchan_buf *buf, - int *is_global) -{ - struct dentry *buf_file; - - buf_file = debugfs_create_file(filename, mode, parent, buf, - &relay_file_operations); - *is_global = 1; - return buf_file; -} - -static int remove_buf_file_handler(struct dentry *dentry) -{ - debugfs_remove(dentry); - - return 0; -} - -static struct rchan_callbacks rfs_spec_scan_cb = { - .create_buf_file = create_buf_file_handler, - .remove_buf_file = remove_buf_file_handler, -}; - -/*********************/ -/* Debug Init/Deinit */ -/*********************/ - -void ath9k_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) -{ - if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { - relay_close(spec_priv->rfs_chan_spec_scan); - spec_priv->rfs_chan_spec_scan = NULL; - } -} - -void ath9k_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy) -{ - spec_priv->rfs_chan_spec_scan = relay_open("spectral_scan", - debugfs_phy, - 1024, 256, &rfs_spec_scan_cb, - NULL); - debugfs_create_file("spectral_scan_ctl", - S_IRUSR | S_IWUSR, - debugfs_phy, spec_priv, - &fops_spec_scan_ctl); - debugfs_create_file("spectral_short_repeat", - S_IRUSR | S_IWUSR, - debugfs_phy, spec_priv, - &fops_spectral_short_repeat); - debugfs_create_file("spectral_count", - S_IRUSR | S_IWUSR, - debugfs_phy, spec_priv, - &fops_spectral_count); - debugfs_create_file("spectral_period", - S_IRUSR | S_IWUSR, - debugfs_phy, spec_priv, - &fops_spectral_period); - debugfs_create_file("spectral_fft_period", - S_IRUSR | S_IWUSR, - debugfs_phy, spec_priv, - &fops_spectral_fft_period); -} diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h deleted file mode 100644 index 77582cf743ac..000000000000 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2013 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef SPECTRAL_H -#define SPECTRAL_H - -#include "../spectral_common.h" - -/* enum spectral_mode: - * - * @SPECTRAL_DISABLED: spectral mode is disabled - * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with - * something else. - * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples - * is performed manually. - * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels - * during a channel scan. - */ -enum spectral_mode { - SPECTRAL_DISABLED = 0, - SPECTRAL_BACKGROUND, - SPECTRAL_MANUAL, - SPECTRAL_CHANSCAN, -}; - -#define SPECTRAL_SCAN_BITMASK 0x10 -/* Radar info packet format, used for DFS and spectral formats. */ -struct ath_radar_info { - u8 pulse_length_pri; - u8 pulse_length_ext; - u8 pulse_bw_info; -} __packed; - -/* The HT20 spectral data has 4 bytes of additional information at it's end. - * - * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]} - * [7:0]: all bins max_magnitude[9:2] - * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]} - * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) - */ -struct ath_ht20_mag_info { - u8 all_bins[3]; - u8 max_exp; -} __packed; - -/* WARNING: don't actually use this struct! MAC may vary the amount of - * data by -1/+2. This struct is for reference only. - */ -struct ath_ht20_fft_packet { - u8 data[SPECTRAL_HT20_NUM_BINS]; - struct ath_ht20_mag_info mag_info; - struct ath_radar_info radar_info; -} __packed; - -#define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet)) - -/* Dynamic 20/40 mode: - * - * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]} - * [7:0]: lower bins max_magnitude[9:2] - * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]} - * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]} - * [7:0]: upper bins max_magnitude[9:2] - * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]} - * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) - */ -struct ath_ht20_40_mag_info { - u8 lower_bins[3]; - u8 upper_bins[3]; - u8 max_exp; -} __packed; - -/* WARNING: don't actually use this struct! MAC may vary the amount of - * data. This struct is for reference only. - */ -struct ath_ht20_40_fft_packet { - u8 data[SPECTRAL_HT20_40_NUM_BINS]; - struct ath_ht20_40_mag_info mag_info; - struct ath_radar_info radar_info; -} __packed; - -struct ath_spec_scan_priv { - struct ath_hw *ah; - /* relay(fs) channel for spectral scan */ - struct rchan *rfs_chan_spec_scan; - enum spectral_mode spectral_mode; - struct ath_spec_scan spec_config; -}; - -#define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) - -/* grabs the max magnitude from the all/upper/lower bins */ -static inline u16 spectral_max_magnitude(u8 *bins) -{ - return (bins[0] & 0xc0) >> 6 | - (bins[1] & 0xff) << 2 | - (bins[2] & 0x03) << 10; -} - -/* return the max magnitude from the all/upper/lower bins */ -static inline u8 spectral_max_index(u8 *bins) -{ - s8 m = (bins[2] & 0xfc) >> 2; - - /* TODO: this still doesn't always report the right values ... */ - if (m > 32) - m |= 0xe0; - else - m &= ~0xe0; - - return m + 29; -} - -/* return the bitmap weight from the all/upper/lower bins */ -static inline u8 spectral_bitmap_weight(u8 *bins) -{ - return bins[0] & 0x3f; -} - -void ath9k_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); -void ath9k_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); - -void ath9k_spectral_scan_trigger(struct ath_common *common, - struct ath_spec_scan_priv *spec_priv); -int ath9k_spectral_scan_config(struct ath_common *common, - struct ath_spec_scan_priv *spec_priv, - enum spectral_mode spectral_mode); - -#ifdef CONFIG_ATH9K_DEBUGFS -int ath_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, - struct ath_rx_status *rs, u64 tsf); -#else -static inline int ath_process_fft(struct ath_spec_scan_priv *spec_priv, - struct ieee80211_hdr *hdr, - struct ath_rx_status *rs, u64 tsf) -{ - return 0; -} -#endif /* CONFIG_ATH9K_DEBUGFS */ - -#endif /* SPECTRAL_H */ -- cgit v1.2.3 From 46140ddf169703ef0538bf00098233b24b2269e8 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:31 +0100 Subject: ath9k: For AR9271 chipsets, set count = 0 for endless samples. not sure why. Initially provided by Ashish Patro Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_phy.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 9a2afa2c690b..fc08162b5820 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -643,9 +643,12 @@ static void ar9002_hw_spectral_scan_config(struct ath_hw *ah, * and fix otherwise. */ count = param->count; - if (param->endless) - count = 0x80; - else if (count & 0x80) + if (param->endless) { + if (AR_SREV_9271(ah)) + count = 0; + else + count = 0x80; + } else if (count & 0x80) count = 0x7f; REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, -- cgit v1.2.3 From 525d09456b9fc2f769647c744c75629d9926fb9e Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:32 +0100 Subject: ath9k_htc: fix rs_datalen conversation For some reason it didn't coused obvious problems. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index f0484b1b617e..2622002845ce 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -946,7 +946,7 @@ static inline void convert_htc_flag(struct ath_rx_status *rx_stats, static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats, struct ath_htc_rx_status *rxstatus) { - rx_stats->rs_datalen = rxstatus->rs_datalen; + rx_stats->rs_datalen = be16_to_cpu(rxstatus->rs_datalen); rx_stats->rs_status = rxstatus->rs_status; rx_stats->rs_phyerr = rxstatus->rs_phyerr; rx_stats->rs_rssi = rxstatus->rs_rssi; -- cgit v1.2.3 From 94cd95c217a5ed4c45e2a8c97043c3efcd66dac9 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:33 +0100 Subject: ath9k_htc: add ath_ps_ops bindings Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 4014c4be6e79..f91b8e6b14bc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -53,6 +53,21 @@ static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { }; #endif +void ath9k_htc_op_ps_wakeup(struct ath_common *common) +{ + ath9k_htc_ps_wakeup((struct ath9k_htc_priv *) common->priv); +} + +void ath9k_htc_op_ps_restore(struct ath_common *common) +{ + ath9k_htc_ps_restore((struct ath9k_htc_priv *) common->priv); +} + +struct ath_ps_ops ath9k_htc_ps_ops = { + .wakeup = ath9k_htc_op_ps_wakeup, + .restore = ath9k_htc_op_ps_restore, +}; + static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) { int time_left; @@ -478,6 +493,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, common = ath9k_hw_common(ah); common->ops = &ah->reg_ops; + common->ps_ops = &ath9k_htc_ps_ops; common->bus_ops = &ath9k_usb_bus_ops; common->ah = ah; common->hw = priv->hw; -- cgit v1.2.3 From fe30e8bb5be52e2e6b913db77dda6c22b643dbd7 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:34 +0100 Subject: ath9k_htc: add struct ath_spec_scan_priv to ath9k_htc_priv Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 09a5d72f3ff5..1f019aa2d1f8 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -481,6 +481,7 @@ struct ath9k_htc_priv { unsigned long op_flags; struct ath9k_hw_cal_data caldata; + struct ath_spec_scan_priv spec_priv; spinlock_t beacon_lock; struct ath_beacon_config cur_beacon_conf; -- cgit v1.2.3 From 88a2e3fb7b7e9dd3c51ceef81e0415478c27910c Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:35 +0100 Subject: ath9k_htc: set initial spec_config values use values provided by Ashish Patro Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index f91b8e6b14bc..285d0ada369f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -464,6 +464,14 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) common->last_rssi = ATH_RSSI_DUMMY_MARKER; priv->ah->opmode = NL80211_IFTYPE_STATION; + + priv->spec_priv.ah = priv->ah; + priv->spec_priv.spec_config.enabled = 0; + priv->spec_priv.spec_config.short_repeat = false; + priv->spec_priv.spec_config.count = 8; + priv->spec_priv.spec_config.endless = false; + priv->spec_priv.spec_config.period = 0x12; + priv->spec_priv.spec_config.fft_period = 0x02; } static int ath9k_init_priv(struct ath9k_htc_priv *priv, -- cgit v1.2.3 From 911544f6a8d66c27ff807f5d71e3f0f5a904c100 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:36 +0100 Subject: ath9k_htc: trigger spectral scan on set_channel Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 994fff1ff519..689ac998b87e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -314,6 +314,10 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, mod_timer(&priv->tx.cleanup_timer, jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); + /* perform spectral scan if requested. */ + if (test_bit(ATH_OP_SCANNING, &common->op_flags) && + priv->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) + ath9k_cmn_spectral_scan_trigger(common, &priv->spec_priv); err: ath9k_htc_ps_restore(priv); return ret; -- cgit v1.2.3 From 83fb287ecd8ae60ed79c647a5df8beacdf4f4807 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:37 +0100 Subject: ath9k_htc: process rx spectral packets use code provided by Ashish Patro Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 2622002845ce..a0f58e2aa553 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -1012,6 +1012,20 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, * separately to avoid doing two lookups for a rate for each frame. */ hdr = (struct ieee80211_hdr *)skb->data; + + /* + * Process PHY errors and return so that the packet + * can be dropped. + */ + if (rx_stats.rs_status & ATH9K_RXERR_PHY) { + /* TODO: Not using DFS processing now. */ + if (ath_cmn_process_fft(&priv->spec_priv, hdr, + &rx_stats, rx_status->mactime)) { + /* TODO: Code to collect spectral scan statistics */ + } + goto rx_next; + } + if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats, &decrypt_error, priv->rxfilter)) goto rx_next; -- cgit v1.2.3 From 3f2aa13f6d16a53a4cf5de369c685c6f75fe4d58 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 6 Nov 2014 08:53:38 +0100 Subject: ath9k_htc: add spectral scan debug interface Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 2 ++ drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 6 ++++++ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 + 3 files changed, 9 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 1f019aa2d1f8..b34acdeb1f21 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -626,8 +626,10 @@ int ath9k_htc_resume(struct htc_target *htc_handle); #endif #ifdef CONFIG_ATH9K_HTC_DEBUGFS int ath9k_htc_init_debug(struct ath_hw *ah); +void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv); #else static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; +static inline void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv) { return 0; }; #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #endif /* HTC_H */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 8b529e4b8ac4..8cef1edcc621 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -490,6 +490,10 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw, WARN_ON(i != ATH9K_HTC_SSTATS_LEN); } +void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv) +{ + ath9k_cmn_spectral_deinit_debug(&priv->spec_priv); +} int ath9k_htc_init_debug(struct ath_hw *ah) { @@ -501,6 +505,8 @@ int ath9k_htc_init_debug(struct ath_hw *ah) if (!priv->debug.debugfs_phy) return -ENOMEM; + ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy); + debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, priv, &fops_tgt_int_stats); debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 285d0ada369f..ad8f1dcc9cd5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -102,6 +102,7 @@ static void ath9k_deinit_device(struct ath9k_htc_priv *priv) wiphy_rfkill_stop_polling(hw->wiphy); ath9k_deinit_leds(priv); + ath9k_htc_deinit_debug(priv); ieee80211_unregister_hw(hw); ath9k_rx_cleanup(priv); ath9k_tx_cleanup(priv); -- cgit v1.2.3 From a15c706889753a92ccf90a55516a4f0c87a02201 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 11 Nov 2014 17:12:17 -0500 Subject: ath9k_htc: remove return of value in empty definintion of ath9k_htc_deinit_debug Cc: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index b34acdeb1f21..9dde265d3f84 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -629,7 +629,9 @@ int ath9k_htc_init_debug(struct ath_hw *ah); void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv); #else static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; -static inline void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv) { return 0; }; +static inline void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv) +{ +} #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ #endif /* HTC_H */ -- cgit v1.2.3 From 325e188176681bdce0584154075e02c373794749 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Tue, 4 Nov 2014 15:22:49 -0800 Subject: ath9k: fix misc debugfs when not using chan context When channel-context is not enabled, all vifs belong to the first context, but it is not configured as 'assigned'. Fix misc debugfs file to print out info for non-assigned contexts, and also print whether ctx is assigned or not. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (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 db388405bf0c..3f21b1bbc52e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -828,13 +828,14 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, i = 0; ath_for_each_chanctx(sc, ctx) { - if (!ctx->assigned || list_empty(&ctx->vifs)) + if (list_empty(&ctx->vifs)) continue; ath9k_calculate_iter_data(sc, ctx, &iter_data); len += scnprintf(buf + len, sizeof(buf) - len, - "VIF-COUNTS: CTX %i AP: %i STA: %i MESH: %i WDS: %i", - i++, iter_data.naps, iter_data.nstations, + "VIFS: CTX %i(%i) AP: %i STA: %i MESH: %i WDS: %i", + i++, (int)(ctx->assigned), iter_data.naps, + iter_data.nstations, iter_data.nmeshes, iter_data.nwds); len += scnprintf(buf + len, sizeof(buf) - len, " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n", -- cgit v1.2.3 From d81f9a09bcd4fa3a4ba54bb02e94d2b6f30a889d Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Wed, 12 Nov 2014 06:19:48 +0800 Subject: ath9k: ath9k_op_ps_wakeup() can be static drivers/net/wireless/ath/ath9k/init.c:91:6: sparse: symbol 'ath9k_op_ps_wakeup' was not declared. Should it be static? drivers/net/wireless/ath/ath9k/init.c:96:6: sparse: symbol 'ath9k_op_ps_restore' was not declared. Should it be static? drivers/net/wireless/ath/ath9k/init.c:101:19: sparse: symbol 'ath9k_ps_ops' was not declared. Should it be static? Signed-off-by: Fengguang Wu Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 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 4124140a4d35..41736e5a49e0 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -88,17 +88,17 @@ static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = { static void ath9k_deinit_softc(struct ath_softc *sc); -void ath9k_op_ps_wakeup(struct ath_common *common) +static void ath9k_op_ps_wakeup(struct ath_common *common) { ath9k_ps_wakeup((struct ath_softc *) common->priv); } -void ath9k_op_ps_restore(struct ath_common *common) +static void ath9k_op_ps_restore(struct ath_common *common) { ath9k_ps_restore((struct ath_softc *) common->priv); } -struct ath_ps_ops ath9k_ps_ops = { +static struct ath_ps_ops ath9k_ps_ops = { .wakeup = ath9k_op_ps_wakeup, .restore = ath9k_op_ps_restore, }; -- cgit v1.2.3 From 7d031552661ba61f9f258ec21272b4eafa9c21b4 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Wed, 12 Nov 2014 06:24:17 +0800 Subject: ath9k_htc: ath9k_htc_op_ps_wakeup() can be static drivers/net/wireless/ath/ath9k/htc_drv_init.c:56:6: sparse: symbol 'ath9k_htc_op_ps_wakeup' was not declared. Should it be static? drivers/net/wireless/ath/ath9k/htc_drv_init.c:61:6: sparse: symbol 'ath9k_htc_op_ps_restore' was not declared. Should it be static? drivers/net/wireless/ath/ath9k/htc_drv_init.c:66:19: sparse: symbol 'ath9k_htc_ps_ops' was not declared. Should it be static? Signed-off-by: Fengguang Wu Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index ad8f1dcc9cd5..e8fa9448da24 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -53,17 +53,17 @@ static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { }; #endif -void ath9k_htc_op_ps_wakeup(struct ath_common *common) +static void ath9k_htc_op_ps_wakeup(struct ath_common *common) { ath9k_htc_ps_wakeup((struct ath9k_htc_priv *) common->priv); } -void ath9k_htc_op_ps_restore(struct ath_common *common) +static void ath9k_htc_op_ps_restore(struct ath_common *common) { ath9k_htc_ps_restore((struct ath9k_htc_priv *) common->priv); } -struct ath_ps_ops ath9k_htc_ps_ops = { +static struct ath_ps_ops ath9k_htc_ps_ops = { .wakeup = ath9k_htc_op_ps_wakeup, .restore = ath9k_htc_op_ps_restore, }; -- cgit v1.2.3 From 2eaea3284b082271315be815b762fdd02b007c32 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Wed, 12 Nov 2014 08:32:08 +0100 Subject: ath9k: common-spectral: don't depend from ATH9K_DEBUGFS we can have here two variants. Add ATH9K_CMN_DEBUGFS y if ATH9K_CMN_DEBUGFS || ATH9K_HTC_DEBUGFS wich will add more configurations and testcases. Or remove ATH9K_HTC_DEBUGFS which need more time to be done. So, make common-spectral ignore ATH9K_DEBUGFS option for now. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common-spectral.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.h b/drivers/net/wireless/ath/ath9k/common-spectral.h index 214c3baf5023..82d9dd29652c 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.h +++ b/drivers/net/wireless/ath/ath9k/common-spectral.h @@ -138,17 +138,7 @@ void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, int ath9k_cmn_spectral_scan_config(struct ath_common *common, struct ath_spec_scan_priv *spec_priv, enum spectral_mode spectral_mode); - -#ifdef CONFIG_ATH9K_DEBUGFS int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, struct ath_rx_status *rs, u64 tsf); -#else -static inline int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, - struct ieee80211_hdr *hdr, - struct ath_rx_status *rs, u64 tsf) -{ - return 0; -} -#endif /* CONFIG_ATH9K_DEBUGFS */ #endif /* SPECTRAL_H */ -- cgit v1.2.3 From 4b870c26e082cc950d91e54acd265fd640b9a56d Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Wed, 12 Nov 2014 16:40:19 +0800 Subject: ath9k: fix the assignment of hw queues for mesh interface We need to assign the hw queues for mesh interface. Otherwise, we are not able to bring up the mesh interface due to the IEEE80211_INVAL_HW_QUEUE error. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 3 ++- 1 file changed, 2 insertions(+), 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 1a88614eb73e..6aed6a236066 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1185,7 +1185,8 @@ static void ath9k_assign_hw_queues(struct ieee80211_hw *hw, for (i = 0; i < IEEE80211_NUM_ACS; i++) vif->hw_queue[i] = i; - if (vif->type == NL80211_IFTYPE_AP) + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT) vif->cab_queue = hw->queues - 2; else vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; -- cgit v1.2.3 From e6510b11209a4f4668924d9178ead304a692a9b2 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Sun, 16 Nov 2014 03:05:40 +0800 Subject: ath9k|ath9k_htc: Seperate the software crypto flag for Tx and Rx Use the sw_mgmt_crypto_tx flag to trigger the CCMP encryption for transmitted management frames to be done in software while the sw_mgmt_crypto_rx flag is used to trigger the CCMP decryption for received management frames to be done in software. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/common.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +- drivers/net/wireless/ath/ath9k/hw.c | 9 ++++++--- drivers/net/wireless/ath/ath9k/hw.h | 3 ++- drivers/net/wireless/ath/ath9k/main.c | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index c6dd7f1fed65..eb62c58dd0f7 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -159,7 +159,7 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, if (test_bit(keyix, common->keymap)) rxs->flag |= RX_FLAG_DECRYPTED; } - if (ah->sw_mgmt_crypto && + if (ah->sw_mgmt_crypto_rx && (rxs->flag & RX_FLAG_DECRYPTED) && ieee80211_is_mgmt(fc)) /* Use software decrypt for management frames. */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 689ac998b87e..c7d12efaa86a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1447,7 +1447,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; if (key->cipher == WLAN_CIPHER_SUITE_TKIP) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (priv->ah->sw_mgmt_crypto && + if (priv->ah->sw_mgmt_crypto_tx && key->cipher == WLAN_CIPHER_SUITE_CCMP) key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; ret = 0; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ee9fb52cec62..c1c2f2158b75 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1598,16 +1598,19 @@ static void ath9k_hw_init_mfp(struct ath_hw *ah) * frames when constructing CCMP AAD. */ REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, 0xc7ff); - ah->sw_mgmt_crypto = false; + ah->sw_mgmt_crypto_tx = false; + ah->sw_mgmt_crypto_rx = false; } else if (AR_SREV_9160_10_OR_LATER(ah)) { /* Disable hardware crypto for management frames */ REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); REG_SET_BIT(ah, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); - ah->sw_mgmt_crypto = true; + ah->sw_mgmt_crypto_tx = true; + ah->sw_mgmt_crypto_rx = true; } else { - ah->sw_mgmt_crypto = true; + ah->sw_mgmt_crypto_tx = true; + ah->sw_mgmt_crypto_rx = true; } } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e49721e85f6a..55ee0a5bc6fa 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -753,7 +753,8 @@ struct ath_hw { } eeprom; const struct eeprom_ops *eep_ops; - bool sw_mgmt_crypto; + bool sw_mgmt_crypto_tx; + bool sw_mgmt_crypto_rx; bool is_pciexpress; bool aspm_enabled; bool is_monitoring; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6aed6a236066..ca71f2fdc276 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1655,7 +1655,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; if (key->cipher == WLAN_CIPHER_SUITE_TKIP) key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (sc->sc_ah->sw_mgmt_crypto && + if (sc->sc_ah->sw_mgmt_crypto_tx && key->cipher == WLAN_CIPHER_SUITE_CCMP) key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; ret = 0; -- cgit v1.2.3 From 60fc4962549cf3acad85b67c6934785afa014b8e Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Sun, 16 Nov 2014 03:05:41 +0800 Subject: ath9k_htc: Enable software crypto for mgmt frame in Tx for USB devices In secured mesh, the unicast mgmt frame is encrypted using the same key that used for encrypting the unicast data frame. This patch "ath9k_htc_firmware: fix the offset of CCMP header for mesh data frame" applied to open-ath9k-htc-firmware allows the ath9k_htc to be loaded without "nohwcrypt=1". Unfortunately, this is not working and we still need CCMP encryption of transmitted management frames to be done in software. So this patch allows the software encryption for transmitted management frame to be done in software but remain the hardware decryption for received management frame. This patch is tested with the following hardwares: - TP-Link TL-WN821N v3 802.11n [Atheros AR7010+AR9287] - AR9271 802.11n and managed to work with peer mesh STA equipped with ath9k. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c1c2f2158b75..fa9e5e998337 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1598,7 +1598,10 @@ static void ath9k_hw_init_mfp(struct ath_hw *ah) * frames when constructing CCMP AAD. */ REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, 0xc7ff); - ah->sw_mgmt_crypto_tx = false; + if (AR_SREV_9271(ah) || AR_DEVID_7010(ah)) + ah->sw_mgmt_crypto_tx = true; + else + ah->sw_mgmt_crypto_tx = false; ah->sw_mgmt_crypto_rx = false; } else if (AR_SREV_9160_10_OR_LATER(ah)) { /* Disable hardware crypto for management frames */ -- cgit v1.2.3 From 459b1ec62224cd1d1588551eb78b1b0d81205f31 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:00 +0530 Subject: ath9k: Update QCA953x initvals * Duplicates have been marked. * New initvals for 1.1 and 2.0 versions. * xPA support. * Fix for low power issue. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar953x_initvals.h | 498 +++++++++++++++++++++-- 1 file changed, 468 insertions(+), 30 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h index 812a9d787bf3..159cc6fd2362 100644 --- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h @@ -20,6 +20,8 @@ #define qca953x_1p0_mac_postamble ar9300_2p2_mac_postamble +#define qca953x_1p0_soc_preamble ar955x_1p0_soc_preamble + #define qca953x_1p0_soc_postamble ar9300_2p2_soc_postamble #define qca953x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2 @@ -28,6 +30,10 @@ #define qca953x_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2 +#define qca953x_1p0_common_wo_xlna_rx_gain_bounds ar955x_1p0_common_wo_xlna_rx_gain_bounds + +#define qca953x_1p0_common_rx_gain_bounds ar955x_1p0_common_rx_gain_bounds + static const u32 qca953x_1p0_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, @@ -490,35 +496,6 @@ static const u32 qca953x_1p0_radio_postamble[][5] = { {0x00016540, 0x10804008, 0x10804008, 0x50804000, 0x50804000}, }; -static const u32 qca953x_1p0_soc_preamble[][2] = { - /* Addr allmodes */ - {0x00007000, 0x00000000}, - {0x00007004, 0x00000000}, - {0x00007008, 0x00000000}, - {0x0000700c, 0x00000000}, - {0x0000701c, 0x00000000}, - {0x00007020, 0x00000000}, - {0x00007024, 0x00000000}, - {0x00007028, 0x00000000}, - {0x0000702c, 0x00000000}, - {0x00007030, 0x00000000}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, - {0x00007048, 0x00000000}, -}; - -static const u32 qca953x_1p0_common_rx_gain_bounds[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018}, -}; - -static const u32 qca953x_1p0_common_wo_xlna_rx_gain_bounds[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, -}; - static const u32 qca953x_1p0_modes_xpa_tx_gain_table[][2] = { /* Addr allmodes */ {0x0000a2dc, 0xfffd5aaa}, @@ -715,8 +692,73 @@ static const u32 qca953x_1p1_modes_no_xpa_tx_gain_table[][2] = { {0x00016448, 0x6c927a70}, }; +static const u32 qca953x_1p1_modes_xpa_tx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a2dc, 0xfffb52aa}, + {0x0000a2e0, 0xfffd64cc}, + {0x0000a2e4, 0xfffe80f0}, + {0x0000a2e8, 0xffffff00}, + {0x0000a410, 0x000050d5}, + {0x0000a500, 0x00000000}, + {0x0000a504, 0x04000002}, + {0x0000a508, 0x08000004}, + {0x0000a50c, 0x0c000006}, + {0x0000a510, 0x1000000a}, + {0x0000a514, 0x1400000c}, + {0x0000a518, 0x1800000e}, + {0x0000a51c, 0x1c000048}, + {0x0000a520, 0x2000004a}, + {0x0000a524, 0x2400004c}, + {0x0000a528, 0x2800004e}, + {0x0000a52c, 0x2b00024a}, + {0x0000a530, 0x2f00024c}, + {0x0000a534, 0x3300024e}, + {0x0000a538, 0x36000668}, + {0x0000a53c, 0x38000669}, + {0x0000a540, 0x3a000868}, + {0x0000a544, 0x3d00086a}, + {0x0000a548, 0x4000086c}, + {0x0000a54c, 0x4200086e}, + {0x0000a550, 0x43000a6e}, + {0x0000a554, 0x43000a6e}, + {0x0000a558, 0x43000a6e}, + {0x0000a55c, 0x43000a6e}, + {0x0000a560, 0x43000a6e}, + {0x0000a564, 0x43000a6e}, + {0x0000a568, 0x43000a6e}, + {0x0000a56c, 0x43000a6e}, + {0x0000a570, 0x43000a6e}, + {0x0000a574, 0x43000a6e}, + {0x0000a578, 0x43000a6e}, + {0x0000a57c, 0x43000a6e}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x03804000}, + {0x0000a610, 0x03804e01}, + {0x0000a614, 0x03804e01}, + {0x0000a618, 0x03804e01}, + {0x0000a61c, 0x04009002}, + {0x0000a620, 0x04009002}, + {0x0000a624, 0x04009002}, + {0x0000a628, 0x04009002}, + {0x0000a62c, 0x04009002}, + {0x0000a630, 0x04009002}, + {0x0000a634, 0x04009002}, + {0x0000a638, 0x04009002}, + {0x0000a63c, 0x04009002}, + {0x0000b2dc, 0xfffb52aa}, + {0x0000b2e0, 0xfffd64cc}, + {0x0000b2e4, 0xfffe80f0}, + {0x0000b2e8, 0xffffff00}, + {0x00016044, 0x024922db}, + {0x00016048, 0x6c927a70}, + {0x00016444, 0x024922db}, + {0x00016448, 0x6c927a70}, +}; + static const u32 qca953x_2p0_baseband_core[][2] = { - /* Addr allmodes */ + /* Addr allmodes */ {0x00009800, 0xafe68e30}, {0x00009804, 0xfd14e000}, {0x00009808, 0x9c0a9f6b}, @@ -914,4 +956,400 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = { {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, }; +static const u32 qca953x_2p0_common_wo_xlna_rx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 qca953x_2p0_common_wo_xlna_rx_gain_bounds[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, +}; + +static const u32 qca953x_2p0_modes_xpa_tx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a2dc, 0xfffb52aa}, + {0x0000a2e0, 0xfffd64cc}, + {0x0000a2e4, 0xfffe80f0}, + {0x0000a2e8, 0xffffff00}, + {0x0000a410, 0x000050d5}, + {0x0000a500, 0x00000000}, + {0x0000a504, 0x04000002}, + {0x0000a508, 0x08000004}, + {0x0000a50c, 0x0c000006}, + {0x0000a510, 0x1000000a}, + {0x0000a514, 0x1400000c}, + {0x0000a518, 0x1800000e}, + {0x0000a51c, 0x1c000048}, + {0x0000a520, 0x2000004a}, + {0x0000a524, 0x2400004c}, + {0x0000a528, 0x2800004e}, + {0x0000a52c, 0x2b00024a}, + {0x0000a530, 0x2f00024c}, + {0x0000a534, 0x3300024e}, + {0x0000a538, 0x36000668}, + {0x0000a53c, 0x38000669}, + {0x0000a540, 0x3a000868}, + {0x0000a544, 0x3d00086a}, + {0x0000a548, 0x4000086c}, + {0x0000a54c, 0x4200086e}, + {0x0000a550, 0x43000a6e}, + {0x0000a554, 0x43000a6e}, + {0x0000a558, 0x43000a6e}, + {0x0000a55c, 0x43000a6e}, + {0x0000a560, 0x43000a6e}, + {0x0000a564, 0x43000a6e}, + {0x0000a568, 0x43000a6e}, + {0x0000a56c, 0x43000a6e}, + {0x0000a570, 0x43000a6e}, + {0x0000a574, 0x43000a6e}, + {0x0000a578, 0x43000a6e}, + {0x0000a57c, 0x43000a6e}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x03804000}, + {0x0000a610, 0x03804e01}, + {0x0000a614, 0x03804e01}, + {0x0000a618, 0x03804e01}, + {0x0000a61c, 0x04009002}, + {0x0000a620, 0x04009002}, + {0x0000a624, 0x04009002}, + {0x0000a628, 0x04009002}, + {0x0000a62c, 0x04009002}, + {0x0000a630, 0x04009002}, + {0x0000a634, 0x04009002}, + {0x0000a638, 0x04009002}, + {0x0000a63c, 0x04009002}, + {0x0000b2dc, 0xfffb52aa}, + {0x0000b2e0, 0xfffd64cc}, + {0x0000b2e4, 0xfffe80f0}, + {0x0000b2e8, 0xffffff00}, + {0x00016044, 0x024922db}, + {0x00016048, 0x6c927a70}, + {0x00016444, 0x024922db}, + {0x00016448, 0x6c927a70}, +}; + +static const u32 qca953x_2p0_modes_no_xpa_tx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a2dc, 0xffd5f552}, + {0x0000a2e0, 0xffe60664}, + {0x0000a2e4, 0xfff80780}, + {0x0000a2e8, 0xfffff800}, + {0x0000a410, 0x000050de}, + {0x0000a500, 0x00000061}, + {0x0000a504, 0x04000063}, + {0x0000a508, 0x08000065}, + {0x0000a50c, 0x0c000261}, + {0x0000a510, 0x10000263}, + {0x0000a514, 0x14000265}, + {0x0000a518, 0x18000482}, + {0x0000a51c, 0x1b000484}, + {0x0000a520, 0x1f000486}, + {0x0000a524, 0x240008c2}, + {0x0000a528, 0x28000cc1}, + {0x0000a52c, 0x2d000ce3}, + {0x0000a530, 0x31000ce5}, + {0x0000a534, 0x350010e5}, + {0x0000a538, 0x360012e5}, + {0x0000a53c, 0x380014e5}, + {0x0000a540, 0x3b0018e5}, + {0x0000a544, 0x3d001d04}, + {0x0000a548, 0x3e001d05}, + {0x0000a54c, 0x40001d07}, + {0x0000a550, 0x42001f27}, + {0x0000a554, 0x43001f67}, + {0x0000a558, 0x46001fe7}, + {0x0000a55c, 0x47001f2b}, + {0x0000a560, 0x49001f0d}, + {0x0000a564, 0x4b001ed2}, + {0x0000a568, 0x4c001ed4}, + {0x0000a56c, 0x4e001f15}, + {0x0000a570, 0x4f001ff6}, + {0x0000a574, 0x4f001ff6}, + {0x0000a578, 0x4f001ff6}, + {0x0000a57c, 0x4f001ff6}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x00804201}, + {0x0000a610, 0x01008201}, + {0x0000a614, 0x0180c402}, + {0x0000a618, 0x0180c603}, + {0x0000a61c, 0x0180c603}, + {0x0000a620, 0x01c10603}, + {0x0000a624, 0x01c10704}, + {0x0000a628, 0x02c18b05}, + {0x0000a62c, 0x02c14c07}, + {0x0000a630, 0x01008704}, + {0x0000a634, 0x01c10402}, + {0x0000a638, 0x0301cc07}, + {0x0000a63c, 0x0301cc07}, + {0x0000b2dc, 0xffd5f552}, + {0x0000b2e0, 0xffe60664}, + {0x0000b2e4, 0xfff80780}, + {0x0000b2e8, 0xfffff800}, + {0x00016044, 0x049242db}, + {0x00016048, 0x6c927a70}, + {0x00016444, 0x049242db}, + {0x00016448, 0x6c927a70}, +}; + #endif /* INITVALS_953X_H */ -- cgit v1.2.3 From 46270d077a761e72fc6ea5ec5a76c5ef2e61782b Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Sun, 16 Nov 2014 06:11:01 +0530 Subject: ath9k: Use new QCA953x initvals This patch updates the initvals for QCA953x v1.1 and v2.0 Signed-off-by: Miaoqing Pan Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 51 ++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index cb09102245b2..06ad2172030e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -333,12 +333,29 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) qca953x_1p0_soc_preamble); INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], qca953x_1p0_soc_postamble); - INIT_INI_ARRAY(&ah->iniModesRxGain, - qca953x_1p0_common_wo_xlna_rx_gain_table); - INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, - qca953x_1p0_common_wo_xlna_rx_gain_bounds); - INIT_INI_ARRAY(&ah->iniModesTxGain, - qca953x_1p0_modes_no_xpa_tx_gain_table); + + if (AR_SREV_9531_20(ah)) { + INIT_INI_ARRAY(&ah->iniModesRxGain, + qca953x_2p0_common_wo_xlna_rx_gain_table); + INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, + qca953x_2p0_common_wo_xlna_rx_gain_bounds); + } else { + INIT_INI_ARRAY(&ah->iniModesRxGain, + qca953x_1p0_common_wo_xlna_rx_gain_table); + INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, + qca953x_1p0_common_wo_xlna_rx_gain_bounds); + } + + if (AR_SREV_9531_20(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_2p0_modes_no_xpa_tx_gain_table); + else if (AR_SREV_9531_11(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_1p1_modes_no_xpa_tx_gain_table); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_1p0_modes_no_xpa_tx_gain_table); + INIT_INI_ARRAY(&ah->iniModesFastClock, qca953x_1p0_modes_fast_clock); } else if (AR_SREV_9580(ah)) { @@ -518,9 +535,15 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) else if (AR_SREV_9550(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar955x_1p0_modes_xpa_tx_gain_table); - else if (AR_SREV_9531(ah)) + else if (AR_SREV_9531_10(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_1p0_modes_xpa_tx_gain_table); + else if (AR_SREV_9531_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, - qca953x_1p0_modes_xpa_tx_gain_table); + qca953x_1p1_modes_xpa_tx_gain_table); + else if (AR_SREV_9531_20(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_2p0_modes_xpa_tx_gain_table); else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9580_1p0_lowest_ob_db_tx_gain_table); @@ -562,7 +585,10 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniModesTxGain, ar955x_1p0_modes_no_xpa_tx_gain_table); else if (AR_SREV_9531(ah)) { - if (AR_SREV_9531_11(ah)) + if (AR_SREV_9531_20(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_2p0_modes_no_xpa_tx_gain_table); + else if (AR_SREV_9531_11(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, qca953x_1p1_modes_no_xpa_tx_gain_table); else @@ -789,11 +815,16 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) ar955x_1p0_common_wo_xlna_rx_gain_table); INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, ar955x_1p0_common_wo_xlna_rx_gain_bounds); - } else if (AR_SREV_9531(ah)) { + } else if (AR_SREV_9531_10(ah) || AR_SREV_9531_11(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, qca953x_1p0_common_wo_xlna_rx_gain_table); INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, qca953x_1p0_common_wo_xlna_rx_gain_bounds); + } else if (AR_SREV_9531_20(ah)) { + INIT_INI_ARRAY(&ah->iniModesRxGain, + qca953x_2p0_common_wo_xlna_rx_gain_table); + INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, + qca953x_2p0_common_wo_xlna_rx_gain_bounds); } else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9580_1p0_wo_xlna_rx_gain_table); -- cgit v1.2.3 From aeeb2065794361f823e17a20af0db18b3a369845 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:02 +0530 Subject: ath9k: Fix LED configuration On some x86 platforms, the LED gpio is active high instead of active low. Identify such cards and modify the GPIO usage to make sure LED works properly. Cc: Russell Hu Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/gpio.c | 9 +++++++-- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 3 +++ drivers/net/wireless/ath/ath9k/main.c | 6 ++++-- drivers/net/wireless/ath/ath9k/pci.c | 4 +++- 6 files changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index d5a2019921bd..0f6db12967d9 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -931,6 +931,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); #define ATH9K_PCI_AR9565_2ANT 0x0100 #define ATH9K_PCI_NO_PLL_PWRSAVE 0x0200 #define ATH9K_PCI_KILLER 0x0400 +#define ATH9K_PCI_LED_ACT_HI 0x0800 /* * Default cache line size, in bytes. diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index b1956bf6e01e..2fef7a480fec 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -25,7 +25,12 @@ static void ath_led_brightness(struct led_classdev *led_cdev, enum led_brightness brightness) { struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF)); + u32 val = (brightness == LED_OFF); + + if (sc->sc_ah->config.led_active_high) + val = !val; + + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); } void ath_deinit_leds(struct ath_softc *sc) @@ -82,7 +87,7 @@ void ath_fill_led_pin(struct ath_softc *sc) ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); /* LED off, active low */ - ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1); } #endif diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 55ee0a5bc6fa..d2c044885aff 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -329,6 +329,7 @@ struct ath9k_ops_config { bool alt_mingainidx; bool no_pll_pwrsave; bool tx_gain_buffalo; + bool led_active_high; }; enum ath9k_int { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 41736e5a49e0..39157ca723d6 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -441,6 +441,9 @@ static void ath9k_init_pcoem_platform(struct ath_softc *sc) ah->config.no_pll_pwrsave = true; ath_info(common, "Disable PLL PowerSave\n"); } + + if (sc->driver_data & ATH9K_PCI_LED_ACT_HI) + ah->config.led_active_high = true; } static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index ca71f2fdc276..5a2a8d288487 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -727,7 +727,8 @@ static int ath9k_start(struct ieee80211_hw *hw) if (ah->led_pin >= 0) { ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ah->led_pin, 0); + ath9k_hw_set_gpio(ah, ah->led_pin, + (ah->config.led_active_high) ? 1 : 0); } /* @@ -869,7 +870,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) spin_lock_bh(&sc->sc_pcu_lock); if (ah->led_pin >= 0) { - ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_set_gpio(ah, ah->led_pin, + (ah->config.led_active_high) ? 0 : 1); ath9k_hw_cfg_gpio_input(ah, ah->led_pin); } diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index e3f60d5c5263..f009b5b57e5e 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -657,7 +657,9 @@ static const struct pci_device_id ath_pci_id_table[] = { 0x0036, PCI_VENDOR_ID_DELL, 0x020E), - .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, + .driver_data = ATH9K_PCI_AR9565_2ANT | + ATH9K_PCI_BT_ANT_DIV | + ATH9K_PCI_LED_ACT_HI}, /* PCI-E AR9565 (WB335) */ { PCI_VDEVICE(ATHEROS, 0x0036), -- cgit v1.2.3 From f4c34af4fcb8d28547fb96512f2389d79992cfcd Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:03 +0530 Subject: ath9k: Enable TSF2 for generic HW timers The base TSF is used for HW timers 0..7, but chips in the AR9003 family and above can support more generic timers. To use them, however, a second HW TSF needs to be enabled. This patch allows usage of the extra timers by starting the second TSF properly. The extra set of HW timers is apparently also present in AR9287, but we enable it only for the AR9003 family. Cc: Kobi Cohen-Arazi Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 23 ++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/hw.h | 2 ++ drivers/net/wireless/ath/ath9k/reg.h | 3 +++ 3 files changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index fa9e5e998337..19004dd26092 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1960,6 +1960,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REGWRITE_BUFFER_FLUSH(ah); + ath9k_hw_gen_timer_start_tsf2(ah); + ath9k_hw_init_desc(ah); if (ath9k_hw_btcoex_is_enabled(ah)) @@ -2924,6 +2926,16 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_gettsf32); +void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah) +{ + struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; + + if (timer_table->tsf2_enabled) { + REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN); + REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE); + } +} + struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, void (*trigger)(void *), void (*overflow)(void *), @@ -2934,7 +2946,11 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, struct ath_gen_timer *timer; if ((timer_index < AR_FIRST_NDP_TIMER) || - (timer_index >= ATH_MAX_GEN_TIMER)) + (timer_index >= ATH_MAX_GEN_TIMER)) + return NULL; + + if ((timer_index > AR_FIRST_NDP_TIMER) && + !AR_SREV_9300_20_OR_LATER(ah)) return NULL; timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); @@ -2948,6 +2964,11 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, timer->overflow = overflow; timer->arg = arg; + if ((timer_index > AR_FIRST_NDP_TIMER) && !timer_table->tsf2_enabled) { + timer_table->tsf2_enabled = true; + ath9k_hw_gen_timer_start_tsf2(ah); + } + return timer; } EXPORT_SYMBOL(ath_gen_timer_alloc); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d2c044885aff..893584b37bca 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -525,6 +525,7 @@ struct ath_gen_timer { struct ath_gen_timer_table { struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER]; u16 timer_mask; + bool tsf2_enabled; }; struct ath_hw_antcomb_conf { @@ -1037,6 +1038,7 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, u32 timer_next, u32 timer_period); +void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah); void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 1c0b1c1c5350..ced36b475acc 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1605,6 +1605,7 @@ enum { #define AR_RESET_TSF 0x8020 #define AR_RESET_TSF_ONCE 0x01000000 +#define AR_RESET_TSF2_ONCE 0x02000000 #define AR_MAX_CFP_DUR 0x8038 #define AR_CFP_VAL 0x0000FFFF @@ -1966,6 +1967,8 @@ enum { #define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 #define AR_MAC_PCU_GEN_TIMER_TSF_SEL 0x83d8 +#define AR_DIRECT_CONNECT 0x83a0 +#define AR_DC_AP_STA_EN 0x00000001 #define AR_AES_MUTE_MASK0 0x805c #define AR_AES_MUTE_MASK0_FC 0x0000FFFF -- cgit v1.2.3 From ee79ccd9ea8617220783ace007d722ed3815e00f Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:04 +0530 Subject: ath9k: Store the chip chainmask in HW capabilities Cc: Miaoqing Pan Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 20 ++++++++++---------- drivers/net/wireless/ath/ath9k/hw.h | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 19004dd26092..fbc78d80c559 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2341,7 +2341,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_common *common = ath9k_hw_common(ah); - unsigned int chip_chainmask; u16 eeval; u8 ant_div_ctl1, tx_chainmask, rx_chainmask; @@ -2385,15 +2384,16 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) AR_SREV_9285(ah) || AR_SREV_9330(ah) || AR_SREV_9565(ah)) - chip_chainmask = 1; - else if (AR_SREV_9462(ah)) - chip_chainmask = 3; + pCap->chip_chainmask = 1; else if (!AR_SREV_9280_20_OR_LATER(ah)) - chip_chainmask = 7; - else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah)) - chip_chainmask = 3; + pCap->chip_chainmask = 7; + else if (!AR_SREV_9300_20_OR_LATER(ah) || + AR_SREV_9340(ah) || + AR_SREV_9462(ah) || + AR_SREV_9531(ah)) + pCap->chip_chainmask = 3; else - chip_chainmask = 7; + pCap->chip_chainmask = 7; pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); /* @@ -2411,8 +2411,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) /* Use rx_chainmask from EEPROM. */ pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); - pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask); - pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask); + pCap->tx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->tx_chainmask); + pCap->rx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->rx_chainmask); ah->txchainmask = pCap->tx_chainmask; ah->rxchainmask = pCap->rx_chainmask; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 893584b37bca..4cf9e0ac0743 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -276,6 +276,7 @@ struct ath9k_hw_capabilities { u16 rts_aggr_limit; u8 tx_chainmask; u8 rx_chainmask; + u8 chip_chainmask; u8 max_txchains; u8 max_rxchains; u8 num_gpio_pins; -- cgit v1.2.3 From 89b6e35c2032d74f51333fbf3635d980b3311c68 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:05 +0530 Subject: ath9k: Fix thermometer programming The registers that control the on-chip thermometer need to be programmed based on the chainmask that the solution supports, not the chainmask that is present in the eeprom. Cc: Miaoqing Pan Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 80c6eacbda53..e726e405152c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4079,27 +4079,28 @@ static int ar9003_hw_get_thermometer(struct ath_hw *ah) static void ar9003_hw_thermometer_apply(struct ath_hw *ah) { + struct ath9k_hw_capabilities *pCap = &ah->caps; int thermometer = ar9003_hw_get_thermometer(ah); u8 therm_on = (thermometer < 0) ? 0 : 1; REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); - if (ah->caps.tx_chainmask & BIT(1)) + if (pCap->chip_chainmask & BIT(1)) REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); - if (ah->caps.tx_chainmask & BIT(2)) + if (pCap->chip_chainmask & BIT(2)) REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); therm_on = (thermometer < 0) ? 0 : (thermometer == 0); REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); - if (ah->caps.tx_chainmask & BIT(1)) { + if (pCap->chip_chainmask & BIT(1)) { therm_on = (thermometer < 0) ? 0 : (thermometer == 1); REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); } - if (ah->caps.tx_chainmask & BIT(2)) { + if (pCap->chip_chainmask & BIT(2)) { therm_on = (thermometer < 0) ? 0 : (thermometer == 2); REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); -- cgit v1.2.3 From e21a1d8b2b92e78fca0b4ee48681aa03dd671f88 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:06 +0530 Subject: ath9k: Clear offchannel state properly When a pending roc or scan operation is cancelled, the offchannel operation is cleared, but the offchannel state in the main scheduler is not cleared. This causes problems since an active GO will try to process a stale offchannel request that was deferred earlier. Fix this by clearing the state when there is no pending offchannel (roc/scan) operation. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/channel.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 1dadf6d77a82..ee76682cc058 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -900,6 +900,11 @@ void ath_offchannel_next(struct ath_softc *sc) sc->offchannel.state = ATH_OFFCHANNEL_ROC_START; ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan); } else { + spin_lock_bh(&sc->chan_lock); + sc->sched.offchannel_pending = false; + sc->sched.wait_switch = false; + spin_unlock_bh(&sc->chan_lock); + ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false), NULL); sc->offchannel.state = ATH_OFFCHANNEL_IDLE; -- cgit v1.2.3 From 6185672abad996fa520b0b4c77c30258634ee07f Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:07 +0530 Subject: ath9k: Cancel pending offchannel operations This patch makes sure that pending roc/scan operations are cancelled properly when a new context is assigned/unassigned. The flush_work() call to flush out any scheduled channel context work is removed, instead, sc->mutex is dropped to allow any pending work to get a chance to complete by the channel scheduler. Also, increase the timeout to allow a switch to an active GO. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 43 ++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 13 deletions(-) (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 5a2a8d288487..a6cb15c96052 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2196,6 +2196,28 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT +static void ath9k_cancel_pending_offchannel(struct ath_softc *sc) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + + if (sc->offchannel.roc_vif) { + ath_dbg(common, CHAN_CTX, + "%s: Aborting RoC\n", __func__); + + del_timer_sync(&sc->offchannel.timer); + if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START) + ath_roc_complete(sc, true); + } + + if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { + ath_dbg(common, CHAN_CTX, + "%s: Aborting HW scan\n", __func__); + + del_timer_sync(&sc->offchannel.timer); + ath_scan_complete(sc, true); + } +} + static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) { @@ -2382,6 +2404,8 @@ static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw, struct ath_chanctx *ctx = ath_chanctx_get(conf); int i; + ath9k_cancel_pending_offchannel(sc); + mutex_lock(&sc->mutex); ath_dbg(common, CHAN_CTX, @@ -2411,6 +2435,8 @@ static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ath_chanctx *ctx = ath_chanctx_get(conf); int ac; + ath9k_cancel_pending_offchannel(sc); + mutex_lock(&sc->mutex); ath_dbg(common, CHAN_CTX, @@ -2456,18 +2482,7 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw, if (!changed) goto out; - if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { - ath_dbg(common, CHAN_CTX, - "%s: Aborting HW scan\n", __func__); - - mutex_unlock(&sc->mutex); - - del_timer_sync(&sc->offchannel.timer); - ath_scan_complete(sc, true); - flush_work(&sc->chanctx_work); - - mutex_lock(&sc->mutex); - } + ath9k_cancel_pending_offchannel(sc); go_ctx = ath_is_go_chanctx_present(sc); @@ -2482,13 +2497,15 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw, beacon_int = TU_TO_USEC(cur_conf->beacon_interval); spin_unlock_bh(&sc->chan_lock); - timeout = usecs_to_jiffies(beacon_int); + timeout = usecs_to_jiffies(beacon_int * 2); init_completion(&sc->go_beacon); + mutex_unlock(&sc->mutex); if (wait_for_completion_timeout(&sc->go_beacon, timeout) == 0) ath_dbg(common, CHAN_CTX, "Failed to send new NoA\n"); + mutex_lock(&sc->mutex); } ath_dbg(common, CHAN_CTX, -- cgit v1.2.3 From 2c3634a8d4c66f743d11dab03d0e66d77b6aac05 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:08 +0530 Subject: ath9k: Handle failure to send NoA If for some reason a beacon with a new NoA is not sent out, then reset the mgd_prepare_tx flag. Not doing this will result in a situation where a GO will send a new NoA when it shouldn't. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 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 a6cb15c96052..5f16630f26ce 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2501,10 +2501,17 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw, init_completion(&sc->go_beacon); mutex_unlock(&sc->mutex); + if (wait_for_completion_timeout(&sc->go_beacon, - timeout) == 0) + timeout) == 0) { ath_dbg(common, CHAN_CTX, "Failed to send new NoA\n"); + + spin_lock_bh(&sc->chan_lock); + sc->sched.mgd_prepare_tx = false; + spin_unlock_bh(&sc->chan_lock); + } + mutex_lock(&sc->mutex); } -- cgit v1.2.3 From d9092c9873739429c9e97c4bc21ead9af2fb6aa1 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:09 +0530 Subject: ath9k: Adjust tbtt delta properly In a GO/STA setup, when we switch to the STA context, the channel context timer is scheduled with a period of half the beacon interval. If a beacon is received in this duration, the timer is adjusted to accommodate TSF sync done by the HW. But, if the actual channel switch is delayed for some reason, we end up rearming the timer every time a new beacon is received. Avoid this by doing the adjustment only once. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/channel.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0f6db12967d9..abe8bd6b972d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -381,6 +381,7 @@ enum ath_chanctx_state { struct ath_chanctx_sched { bool beacon_pending; + bool beacon_adjust; bool offchannel_pending; bool wait_switch; bool force_noa_update; diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index ee76682cc058..99425fe13055 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -659,6 +659,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, sc->sched.beacon_miss = 0; if (sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE || + !sc->sched.beacon_adjust || !sc->cur_chan->tsf_val) break; @@ -672,7 +673,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL); tsf_time += ath9k_hw_gettsf32(ah); - + sc->sched.beacon_adjust = false; ath_chanctx_setup_timer(sc, tsf_time); break; case ATH_CHANCTX_EVENT_AUTHORIZED: @@ -717,6 +718,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, ath_chanctx_setup_timer(sc, tsf_time); sc->sched.beacon_pending = true; + sc->sched.beacon_adjust = true; break; case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL: if (sc->cur_chan == &sc->offchannel.chan || -- cgit v1.2.3 From 47b6308b643302e642ca2a5cb6470926f7e1c428 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Sun, 16 Nov 2014 06:11:10 +0530 Subject: ath9k: Move roc completion to the offchannel timer Currently, when a roc period expires, the offchannel timer calls ieee80211_remain_on_channel_expired(), but the roc state is cleared only when the queued work to switch to the operating channel gets a chance to run. This race is a problem because mac80211 can issue a new roc request in this window. To avoid this, handle roc completion in the offchannel timer itself. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/channel.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 99425fe13055..794d52016437 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -926,8 +926,7 @@ void ath_roc_complete(struct ath_softc *sc, bool abort) sc->offchannel.roc_vif = NULL; sc->offchannel.roc_chan = NULL; - if (abort) - ieee80211_remain_on_channel_expired(sc->hw); + ieee80211_remain_on_channel_expired(sc->hw); ath_offchannel_next(sc); ath9k_ps_restore(sc); } @@ -1058,10 +1057,8 @@ static void ath_offchannel_timer(unsigned long data) break; case ATH_OFFCHANNEL_ROC_START: case ATH_OFFCHANNEL_ROC_WAIT: - ctx = ath_chanctx_get_oper_chan(sc, false); sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE; - ieee80211_remain_on_channel_expired(sc->hw); - ath_chanctx_switch(sc, ctx, NULL); + ath_roc_complete(sc, false); break; default: break; @@ -1191,7 +1188,6 @@ static void ath_offchannel_channel_change(struct ath_softc *sc) ieee80211_ready_on_channel(sc->hw); break; case ATH_OFFCHANNEL_ROC_DONE: - ath_roc_complete(sc, false); break; default: break; -- cgit v1.2.3 From a344d6778a98e4c19ac871f369e399e6356edcb3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 12 Jun 2014 22:24:31 +0200 Subject: mac80211: allow drivers to support NL80211_SCAN_FLAG_RANDOM_ADDR Allow drivers to support NL80211_SCAN_FLAG_RANDOM_ADDR with software based scanning and generate a random MAC address for them for every scan request with the flag. Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 6 ++- drivers/net/wireless/ath/ath9k/channel.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 7 +++- drivers/net/wireless/ath/ath9k/main.c | 7 +++- drivers/net/wireless/ath/wcn36xx/main.c | 7 +++- drivers/net/wireless/b43/main.c | 7 +++- .../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 7 +++- drivers/net/wireless/cw1200/scan.c | 2 +- drivers/net/wireless/mac80211_hwsim.c | 9 ++-- drivers/net/wireless/mwl8k.c | 7 +++- drivers/net/wireless/rt2x00/rt2x00.h | 7 +++- drivers/net/wireless/rt2x00/rt2x00mac.c | 7 +++- drivers/net/wireless/rtlwifi/core.c | 7 +++- drivers/net/wireless/ti/wl1251/main.c | 2 +- drivers/net/wireless/ti/wlcore/cmd.c | 2 +- drivers/staging/vt6656/main_usb.c | 7 +++- include/net/mac80211.h | 15 ++++--- net/mac80211/driver-ops.h | 15 ++++--- net/mac80211/ieee80211_i.h | 7 +++- net/mac80211/mlme.c | 8 ++-- net/mac80211/scan.c | 48 +++++++++++++++++----- net/mac80211/trace.h | 31 +++++++++++--- net/mac80211/tx.c | 9 ++-- net/mac80211/util.c | 12 +++--- 24 files changed, 166 insertions(+), 72 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index ab2709a43768..19eab2a69ad5 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -547,7 +547,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static void -ath5k_sw_scan_start(struct ieee80211_hw *hw) +ath5k_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct ath5k_hw *ah = hw->priv; if (!ah->assoc) @@ -556,7 +558,7 @@ ath5k_sw_scan_start(struct ieee80211_hw *hw) static void -ath5k_sw_scan_complete(struct ieee80211_hw *hw) +ath5k_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath5k_hw *ah = hw->priv; ath5k_hw_set_ledstate(ah, ah->assoc ? diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 794d52016437..206665059d66 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -963,7 +963,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, struct ieee80211_tx_info *info; int band = sc->offchannel.chan.chandef.chan->band; - skb = ieee80211_probereq_get(sc->hw, vif, + skb = ieee80211_probereq_get(sc->hw, vif->addr, ssid->ssid, ssid->ssid_len, req->ie_len); if (!skb) return; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index c7d12efaa86a..92d5a6c5a225 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1691,7 +1691,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, return ret; } -static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) +static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct ath9k_htc_priv *priv = hw->priv; struct ath_common *common = ath9k_hw_common(priv->ah); @@ -1705,7 +1707,8 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); } -static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) +static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct ath9k_htc_priv *priv = hw->priv; struct ath_common *common = ath9k_hw_common(priv->ah); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 5f16630f26ce..027ad715ffb2 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2180,14 +2180,17 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) return 0; } -static void ath9k_sw_scan_start(struct ieee80211_hw *hw) +static void ath9k_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); set_bit(ATH_OP_SCANNING, &common->op_flags); } -static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) +static void ath9k_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index b71d2b33532d..267c35d1f699 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -494,7 +494,9 @@ out: return ret; } -static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) +static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct wcn36xx *wcn = hw->priv; @@ -502,7 +504,8 @@ static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) wcn36xx_smd_start_scan(wcn); } -static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw) +static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct wcn36xx *wcn = hw->priv; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5d4173ee55bc..47731cb0d815 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -5110,7 +5110,9 @@ static void b43_op_sta_notify(struct ieee80211_hw *hw, B43_WARN_ON(!vif || wl->vif != vif); } -static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw) +static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; @@ -5124,7 +5126,8 @@ static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw) mutex_unlock(&wl->mutex); } -static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw) +static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 43c71bfaa474..f95b52442281 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -764,7 +764,9 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw, return; } -static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) +static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct brcms_info *wl = hw->priv; spin_lock_bh(&wl->lock); @@ -773,7 +775,8 @@ static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) return; } -static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw) +static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct brcms_info *wl = hw->priv; spin_lock_bh(&wl->lock); diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c index b2fb6c632092..f2e276faca70 100644 --- a/drivers/net/wireless/cw1200/scan.c +++ b/drivers/net/wireless/cw1200/scan.c @@ -78,7 +78,7 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS) return -EINVAL; - frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0, + frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0, req->ie_len); if (!frame.skb) return -ENOMEM; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 58f11bb0896f..6daaad595ea4 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1802,7 +1802,7 @@ static void hw_scan_work(struct work_struct *work) struct sk_buff *probe; probe = ieee80211_probereq_get(hwsim->hw, - hwsim->hw_scan_vif, + hwsim->hw_scan_vif->addr, req->ssids[i].ssid, req->ssids[i].ssid_len, req->ie_len); @@ -1866,7 +1866,9 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw, mutex_unlock(&hwsim->mutex); } -static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) +static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct mac80211_hwsim_data *hwsim = hw->priv; @@ -1884,7 +1886,8 @@ out: mutex_unlock(&hwsim->mutex); } -static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) +static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct mac80211_hwsim_data *hwsim = hw->priv; diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ef1104476bd8..b8d1e04aa9b9 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -5548,7 +5548,9 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return rc; } -static void mwl8k_sw_scan_start(struct ieee80211_hw *hw) +static void mwl8k_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct mwl8k_priv *priv = hw->priv; u8 tmp; @@ -5565,7 +5567,8 @@ static void mwl8k_sw_scan_start(struct ieee80211_hw *hw) priv->sw_scan_start = true; } -static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw) +static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; u8 tmp; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index d13f25cd70d5..1ff81afb672c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1437,8 +1437,11 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw); -void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw); +void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr); +void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); int rt2x00mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index ad6e5a8d1e10..cb40245a0695 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -568,7 +568,9 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); -void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) +void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct rt2x00_dev *rt2x00dev = hw->priv; set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); @@ -576,7 +578,8 @@ void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) } EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); -void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw) +void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = hw->priv; clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index f6179bc06086..884d90526f9e 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -1361,7 +1361,9 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, return 0; } -static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) +static void rtl_op_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -1396,7 +1398,8 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP_BAND0); } -static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) +static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 38234851457e..0b30a7b4d663 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c @@ -1029,7 +1029,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, goto out_sleep; } - skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, + skb = ieee80211_probereq_get(wl->hw, wl->vif->addr, ssid, ssid_len, req->ie_len); if (!skb) { ret = -ENOMEM; diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index dd2e448c3e2b..b82661962d33 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -1145,7 +1145,7 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_debug(DEBUG_SCAN, "build probe request band %d", band); - skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, + skb = ieee80211_probereq_get(wl->hw, vif->addr, ssid, ssid_len, ie0_len + ie1_len); if (!skb) { ret = -ENOMEM; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 2fbff907ce8a..dbc311c3dc37 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -856,7 +856,9 @@ static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return 0; } -static void vnt_sw_scan_start(struct ieee80211_hw *hw) +static void vnt_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *addr) { struct vnt_private *priv = hw->priv; @@ -865,7 +867,8 @@ static void vnt_sw_scan_start(struct ieee80211_hw *hw) vnt_update_pre_ed_threshold(priv, true); } -static void vnt_sw_scan_complete(struct ieee80211_hw *hw) +static void vnt_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct vnt_private *priv = hw->priv; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 59166a115aff..7b889e3a2647 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2622,7 +2622,9 @@ enum ieee80211_reconfig_type { * * @sw_scan_start: Notifier function that is called just before a software scan * is started. Can be NULL, if the driver doesn't need this notification. - * The callback can sleep. + * The mac_addr parameter allows supporting NL80211_SCAN_FLAG_RANDOM_ADDR, + * the driver may set the NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR flag if it + * can use this parameter. The callback can sleep. * * @sw_scan_complete: Notifier function that is called just after a * software scan finished. Can be NULL, if the driver doesn't need @@ -3016,8 +3018,11 @@ struct ieee80211_ops { struct ieee80211_scan_ies *ies); int (*sched_scan_stop)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); - void (*sw_scan_start)(struct ieee80211_hw *hw); - void (*sw_scan_complete)(struct ieee80211_hw *hw); + void (*sw_scan_start)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr); + void (*sw_scan_complete)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); int (*get_stats)(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, @@ -3820,7 +3825,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, /** * ieee80211_probereq_get - retrieve a Probe Request template * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @src_addr: source MAC address * @ssid: SSID buffer * @ssid_len: length of SSID * @tailroom: tailroom to reserve at end of SKB for IEs @@ -3831,7 +3836,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, * Return: The Probe Request template. %NULL on error. */ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, + const u8 *src_addr, const u8 *ssid, size_t ssid_len, size_t tailroom); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index ba0d2cb5df12..5f5fc3f3ee7c 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -380,23 +380,26 @@ static inline int drv_sched_scan_stop(struct ieee80211_local *local, return ret; } -static inline void drv_sw_scan_start(struct ieee80211_local *local) +static inline void drv_sw_scan_start(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + const u8 *mac_addr) { might_sleep(); - trace_drv_sw_scan_start(local); + trace_drv_sw_scan_start(local, sdata, mac_addr); if (local->ops->sw_scan_start) - local->ops->sw_scan_start(&local->hw); + local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr); trace_drv_return_void(local); } -static inline void drv_sw_scan_complete(struct ieee80211_local *local) +static inline void drv_sw_scan_complete(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) { might_sleep(); - trace_drv_sw_scan_complete(local); + trace_drv_sw_scan_complete(local, sdata); if (local->ops->sw_scan_complete) - local->ops->sw_scan_complete(&local->hw); + local->ops->sw_scan_complete(&local->hw, &sdata->vif); trace_drv_return_void(local); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index dd27180060b9..cf95d033bcbf 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1249,6 +1249,7 @@ struct ieee80211_local { struct work_struct sched_scan_stopped_work; struct ieee80211_sub_if_data __rcu *sched_scan_sdata; struct cfg80211_sched_scan_request __rcu *sched_scan_req; + u8 scan_addr[ETH_ALEN]; unsigned long leave_oper_channel_time; enum mac80211_scan_state next_scan_state; @@ -1901,12 +1902,14 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, u8 bands_used, u32 *rate_masks, struct cfg80211_chan_def *chandef); struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, - u8 *dst, u32 ratemask, + const u8 *src, const u8 *dst, + u32 ratemask, struct ieee80211_channel *chan, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, bool directed); -void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, +void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, + const u8 *src, const u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u32 ratemask, bool directed, u32 tx_flags, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 45490a202d9c..d29589a09065 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2225,7 +2225,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) else ssid_len = ssid[1]; - ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, + ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL, + ssid + 2, ssid_len, NULL, 0, (u32) -1, true, 0, ifmgd->associated->channel, false); rcu_read_unlock(); @@ -2328,7 +2329,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, else ssid_len = ssid[1]; - skb = ieee80211_build_probe_req(sdata, cbss->bssid, + skb = ieee80211_build_probe_req(sdata, sdata->vif.addr, cbss->bssid, (u32) -1, cbss->channel, ssid + 2, ssid_len, NULL, 0, true); @@ -3649,7 +3650,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) * Direct probe is sent to broadcast address as some APs * will not answer to direct packet in unassociated state. */ - ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], + ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL, + ssidie + 2, ssidie[1], NULL, 0, (u32) -1, true, 0, auth_data->bss->channel, false); rcu_read_unlock(); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index e75e64b8042c..ae842678b629 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -184,9 +184,21 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) return; if (ieee80211_is_probe_resp(mgmt->frame_control)) { - /* ignore ProbeResp to foreign address */ - if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) && - (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr))) + struct cfg80211_scan_request *scan_req; + struct cfg80211_sched_scan_request *sched_scan_req; + + scan_req = rcu_dereference(local->scan_req); + sched_scan_req = rcu_dereference(local->sched_scan_req); + + /* ignore ProbeResp to foreign address unless scanning + * with randomised address + */ + if (!(sdata1 && + (ether_addr_equal(mgmt->da, sdata1->vif.addr) || + scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) && + !(sdata2 && + (ether_addr_equal(mgmt->da, sdata2->vif.addr) || + sched_scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))) return; elements = mgmt->u.probe_resp.variable; @@ -284,6 +296,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) bands_used, req->rates, &chandef); local->hw_scan_req->req.ie_len = ielen; local->hw_scan_req->req.no_cck = req->no_cck; + ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr); + ether_addr_copy(local->hw_scan_req->req.mac_addr_mask, + req->mac_addr_mask); return true; } @@ -294,6 +309,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) bool hw_scan = local->ops->hw_scan; bool was_scanning = local->scanning; struct cfg80211_scan_request *scan_req; + struct ieee80211_sub_if_data *scan_sdata; lockdep_assert_held(&local->mtx); @@ -332,6 +348,9 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) if (scan_req != local->int_scan_req) cfg80211_scan_done(scan_req, aborted); RCU_INIT_POINTER(local->scan_req, NULL); + + scan_sdata = rcu_dereference_protected(local->scan_sdata, + lockdep_is_held(&local->mtx)); RCU_INIT_POINTER(local->scan_sdata, NULL); local->scanning = 0; @@ -342,7 +361,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) if (!hw_scan) { ieee80211_configure_filter(local); - drv_sw_scan_complete(local); + drv_sw_scan_complete(local, scan_sdata); ieee80211_offchannel_return(local); } @@ -368,7 +387,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) } EXPORT_SYMBOL(ieee80211_scan_completed); -static int ieee80211_start_sw_scan(struct ieee80211_local *local) +static int ieee80211_start_sw_scan(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) { /* Software scan is not supported in multi-channel cases */ if (local->use_chanctx) @@ -387,7 +407,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) * nullfunc frames and probe requests will be dropped in * ieee80211_tx_h_check_assoc(). */ - drv_sw_scan_start(local); + drv_sw_scan_start(local, sdata, local->scan_addr); local->leave_oper_channel_time = jiffies; local->next_scan_state = SCAN_DECISION; @@ -463,7 +483,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, for (i = 0; i < scan_req->n_ssids; i++) ieee80211_send_probe_req( - sdata, NULL, + sdata, local->scan_addr, NULL, scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len, scan_req->ie, scan_req->ie_len, scan_req->rates[band], false, @@ -543,6 +563,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, rcu_assign_pointer(local->scan_req, req); rcu_assign_pointer(local->scan_sdata, sdata); + if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) + get_random_mask_addr(local->scan_addr, + req->mac_addr, + req->mac_addr_mask); + else + memcpy(local->scan_addr, sdata->vif.addr, ETH_ALEN); + if (local->ops->hw_scan) { __set_bit(SCAN_HW_SCANNING, &local->scanning); } else if ((req->n_channels == 1) && @@ -559,7 +586,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, /* Notify driver scan is starting, keep order of operations * same as normal software scan, in case that matters. */ - drv_sw_scan_start(local); + drv_sw_scan_start(local, sdata, local->scan_addr); ieee80211_configure_filter(local); /* accept probe-responses */ @@ -589,8 +616,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, if (local->ops->hw_scan) { WARN_ON(!ieee80211_prep_hw_scan(local)); rc = drv_hw_scan(local, sdata, local->hw_scan_req); - } else - rc = ieee80211_start_sw_scan(local); + } else { + rc = ieee80211_start_sw_scan(local, sdata); + } if (rc) { kfree(local->hw_scan_req); diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 7f76e2f25744..eb91505eb43e 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -596,14 +596,33 @@ DEFINE_EVENT(local_sdata_evt, drv_sched_scan_stop, TP_ARGS(local, sdata) ); -DEFINE_EVENT(local_only_evt, drv_sw_scan_start, - TP_PROTO(struct ieee80211_local *local), - TP_ARGS(local) +TRACE_EVENT(drv_sw_scan_start, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + const u8 *mac_addr), + + TP_ARGS(local, sdata, mac_addr), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + __array(char, mac_addr, ETH_ALEN) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + memcpy(__entry->mac_addr, mac_addr, ETH_ALEN); + ), + + TP_printk(LOCAL_PR_FMT ", " VIF_PR_FMT ", addr:%pM", + LOCAL_PR_ARG, VIF_PR_ARG, __entry->mac_addr) ); -DEFINE_EVENT(local_only_evt, drv_sw_scan_complete, - TP_PROTO(struct ieee80211_local *local), - TP_ARGS(local) +DEFINE_EVENT(local_sdata_evt, drv_sw_scan_complete, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) ); TRACE_EVENT(drv_get_stats, diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0cb41d1a1f20..66ddbbeccd20 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2961,19 +2961,16 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, EXPORT_SYMBOL(ieee80211_nullfunc_get); struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, + const u8 *src_addr, const u8 *ssid, size_t ssid_len, size_t tailroom) { - struct ieee80211_sub_if_data *sdata; - struct ieee80211_local *local; + struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_hdr_3addr *hdr; struct sk_buff *skb; size_t ie_ssid_len; u8 *pos; - sdata = vif_to_sdata(vif); - local = sdata->local; ie_ssid_len = 2 + ssid_len; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + @@ -2988,7 +2985,7 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); eth_broadcast_addr(hdr->addr1); - memcpy(hdr->addr2, vif->addr, ETH_ALEN); + memcpy(hdr->addr2, src_addr, ETH_ALEN); eth_broadcast_addr(hdr->addr3); pos = skb_put(skb, ie_ssid_len); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0ad534abc008..bb9664cb8831 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1523,7 +1523,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, }; struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, - u8 *dst, u32 ratemask, + const u8 *src, const u8 *dst, + u32 ratemask, struct ieee80211_channel *chan, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, @@ -1548,8 +1549,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, else chandef.chan = chan; - skb = ieee80211_probereq_get(&local->hw, &sdata->vif, - ssid, ssid_len, 100 + ie_len); + skb = ieee80211_probereq_get(&local->hw, src, ssid, ssid_len, + 100 + ie_len); if (!skb) return NULL; @@ -1571,7 +1572,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, return skb; } -void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, +void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, + const u8 *src, const u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u32 ratemask, bool directed, u32 tx_flags, @@ -1579,7 +1581,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, { struct sk_buff *skb; - skb = ieee80211_build_probe_req(sdata, dst, ratemask, channel, + skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel, ssid, ssid_len, ie, ie_len, directed); if (skb) { -- cgit v1.2.3 From b4c1b70823721e9edb19a839188e4dae50ce878d Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Wed, 19 Nov 2014 12:30:28 +0100 Subject: ath9k_common: make sure DEBUG_FS and RELAY enabled currently ath9k_common depends on this components. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k') diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index ca101d7cb99f..fee0cadb0f5e 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -3,6 +3,8 @@ config ATH9K_HW config ATH9K_COMMON tristate select ATH_COMMON + select DEBUG_FS + select RELAY config ATH9K_DFS_DEBUGFS def_bool y depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED -- cgit v1.2.3