aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-04-08 02:56:09 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2014-04-11 01:35:25 -0400
commitd650097bfadab387dfb762bf46b8598cbedf50b3 (patch)
tree1ee61b6a479e2146766642123bf8971b7508dbad
parent72654fa7b52861ec91579e4801412fe2d6ba23a1 (diff)
ath10k: refactor radar detection code
If 20MHz CAC completed successfully then subsequent CAC with wider bandwidth (40Mhz, 80Mhz) with identical control frequency did not start monitor vdev making it impossible to detect any radar pulses during intended CAC. It also was incorrect to assume ath10k_config() will be called after CAC is finished. Theoretically for non-HT channels nothing changes between CAC and start_ap() (albeit in practice this can be different). The incorrect assumption led to CAC not being stopped on non-HT chandefs leading to all Rx being drooped making it impossible for clients to associate. While at it clean up the code a bit. kvalo: separate WARN_ON() from the if statement Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c56
2 files changed, 23 insertions, 37 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 33029767a412..2c1dfd719146 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -436,6 +436,10 @@ struct ath10k {
436 unsigned long dev_flags; 436 unsigned long dev_flags;
437 u32 dfs_block_radar_events; 437 u32 dfs_block_radar_events;
438 438
439 /* protected by conf_mutex */
440 bool radar_enabled;
441 int num_started_vdevs;
442
439 struct wmi_pdev_set_wmm_params_arg wmm_params; 443 struct wmi_pdev_set_wmm_params_arg wmm_params;
440 struct completion install_key_done; 444 struct completion install_key_done;
441 445
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 7a56caca4fc0..8385a7ad02ac 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -767,49 +767,18 @@ static int ath10k_stop_cac(struct ath10k *ar)
767 return 0; 767 return 0;
768} 768}
769 769
770static const char *ath10k_dfs_state(enum nl80211_dfs_state dfs_state) 770static void ath10k_recalc_radar_detection(struct ath10k *ar)
771{ 771{
772 switch (dfs_state) {
773 case NL80211_DFS_USABLE:
774 return "USABLE";
775 case NL80211_DFS_UNAVAILABLE:
776 return "UNAVAILABLE";
777 case NL80211_DFS_AVAILABLE:
778 return "AVAILABLE";
779 default:
780 WARN_ON(1);
781 return "bug";
782 }
783}
784
785static void ath10k_config_radar_detection(struct ath10k *ar)
786{
787 struct ieee80211_channel *chan = ar->hw->conf.chandef.chan;
788 bool radar = ar->hw->conf.radar_enabled;
789 bool chan_radar = !!(chan->flags & IEEE80211_CHAN_RADAR);
790 enum nl80211_dfs_state dfs_state = chan->dfs_state;
791 int ret; 772 int ret;
792 773
793 lockdep_assert_held(&ar->conf_mutex); 774 lockdep_assert_held(&ar->conf_mutex);
794 775
795 ath10k_dbg(ATH10K_DBG_MAC,
796 "mac radar config update: chan %dMHz radar %d chan radar %d chan state %s\n",
797 chan->center_freq, radar, chan_radar,
798 ath10k_dfs_state(dfs_state));
799
800 /*
801 * It's safe to call it even if CAC is not started.
802 * This call here guarantees changing channel, etc. will stop CAC.
803 */
804 ath10k_stop_cac(ar); 776 ath10k_stop_cac(ar);
805 777
806 if (!radar) 778 if (!ar->radar_enabled)
807 return;
808
809 if (!chan_radar)
810 return; 779 return;
811 780
812 if (dfs_state != NL80211_DFS_USABLE) 781 if (ar->num_started_vdevs > 0)
813 return; 782 return;
814 783
815 ret = ath10k_start_cac(ar); 784 ret = ath10k_start_cac(ar);
@@ -880,6 +849,9 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
880 return ret; 849 return ret;
881 } 850 }
882 851
852 ar->num_started_vdevs++;
853 ath10k_recalc_radar_detection(ar);
854
883 return ret; 855 return ret;
884} 856}
885 857
@@ -906,6 +878,13 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
906 return ret; 878 return ret;
907 } 879 }
908 880
881 WARN_ON(ar->num_started_vdevs == 0);
882
883 if (ar->num_started_vdevs != 0) {
884 ar->num_started_vdevs--;
885 ath10k_recalc_radar_detection(ar);
886 }
887
909 return ret; 888 return ret;
910} 889}
911 890
@@ -2395,6 +2374,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
2395 goto exit; 2374 goto exit;
2396 } 2375 }
2397 2376
2377 ar->num_started_vdevs = 0;
2398 ath10k_regd_update(ar); 2378 ath10k_regd_update(ar);
2399 ret = 0; 2379 ret = 0;
2400 2380
@@ -2541,15 +2521,17 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
2541 2521
2542 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 2522 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
2543 ath10k_dbg(ATH10K_DBG_MAC, 2523 ath10k_dbg(ATH10K_DBG_MAC,
2544 "mac config channel %d mhz flags 0x%x\n", 2524 "mac config channel %dMHz flags 0x%x radar %d\n",
2545 conf->chandef.chan->center_freq, 2525 conf->chandef.chan->center_freq,
2546 conf->chandef.chan->flags); 2526 conf->chandef.chan->flags,
2527 conf->radar_enabled);
2547 2528
2548 spin_lock_bh(&ar->data_lock); 2529 spin_lock_bh(&ar->data_lock);
2549 ar->rx_channel = conf->chandef.chan; 2530 ar->rx_channel = conf->chandef.chan;
2550 spin_unlock_bh(&ar->data_lock); 2531 spin_unlock_bh(&ar->data_lock);
2551 2532
2552 ath10k_config_radar_detection(ar); 2533 ar->radar_enabled = conf->radar_enabled;
2534 ath10k_recalc_radar_detection(ar);
2553 2535
2554 if (!cfg80211_chandef_identical(&ar->chandef, &conf->chandef)) { 2536 if (!cfg80211_chandef_identical(&ar->chandef, &conf->chandef)) {
2555 ar->chandef = conf->chandef; 2537 ar->chandef = conf->chandef;