aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-08-28 06:58:16 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2014-09-02 03:28:36 -0400
commit1933747f5c29d38936cb53f35b4d8070f1cbefe2 (patch)
tree39b67d321cb4556a4a3acd6108b55a2557b3e100
parent2139627172429baee9d62696c6923ce5dc7052bc (diff)
ath10k: fix monitor start/stop sequences
Fix some cases where monitor start failure left the driver in a confused state. This also makes the monitor code simpler. 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.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c121
2 files changed, 49 insertions, 73 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 4ef476099225..797741d762be 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -472,7 +472,6 @@ struct ath10k {
472 struct cfg80211_chan_def chandef; 472 struct cfg80211_chan_def chandef;
473 473
474 int free_vdev_map; 474 int free_vdev_map;
475 bool promisc;
476 bool monitor; 475 bool monitor;
477 int monitor_vdev_id; 476 int monitor_vdev_id;
478 bool monitor_started; 477 bool monitor_started;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 4e30e577b3ed..8d793f31bbd8 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -493,19 +493,6 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
493 return 0; 493 return 0;
494} 494}
495 495
496static bool ath10k_monitor_is_enabled(struct ath10k *ar)
497{
498 lockdep_assert_held(&ar->conf_mutex);
499
500 ath10k_dbg(ar, ATH10K_DBG_MAC,
501 "mac monitor refs: promisc %d monitor %d cac %d\n",
502 ar->promisc, ar->monitor,
503 test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags));
504
505 return ar->promisc || ar->monitor ||
506 test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
507}
508
509static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) 496static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
510{ 497{
511 struct cfg80211_chan_def *chandef = &ar->chandef; 498 struct cfg80211_chan_def *chandef = &ar->chandef;
@@ -649,16 +636,6 @@ static int ath10k_monitor_start(struct ath10k *ar)
649 636
650 lockdep_assert_held(&ar->conf_mutex); 637 lockdep_assert_held(&ar->conf_mutex);
651 638
652 if (!ath10k_monitor_is_enabled(ar)) {
653 ath10k_warn(ar, "trying to start monitor with no references\n");
654 return 0;
655 }
656
657 if (ar->monitor_started) {
658 ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor already started\n");
659 return 0;
660 }
661
662 ret = ath10k_monitor_vdev_create(ar); 639 ret = ath10k_monitor_vdev_create(ar);
663 if (ret) { 640 if (ret) {
664 ath10k_warn(ar, "failed to create monitor vdev: %d\n", ret); 641 ath10k_warn(ar, "failed to create monitor vdev: %d\n", ret);
@@ -678,34 +655,51 @@ static int ath10k_monitor_start(struct ath10k *ar)
678 return 0; 655 return 0;
679} 656}
680 657
681static void ath10k_monitor_stop(struct ath10k *ar) 658static int ath10k_monitor_stop(struct ath10k *ar)
682{ 659{
683 int ret; 660 int ret;
684 661
685 lockdep_assert_held(&ar->conf_mutex); 662 lockdep_assert_held(&ar->conf_mutex);
686 663
687 if (ath10k_monitor_is_enabled(ar)) {
688 ath10k_dbg(ar, ATH10K_DBG_MAC,
689 "mac monitor will be stopped later\n");
690 return;
691 }
692
693 if (!ar->monitor_started) {
694 ath10k_dbg(ar, ATH10K_DBG_MAC,
695 "mac monitor probably failed to start earlier\n");
696 return;
697 }
698
699 ret = ath10k_monitor_vdev_stop(ar); 664 ret = ath10k_monitor_vdev_stop(ar);
700 if (ret) 665 if (ret) {
701 ath10k_warn(ar, "failed to stop monitor vdev: %d\n", ret); 666 ath10k_warn(ar, "failed to stop monitor vdev: %d\n", ret);
667 return ret;
668 }
702 669
703 ret = ath10k_monitor_vdev_delete(ar); 670 ret = ath10k_monitor_vdev_delete(ar);
704 if (ret) 671 if (ret) {
705 ath10k_warn(ar, "failed to delete monitor vdev: %d\n", ret); 672 ath10k_warn(ar, "failed to delete monitor vdev: %d\n", ret);
673 return ret;
674 }
706 675
707 ar->monitor_started = false; 676 ar->monitor_started = false;
708 ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor stopped\n"); 677 ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor stopped\n");
678
679 return 0;
680}
681
682static int ath10k_monitor_recalc(struct ath10k *ar)
683{
684 bool should_start;
685
686 lockdep_assert_held(&ar->conf_mutex);
687
688 should_start = ar->monitor ||
689 ar->filter_flags & FIF_PROMISC_IN_BSS ||
690 test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
691
692 ath10k_dbg(ar, ATH10K_DBG_MAC,
693 "mac monitor recalc started? %d should? %d\n",
694 ar->monitor_started, should_start);
695
696 if (should_start == ar->monitor_started)
697 return 0;
698
699 if (should_start)
700 return ath10k_monitor_start(ar);
701 else
702 return ath10k_monitor_stop(ar);
709} 703}
710 704
711static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif) 705static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
@@ -736,7 +730,7 @@ static int ath10k_start_cac(struct ath10k *ar)
736 730
737 set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); 731 set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
738 732
739 ret = ath10k_monitor_start(ar); 733 ret = ath10k_monitor_recalc(ar);
740 if (ret) { 734 if (ret) {
741 ath10k_warn(ar, "failed to start monitor (cac): %d\n", ret); 735 ath10k_warn(ar, "failed to start monitor (cac): %d\n", ret);
742 clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); 736 clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
@@ -2369,12 +2363,14 @@ void ath10k_halt(struct ath10k *ar)
2369 2363
2370 lockdep_assert_held(&ar->conf_mutex); 2364 lockdep_assert_held(&ar->conf_mutex);
2371 2365
2372 if (ath10k_monitor_is_enabled(ar)) { 2366 clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
2373 clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); 2367 ar->filter_flags = 0;
2374 ar->promisc = false; 2368 ar->monitor = false;
2375 ar->monitor = false; 2369
2370 if (ar->monitor_started)
2376 ath10k_monitor_stop(ar); 2371 ath10k_monitor_stop(ar);
2377 } 2372
2373 ar->monitor_started = false;
2378 2374
2379 ath10k_scan_finish(ar); 2375 ath10k_scan_finish(ar);
2380 ath10k_peer_cleanup_all(ar); 2376 ath10k_peer_cleanup_all(ar);
@@ -2629,7 +2625,7 @@ static void ath10k_config_chan(struct ath10k *ar)
2629 /* First stop monitor interface. Some FW versions crash if there's a 2625 /* First stop monitor interface. Some FW versions crash if there's a
2630 * lone monitor interface. */ 2626 * lone monitor interface. */
2631 if (ar->monitor_started) 2627 if (ar->monitor_started)
2632 ath10k_monitor_vdev_stop(ar); 2628 ath10k_monitor_stop(ar);
2633 2629
2634 list_for_each_entry(arvif, &ar->arvifs, list) { 2630 list_for_each_entry(arvif, &ar->arvifs, list) {
2635 if (!arvif->is_started) 2631 if (!arvif->is_started)
@@ -2677,8 +2673,7 @@ static void ath10k_config_chan(struct ath10k *ar)
2677 } 2673 }
2678 } 2674 }
2679 2675
2680 if (ath10k_monitor_is_enabled(ar)) 2676 ath10k_monitor_recalc(ar);
2681 ath10k_monitor_vdev_start(ar, ar->monitor_vdev_id);
2682} 2677}
2683 2678
2684static int ath10k_config(struct ieee80211_hw *hw, u32 changed) 2679static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
@@ -2733,19 +2728,10 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
2733 ath10k_config_ps(ar); 2728 ath10k_config_ps(ar);
2734 2729
2735 if (changed & IEEE80211_CONF_CHANGE_MONITOR) { 2730 if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
2736 if (conf->flags & IEEE80211_CONF_MONITOR && !ar->monitor) { 2731 ar->monitor = conf->flags & IEEE80211_CONF_MONITOR;
2737 ar->monitor = true; 2732 ret = ath10k_monitor_recalc(ar);
2738 ret = ath10k_monitor_start(ar); 2733 if (ret)
2739 if (ret) { 2734 ath10k_warn(ar, "failed to recalc monitor: %d\n", ret);
2740 ath10k_warn(ar, "failed to start monitor (config): %d\n",
2741 ret);
2742 ar->monitor = false;
2743 }
2744 } else if (!(conf->flags & IEEE80211_CONF_MONITOR) &&
2745 ar->monitor) {
2746 ar->monitor = false;
2747 ath10k_monitor_stop(ar);
2748 }
2749 } 2735 }
2750 2736
2751 mutex_unlock(&ar->conf_mutex); 2737 mutex_unlock(&ar->conf_mutex);
@@ -3009,18 +2995,9 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
3009 *total_flags &= SUPPORTED_FILTERS; 2995 *total_flags &= SUPPORTED_FILTERS;
3010 ar->filter_flags = *total_flags; 2996 ar->filter_flags = *total_flags;
3011 2997
3012 if (ar->filter_flags & FIF_PROMISC_IN_BSS && !ar->promisc) { 2998 ret = ath10k_monitor_recalc(ar);
3013 ar->promisc = true; 2999 if (ret)
3014 ret = ath10k_monitor_start(ar); 3000 ath10k_warn(ar, "failed to recalc montior: %d\n", ret);
3015 if (ret) {
3016 ath10k_warn(ar, "failed to start monitor (promisc): %d\n",
3017 ret);
3018 ar->promisc = false;
3019 }
3020 } else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && ar->promisc) {
3021 ar->promisc = false;
3022 ath10k_monitor_stop(ar);
3023 }
3024 3001
3025 mutex_unlock(&ar->conf_mutex); 3002 mutex_unlock(&ar->conf_mutex);
3026} 3003}