Commit 1933747f authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

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: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 21396271
...@@ -472,7 +472,6 @@ struct ath10k { ...@@ -472,7 +472,6 @@ struct ath10k {
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
int free_vdev_map; int free_vdev_map;
bool promisc;
bool monitor; bool monitor;
int monitor_vdev_id; int monitor_vdev_id;
bool monitor_started; bool monitor_started;
......
...@@ -493,19 +493,6 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar) ...@@ -493,19 +493,6 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
return 0; return 0;
} }
static bool ath10k_monitor_is_enabled(struct ath10k *ar)
{
lockdep_assert_held(&ar->conf_mutex);
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac monitor refs: promisc %d monitor %d cac %d\n",
ar->promisc, ar->monitor,
test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags));
return ar->promisc || ar->monitor ||
test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
}
static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
{ {
struct cfg80211_chan_def *chandef = &ar->chandef; struct cfg80211_chan_def *chandef = &ar->chandef;
...@@ -649,16 +636,6 @@ static int ath10k_monitor_start(struct ath10k *ar) ...@@ -649,16 +636,6 @@ static int ath10k_monitor_start(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
if (!ath10k_monitor_is_enabled(ar)) {
ath10k_warn(ar, "trying to start monitor with no references\n");
return 0;
}
if (ar->monitor_started) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor already started\n");
return 0;
}
ret = ath10k_monitor_vdev_create(ar); ret = ath10k_monitor_vdev_create(ar);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to create monitor vdev: %d\n", ret); ath10k_warn(ar, "failed to create monitor vdev: %d\n", ret);
...@@ -678,34 +655,51 @@ static int ath10k_monitor_start(struct ath10k *ar) ...@@ -678,34 +655,51 @@ static int ath10k_monitor_start(struct ath10k *ar)
return 0; return 0;
} }
static void ath10k_monitor_stop(struct ath10k *ar) static int ath10k_monitor_stop(struct ath10k *ar)
{ {
int ret; int ret;
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
if (ath10k_monitor_is_enabled(ar)) {
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac monitor will be stopped later\n");
return;
}
if (!ar->monitor_started) {
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac monitor probably failed to start earlier\n");
return;
}
ret = ath10k_monitor_vdev_stop(ar); ret = ath10k_monitor_vdev_stop(ar);
if (ret) if (ret) {
ath10k_warn(ar, "failed to stop monitor vdev: %d\n", ret); ath10k_warn(ar, "failed to stop monitor vdev: %d\n", ret);
return ret;
}
ret = ath10k_monitor_vdev_delete(ar); ret = ath10k_monitor_vdev_delete(ar);
if (ret) if (ret) {
ath10k_warn(ar, "failed to delete monitor vdev: %d\n", ret); ath10k_warn(ar, "failed to delete monitor vdev: %d\n", ret);
return ret;
}
ar->monitor_started = false; ar->monitor_started = false;
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor stopped\n"); ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor stopped\n");
return 0;
}
static int ath10k_monitor_recalc(struct ath10k *ar)
{
bool should_start;
lockdep_assert_held(&ar->conf_mutex);
should_start = ar->monitor ||
ar->filter_flags & FIF_PROMISC_IN_BSS ||
test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac monitor recalc started? %d should? %d\n",
ar->monitor_started, should_start);
if (should_start == ar->monitor_started)
return 0;
if (should_start)
return ath10k_monitor_start(ar);
else
return ath10k_monitor_stop(ar);
} }
static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif) static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
...@@ -736,7 +730,7 @@ static int ath10k_start_cac(struct ath10k *ar) ...@@ -736,7 +730,7 @@ static int ath10k_start_cac(struct ath10k *ar)
set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
ret = ath10k_monitor_start(ar); ret = ath10k_monitor_recalc(ar);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to start monitor (cac): %d\n", ret); ath10k_warn(ar, "failed to start monitor (cac): %d\n", ret);
clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
...@@ -2369,12 +2363,14 @@ void ath10k_halt(struct ath10k *ar) ...@@ -2369,12 +2363,14 @@ void ath10k_halt(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
if (ath10k_monitor_is_enabled(ar)) { clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); ar->filter_flags = 0;
ar->promisc = false; ar->monitor = false;
ar->monitor = false;
if (ar->monitor_started)
ath10k_monitor_stop(ar); ath10k_monitor_stop(ar);
}
ar->monitor_started = false;
ath10k_scan_finish(ar); ath10k_scan_finish(ar);
ath10k_peer_cleanup_all(ar); ath10k_peer_cleanup_all(ar);
...@@ -2629,7 +2625,7 @@ static void ath10k_config_chan(struct ath10k *ar) ...@@ -2629,7 +2625,7 @@ static void ath10k_config_chan(struct ath10k *ar)
/* First stop monitor interface. Some FW versions crash if there's a /* First stop monitor interface. Some FW versions crash if there's a
* lone monitor interface. */ * lone monitor interface. */
if (ar->monitor_started) if (ar->monitor_started)
ath10k_monitor_vdev_stop(ar); ath10k_monitor_stop(ar);
list_for_each_entry(arvif, &ar->arvifs, list) { list_for_each_entry(arvif, &ar->arvifs, list) {
if (!arvif->is_started) if (!arvif->is_started)
...@@ -2677,8 +2673,7 @@ static void ath10k_config_chan(struct ath10k *ar) ...@@ -2677,8 +2673,7 @@ static void ath10k_config_chan(struct ath10k *ar)
} }
} }
if (ath10k_monitor_is_enabled(ar)) ath10k_monitor_recalc(ar);
ath10k_monitor_vdev_start(ar, ar->monitor_vdev_id);
} }
static int ath10k_config(struct ieee80211_hw *hw, u32 changed) static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
...@@ -2733,19 +2728,10 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) ...@@ -2733,19 +2728,10 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
ath10k_config_ps(ar); ath10k_config_ps(ar);
if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
if (conf->flags & IEEE80211_CONF_MONITOR && !ar->monitor) { ar->monitor = conf->flags & IEEE80211_CONF_MONITOR;
ar->monitor = true; ret = ath10k_monitor_recalc(ar);
ret = ath10k_monitor_start(ar); if (ret)
if (ret) { ath10k_warn(ar, "failed to recalc monitor: %d\n", ret);
ath10k_warn(ar, "failed to start monitor (config): %d\n",
ret);
ar->monitor = false;
}
} else if (!(conf->flags & IEEE80211_CONF_MONITOR) &&
ar->monitor) {
ar->monitor = false;
ath10k_monitor_stop(ar);
}
} }
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
...@@ -3009,18 +2995,9 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw, ...@@ -3009,18 +2995,9 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
*total_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS;
ar->filter_flags = *total_flags; ar->filter_flags = *total_flags;
if (ar->filter_flags & FIF_PROMISC_IN_BSS && !ar->promisc) { ret = ath10k_monitor_recalc(ar);
ar->promisc = true; if (ret)
ret = ath10k_monitor_start(ar); ath10k_warn(ar, "failed to recalc montior: %d\n", ret);
if (ret) {
ath10k_warn(ar, "failed to start monitor (promisc): %d\n",
ret);
ar->promisc = false;
}
} else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && ar->promisc) {
ar->promisc = false;
ath10k_monitor_stop(ar);
}
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment