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 bool ath10k_mac_monitor_vdev_is_needed(struct ath10k *ar)
+ {
+ int num_ctx;
+
+ /* At least one chanctx is required to derive a channel to start
+ * monitor vdev on.
+ */
+ num_ctx = ath10k_mac_num_chanctxs(ar);
+ if (num_ctx == 0)
+ return false;
+
+ /* If there's already an existing special monitor interface then don't
+ * bother creating another monitor vdev.
+ */
+ if (ar->monitor_arvif)
+ return false;
+
+ return ar->monitor ||
- !ath10k_mac_should_disable_promisc(ar) ||
+ test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+ }
+
+ static bool ath10k_mac_monitor_vdev_is_allowed(struct ath10k *ar)
+ {
+ int num_ctx;
+
+ num_ctx = ath10k_mac_num_chanctxs(ar);
+
+ /* FIXME: Current interface combinations and cfg80211/mac80211 code
+ * shouldn't allow this but make sure to prevent handling the following
+ * case anyway since multi-channel DFS hasn't been tested at all.
+ */
+ if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags) && num_ctx > 1)
+ return false;
+
+ return true;
+ }
+
static int ath10k_monitor_recalc(struct ath10k *ar)
{
- bool should_start;
+ bool needed;
+ bool allowed;
+ int ret;
lockdep_assert_held(&ar->conf_mutex);
}
}
- static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, bool restart)
+ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
+ {
+ struct ath10k *ar = arvif->ar;
+ int ret;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ reinit_completion(&ar->vdev_setup_done);
+
+ ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id);
+ if (ret) {
+ ath10k_warn(ar, "failed to stop WMI vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
+ ret = ath10k_vdev_setup_sync(ar);
+ if (ret) {
+ ath10k_warn(ar, "failed to syncronise setup for vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
+ WARN_ON(ar->num_started_vdevs == 0);
+
+ if (ar->num_started_vdevs != 0) {
+ ar->num_started_vdevs--;
+ ath10k_recalc_radar_detection(ar);
+ }
+
+ return ret;
+ }
+
+ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif,
+ const struct cfg80211_chan_def *chandef,
+ bool restart)
{
struct ath10k *ar = arvif->ar;
- struct cfg80211_chan_def *chandef = &ar->chandef;
struct wmi_vdev_start_request_arg arg = {};
- int ret = 0, ret2;
+ int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
IEEE80211_HW_AP_LINK_PS |
IEEE80211_HW_SPECTRUM_MGMT |
IEEE80211_HW_SW_CRYPTO_CONTROL |
- IEEE80211_HW_SUPPORT_FAST_XMIT;
++ IEEE80211_HW_SUPPORT_FAST_XMIT |
+ IEEE80211_HW_CONNECTION_MONITOR |
+ IEEE80211_HW_SUPPORTS_PER_STA_GTK |
+ IEEE80211_HW_WANT_MONITOR_VIF |
+ IEEE80211_HW_CHANCTX_STA_CSA |
+ IEEE80211_HW_QUEUE_CONTROL;
ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
+ ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
ar->hw->wiphy->features |= NL80211_FEATURE_DYNAMIC_SMPS;