Commit 54846213 authored by Vasanthakumar Thiagarajan's avatar Vasanthakumar Thiagarajan Committed by Kalle Valo

ath10k: fix interrupt storm

Promiscuous mode is enabled when wlan interface is added to
bridge. ath10k creates a monitor mode when promiscuous mode
is enabled. When monitor vdev is running along with other
vdev(s) there is a huge number of interrupts generated
especially in noisy condition. Fix this by not enabling
promiscuous(monitor) mode when already a vdev is running.
As disabling promiscuous mode may have issues with 4-address
bridging in STA mode, the change is done specific to non-sta/ibss
mode types. This does not change the support of virtual interface of
type monitor along with other vdevs of any type.

This could fix management frame drop in fw due to unavailable
buffers because in monitor mode device receives everything seen
on the air. In noisy condition, disabling monitor mode helps assoc
go through without any issue.
Signed-off-by: default avatarVasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 822b7e0b
...@@ -830,6 +830,25 @@ static int ath10k_monitor_stop(struct ath10k *ar) ...@@ -830,6 +830,25 @@ static int ath10k_monitor_stop(struct ath10k *ar)
return 0; return 0;
} }
static bool ath10k_mac_should_disable_promisc(struct ath10k *ar)
{
struct ath10k_vif *arvif;
if (!(ar->filter_flags & FIF_PROMISC_IN_BSS))
return true;
if (!ar->num_started_vdevs)
return false;
list_for_each_entry(arvif, &ar->arvifs, list)
if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
return false;
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac disabling promiscuous mode because vdev is started\n");
return true;
}
static int ath10k_monitor_recalc(struct ath10k *ar) static int ath10k_monitor_recalc(struct ath10k *ar)
{ {
bool should_start; bool should_start;
...@@ -837,7 +856,7 @@ static int ath10k_monitor_recalc(struct ath10k *ar) ...@@ -837,7 +856,7 @@ static int ath10k_monitor_recalc(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
should_start = ar->monitor || should_start = ar->monitor ||
ar->filter_flags & FIF_PROMISC_IN_BSS || !ath10k_mac_should_disable_promisc(ar);
test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
ath10k_dbg(ar, ATH10K_DBG_MAC, ath10k_dbg(ar, ATH10K_DBG_MAC,
...@@ -974,7 +993,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, bool restart) ...@@ -974,7 +993,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, bool restart)
struct ath10k *ar = arvif->ar; struct ath10k *ar = arvif->ar;
struct cfg80211_chan_def *chandef = &ar->chandef; struct cfg80211_chan_def *chandef = &ar->chandef;
struct wmi_vdev_start_request_arg arg = {}; struct wmi_vdev_start_request_arg arg = {};
int ret = 0; int ret = 0, ret2;
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
...@@ -1033,6 +1052,16 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, bool restart) ...@@ -1033,6 +1052,16 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, bool restart)
ar->num_started_vdevs++; ar->num_started_vdevs++;
ath10k_recalc_radar_detection(ar); ath10k_recalc_radar_detection(ar);
ret = ath10k_monitor_recalc(ar);
if (ret) {
ath10k_warn(ar, "mac failed to recalc monitor for vdev %i restart %d: %d\n",
arg.vdev_id, restart, ret);
ret2 = ath10k_vdev_stop(arvif);
if (ret2)
ath10k_warn(ar, "mac failed to stop vdev %i restart %d: %d\n",
arg.vdev_id, restart, ret2);
}
return ret; return ret;
} }
......
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