@@ -1306,6 +1306,10 @@ 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_vdev_created = false;
+ ar->monitor_started = false;
}
}
@@ -738,7 +738,6 @@ struct ath12k {
#endif
bool dfs_block_radar_events;
- bool monitor_conf_enabled;
bool monitor_vdev_created;
bool monitor_started;
int monitor_vdev_id;
@@ -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,
@@ -1245,61 +1245,6 @@ static int ath12k_mac_monitor_vdev_stop(struct ath12k *ar)
return ret;
}
-static int ath12k_mac_monitor_vdev_create(struct ath12k *ar)
-{
- struct ath12k_pdev *pdev = ar->pdev;
- struct ath12k_wmi_vdev_create_arg arg = {};
- int bit, ret;
- u8 tmp_addr[6];
-
- lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
-
- if (ar->monitor_vdev_created)
- return 0;
-
- if (ar->ab->free_vdev_map == 0) {
- ath12k_warn(ar->ab, "failed to find free vdev id for monitor vdev\n");
- return -ENOMEM;
- }
-
- bit = __ffs64(ar->ab->free_vdev_map);
-
- ar->monitor_vdev_id = bit;
-
- arg.if_id = ar->monitor_vdev_id;
- arg.type = WMI_VDEV_TYPE_MONITOR;
- arg.subtype = WMI_VDEV_SUBTYPE_NONE;
- arg.pdev_id = pdev->pdev_id;
- arg.if_stats_id = ATH12K_INVAL_VDEV_STATS_ID;
-
- if (pdev->cap.supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
- arg.chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
- arg.chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
- }
-
- if (pdev->cap.supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
- arg.chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
- arg.chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
- }
-
- ret = ath12k_wmi_vdev_create(ar, tmp_addr, &arg);
- if (ret) {
- ath12k_warn(ar->ab, "failed to request monitor vdev %i creation: %d\n",
- ar->monitor_vdev_id, ret);
- ar->monitor_vdev_id = -1;
- return ret;
- }
-
- ar->allocated_vdev_map |= 1LL << ar->monitor_vdev_id;
- ar->ab->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
- ar->num_created_vdevs++;
- ar->monitor_vdev_created = true;
- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac monitor vdev %d created\n",
- ar->monitor_vdev_id);
-
- return 0;
-}
-
static int ath12k_mac_monitor_vdev_delete(struct ath12k *ar)
{
int ret;
@@ -1362,9 +1307,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 +1384,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 +7238,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 +7989,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 +8150,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;
}
@@ -8256,8 +8172,6 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
}
ath12k_dp_vdev_tx_attach(ar, arvif);
- if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled)
- ath12k_mac_monitor_vdev_create(ar);
return ret;
@@ -8282,6 +8196,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;
@@ -8559,8 +8478,6 @@ static int ath12k_mac_vdev_delete(struct ath12k *ar, struct ath12k_link_vif *arv
if (ahvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ar->monitor_vdev_id = -1;
ar->monitor_vdev_created = false;
- } else if (ar->monitor_vdev_created && !ar->monitor_started) {
- ret = ath12k_mac_monitor_vdev_delete(ar);
}
ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
@@ -9500,9 +9417,6 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out;
}
- if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)
- ath12k_mac_monitor_start(ar);
-
arvif->is_started = true;
/* TODO: Setup ps and cts/rts protection */
@@ -9564,10 +9478,6 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
}
arvif->is_started = false;
-
- if (ahvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
- ar->num_started_vdevs == 1 && ar->monitor_vdev_created)
- ath12k_mac_monitor_stop(ar);
}
static int
@@ -11212,6 +11122,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 +11322,10 @@ 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_vdev_created = false;
+ ar->monitor_started = false;
}
static int __ath12k_mac_mlo_setup(struct ath12k *ar)