@@ -1306,6 +1306,11 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
ath12k_mac_tx_mgmt_pending_free, ar);
idr_destroy(&ar->txmgmt_idr);
wake_up(&ar->txmgmt_empty_waitq);
+
+ ar->monitor_vdev_id = -1;
+ ar->monitor_conf_enabled = false;
+ ar->monitor_vdev_created = false;
+ ar->monitor_started = false;
}
}
@@ -7,6 +7,7 @@
#include "core.h"
#include "dp_tx.h"
#include "debug.h"
+#include "debugfs.h"
#include "hw.h"
#include "peer.h"
#include "mac.h"
@@ -1431,6 +1432,11 @@ int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset)
HTT_RX_MON_MO_CTRL_FILTER_FLASG3 |
HTT_RX_MON_FP_DATA_FILTER_FLASG3 |
HTT_RX_MON_MO_DATA_FILTER_FLASG3;
+ } else {
+ tlv_filter = ath12k_mac_mon_status_filter_default;
+
+ if (ath12k_debugfs_is_extd_rx_stats_enabled(ar))
+ tlv_filter.rx_filter = ath12k_debugfs_rx_filter(ar);
}
if (ab->hw_params->rxdma1_enable) {
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/types.h>
@@ -1049,7 +1049,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_MESH_POINT) |
BIT(NL80211_IFTYPE_AP_VLAN),
- .supports_monitor = false,
+ .supports_monitor = true,
.idle_ps = false,
.download_calib = true,
@@ -1362,9 +1362,15 @@ static int ath12k_mac_monitor_start(struct ath12k *ar)
return ret;
}
+ ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, false);
+ if (ret) {
+ ath12k_warn(ar->ab, "fail to set monitor filter: %d\n", ret);
+ return ret;
+ }
+
ar->monitor_started = true;
ar->num_started_vdevs++;
- ret = ath12k_dp_tx_htt_monitor_mode_ring_config(ar, false);
+
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor started ret %d\n", ret);
return ret;
@@ -1433,58 +1439,9 @@ int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif)
return ret;
}
-static int ath12k_mac_config(struct ath12k *ar, u32 changed)
-{
- struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
- struct ieee80211_conf *conf = &hw->conf;
- int ret = 0;
-
- lockdep_assert_wiphy(hw->wiphy);
-
- if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
- ar->monitor_conf_enabled = conf->flags & IEEE80211_CONF_MONITOR;
- if (ar->monitor_conf_enabled) {
- if (ar->monitor_vdev_created)
- return ret;
- ret = ath12k_mac_monitor_vdev_create(ar);
- if (ret)
- return ret;
- ret = ath12k_mac_monitor_start(ar);
- if (ret)
- goto err_mon_del;
- } else {
- if (!ar->monitor_vdev_created)
- return ret;
- ret = ath12k_mac_monitor_stop(ar);
- if (ret)
- return ret;
- ath12k_mac_monitor_vdev_delete(ar);
- }
- }
-
- return ret;
-
-err_mon_del:
- ath12k_mac_monitor_vdev_delete(ar);
- return ret;
-}
-
static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
{
- struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
- struct ath12k *ar;
- int ret;
-
- lockdep_assert_wiphy(hw->wiphy);
-
- ar = ath12k_ah_to_ar(ah, 0);
-
- ret = ath12k_mac_config(ar, changed);
- if (ret)
- ath12k_warn(ar->ab, "failed to update config pdev idx %d: %d\n",
- ar->pdev_idx, ret);
-
- return ret;
+ return 0;
}
static int ath12k_mac_setup_bcn_p2p_ie(struct ath12k_link_vif *arvif,
@@ -7336,6 +7293,11 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
u8 link_id;
int ret;
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+
link_id = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK);
memset(skb_cb, 0, sizeof(*skb_cb));
skb_cb->vif = vif;
@@ -8082,6 +8044,12 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
lockdep_assert_wiphy(hw->wiphy);
+ /* In NO_VIRTUAL_MONITOR, its necessary to restrict only one monitor
+ * interface in each radio
+ */
+ if (vif->type == NL80211_IFTYPE_MONITOR && ar->monitor_vdev_created)
+ return -EINVAL;
+
/* If no link is active and scan vdev is requested
* use a default link conf for scan address purpose.
*/
@@ -8237,6 +8205,9 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
goto err_peer_del;
}
break;
+ case WMI_VDEV_TYPE_MONITOR:
+ ar->monitor_vdev_created = true;
+ break;
default:
break;
}
@@ -8282,6 +8253,11 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
}
err_vdev_del:
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ ar->monitor_vdev_id = -1;
+ ar->monitor_vdev_created = false;
+ }
+
ath12k_wmi_vdev_delete(ar, arvif->vdev_id);
ar->num_created_vdevs--;
arvif->is_created = false;
@@ -11212,6 +11188,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
ieee80211_hw_set(hw, QUEUE_CONTROL);
ieee80211_hw_set(hw, SUPPORTS_TX_FRAG);
ieee80211_hw_set(hw, REPORTS_LOW_ACK);
+ ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
if ((ht_cap & WMI_HT_CAP_ENABLED) || is_6ghz) {
ieee80211_hw_set(hw, AMPDU_AGGREGATION);
@@ -11411,6 +11388,11 @@ static void ath12k_mac_setup(struct ath12k *ar)
wiphy_work_init(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work);
skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
+
+ ar->monitor_vdev_id = -1;
+ ar->monitor_conf_enabled = false;
+ ar->monitor_vdev_created = false;
+ ar->monitor_started = false;
}
static int __ath12k_mac_mlo_setup(struct ath12k *ar)