mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-21 19:31:55 +00:00
462 lines
12 KiB
Diff
462 lines
12 KiB
Diff
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -200,10 +200,6 @@ enum ath11k_dev_flags {
|
|
ATH11K_FLAG_FW_RESTART_FOR_HOST,
|
|
};
|
|
|
|
-enum ath11k_monitor_flags {
|
|
- ATH11K_MONITOR_FLAG_STARTED,
|
|
-};
|
|
-
|
|
struct ath11k_vif {
|
|
u32 vdev_id;
|
|
enum wmi_vdev_type vdev_type;
|
|
@@ -539,7 +535,6 @@ struct ath11k {
|
|
|
|
unsigned long dev_flags;
|
|
unsigned int filter_flags;
|
|
- unsigned long monitor_flags;
|
|
u32 min_tx_power;
|
|
u32 max_tx_power;
|
|
u32 txpower_limit_2g;
|
|
@@ -549,7 +544,8 @@ struct ath11k {
|
|
u32 chan_tx_pwr;
|
|
u32 num_stations;
|
|
u32 max_num_stations;
|
|
- bool monitor_present;
|
|
+ bool monitor_conf_enabled;
|
|
+ bool monitor_started;
|
|
/* To synchronize concurrent synchronous mac80211 callback operations,
|
|
* concurrent debugfs configuration and concurrent FW statistics events.
|
|
*/
|
|
@@ -639,7 +635,7 @@ struct ath11k {
|
|
int ap_ps_enabled;
|
|
enum ath11k_ap_ps_state ap_ps_state;
|
|
|
|
- int monitor_vdev_cnt;
|
|
+ bool monitor_vdev_created;
|
|
};
|
|
|
|
struct ath11k_band_cap {
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -742,6 +742,20 @@ ath11k_mac_get_any_chandef_iter(struct i
|
|
*def = &conf->def;
|
|
}
|
|
|
|
+static inline int ath11k_mac_vdev_setup_sync(struct ath11k *ar)
|
|
+{
|
|
+ lockdep_assert_held(&ar->conf_mutex);
|
|
+
|
|
+ if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
|
|
+ return -ESHUTDOWN;
|
|
+
|
|
+ if (!wait_for_completion_timeout(&ar->vdev_setup_done,
|
|
+ ATH11K_VDEV_SETUP_TIMEOUT_HZ))
|
|
+ return -ETIMEDOUT;
|
|
+
|
|
+ return ar->last_wmi_vdev_start_status ? -EINVAL : 0;
|
|
+}
|
|
+
|
|
static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id)
|
|
{
|
|
struct cfg80211_chan_def *chandef = NULL;
|
|
@@ -820,6 +834,7 @@ static int ath11k_mac_monitor_vdev_stop(
|
|
int ret = 0;
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
+
|
|
reinit_completion(&ar->vdev_setup_done);
|
|
|
|
ret = ath11k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
|
|
@@ -851,6 +866,10 @@ static int ath11k_mac_monitor_vdev_creat
|
|
u16 nss = 0;
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
+
|
|
+ if (ar->monitor_vdev_created)
|
|
+ return 0;
|
|
+
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
if (ar->ab->free_vdev_map == 0) {
|
|
@@ -898,7 +917,10 @@ static int ath11k_mac_monitor_vdev_creat
|
|
if (ret)
|
|
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;
|
|
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %d created\n",
|
|
ar->monitor_vdev_id);
|
|
|
|
@@ -909,8 +931,12 @@ static int ath11k_mac_monitor_vdev_delet
|
|
{
|
|
int ret = 0;
|
|
unsigned long time_left = 0;
|
|
+
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
+ if (!ar->monitor_vdev_created)
|
|
+ return 0;
|
|
+
|
|
reinit_completion(&ar->vdev_delete_done);
|
|
|
|
ret = ath11k_wmi_vdev_delete(ar, ar->monitor_vdev_id);
|
|
@@ -925,14 +951,15 @@ static int ath11k_mac_monitor_vdev_delet
|
|
if (time_left == 0) {
|
|
ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
|
|
} else {
|
|
+ ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id);
|
|
ar->ab->free_vdev_map |= 1LL << (ar->monitor_vdev_id);
|
|
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %d deleted\n",
|
|
+ ar->monitor_vdev_id);
|
|
ar->num_created_vdevs--;
|
|
ar->monitor_vdev_id = -1;
|
|
+ ar->monitor_vdev_created = false;
|
|
}
|
|
|
|
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %d deleted\n",
|
|
- ar->monitor_vdev_id);
|
|
-
|
|
return ret;
|
|
}
|
|
|
|
@@ -942,15 +969,8 @@ static int ath11k_mac_monitor_start(stru
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
- if (ar->monitor_vdev_cnt > 0)
|
|
- goto set_monitor_status;
|
|
-
|
|
- ret = ath11k_mac_monitor_vdev_create(ar);
|
|
- if (ret) {
|
|
- ath11k_warn(ar->ab, "failed to create monitor vdev: %d\n", ret);
|
|
- ar->monitor_vdev_id = -1;
|
|
- return ret;
|
|
- }
|
|
+ if (ar->monitor_started)
|
|
+ return 0;
|
|
|
|
ret = ath11k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id);
|
|
if (ret) {
|
|
@@ -959,9 +979,8 @@ static int ath11k_mac_monitor_start(stru
|
|
return ret;
|
|
}
|
|
|
|
- ar->monitor_vdev_cnt++;
|
|
- set_bit(ATH11K_MONITOR_FLAG_STARTED, &ar->monitor_flags);
|
|
-set_monitor_status:
|
|
+ ar->monitor_started = true;
|
|
+ ar->num_started_vdevs++;
|
|
ret = ath11k_dp_tx_htt_monitor_mode_ring_config(ar, false);
|
|
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor started ret %d\n", ret);
|
|
|
|
@@ -974,8 +993,8 @@ static int ath11k_mac_monitor_stop(struc
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
- if (!ar->monitor_vdev_cnt)
|
|
- goto clear_monitor_status;
|
|
+ if (!ar->monitor_started)
|
|
+ return 0;
|
|
|
|
ret = ath11k_mac_monitor_vdev_stop(ar);
|
|
if (ret) {
|
|
@@ -983,47 +1002,47 @@ static int ath11k_mac_monitor_stop(struc
|
|
return ret;
|
|
}
|
|
|
|
- ret = ath11k_mac_monitor_vdev_delete(ar);
|
|
- if (ret) {
|
|
- ath11k_warn(ar->ab, "failed to delete monitor vdev: %d\n", ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- ar->monitor_vdev_cnt--;
|
|
-clear_monitor_status:
|
|
+ ar->monitor_started = false;
|
|
+ ar->num_started_vdevs--;
|
|
ret = ath11k_dp_tx_htt_monitor_mode_ring_config(ar, true);
|
|
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor stopped ret %d\n", ret);
|
|
- if(ar->monitor_vdev_cnt <= 0)
|
|
- clear_bit(ATH11K_MONITOR_FLAG_STARTED, &ar->monitor_flags);
|
|
return ret;
|
|
}
|
|
|
|
-int ath11k_mac_monitor_recalc(struct ath11k *ar, bool needed)
|
|
-{
|
|
- bool started = !!ar->monitor_vdev_cnt;
|
|
-
|
|
- lockdep_assert_held(&ar->conf_mutex);
|
|
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
|
- "mac monitor recalc started? %d needed? %d\n", started, needed);
|
|
-
|
|
- if (needed)
|
|
- return ath11k_mac_monitor_start(ar);
|
|
- else
|
|
- return ath11k_mac_monitor_stop(ar);
|
|
-}
|
|
-
|
|
static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
{
|
|
struct ath11k *ar = hw->priv;
|
|
struct ieee80211_conf *conf = &hw->conf;
|
|
- /* mac80211 requires this op to be present and that's why
|
|
- * there's an empty function, this can be extended when
|
|
- * required.
|
|
- */
|
|
+
|
|
mutex_lock(&ar->conf_mutex);
|
|
|
|
- if (changed & IEEE80211_CONF_CHANGE_MONITOR)
|
|
- ath11k_mac_monitor_recalc(ar, conf->flags & IEEE80211_CONF_MONITOR);
|
|
+ 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)
|
|
+ goto exit;
|
|
+ ret = ath11k_mac_monitor_vdev_create(ar);
|
|
+ if (ret)
|
|
+ goto exit;
|
|
+ ret = ath11k_mac_monitor_start(ar);
|
|
+ if (ret)
|
|
+ goto err_mon_del;
|
|
+ } else {
|
|
+ if (!ar->monitor_vdev_created)
|
|
+ goto exit;
|
|
+ ret = ath11k_mac_monitor_stop(ar);
|
|
+ if (ret)
|
|
+ goto exit;
|
|
+ ath11k_mac_monitor_vdev_delete(ar);
|
|
+ }
|
|
+ }
|
|
+
|
|
+exit:
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ return ret;
|
|
+
|
|
+err_mon_del:
|
|
+ ath11k_mac_monitor_vdev_delete(ar);
|
|
|
|
mutex_unlock(&ar->conf_mutex);
|
|
|
|
@@ -5187,6 +5206,8 @@ static void ath11k_mac_op_stop(struct ie
|
|
ath11k_mac_drain_tx(ar);
|
|
|
|
mutex_lock(&ar->conf_mutex);
|
|
+
|
|
+ ar->monitor_conf_enabled = false;
|
|
ret = ath11k_mac_config_mon_status_default(ar, false);
|
|
if (ret)
|
|
ath11k_err(ar->ab, "failed to clear rx_filter for monitor status ring: (%d)\n",
|
|
@@ -5315,8 +5336,8 @@ static int ath11k_mac_op_add_interface(s
|
|
}
|
|
|
|
if (ar->num_created_vdevs > (TARGET_NUM_VDEVS - 1)) {
|
|
- ath11k_warn(ab, "failed to create vdev, reached max vdev limit %d\n",
|
|
- TARGET_NUM_VDEVS);
|
|
+ ath11k_warn(ab, "failed to create vdev %u, reached max vdev limit %d\n",
|
|
+ ar->num_created_vdevs, TARGET_NUM_VDEVS);
|
|
ret = -EBUSY;
|
|
goto err;
|
|
}
|
|
@@ -5361,6 +5382,7 @@ static int ath11k_mac_op_add_interface(s
|
|
break;
|
|
case NL80211_IFTYPE_MONITOR:
|
|
arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
|
|
+ ar->monitor_vdev_id = bit;
|
|
break;
|
|
default:
|
|
WARN_ON(1);
|
|
@@ -5462,7 +5484,7 @@ static int ath11k_mac_op_add_interface(s
|
|
}
|
|
break;
|
|
case WMI_VDEV_TYPE_MONITOR:
|
|
- ar->monitor_vdev_cnt++;
|
|
+ ar->monitor_vdev_created = true;
|
|
break;
|
|
default:
|
|
break;
|
|
@@ -5485,12 +5507,17 @@ static int ath11k_mac_op_add_interface(s
|
|
ath11k_dp_vdev_tx_attach(ar, arvif);
|
|
|
|
ret = ath11k_mac_ap_ps_recalc(ar);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
ath11k_warn(ar->ab, "failed to set ap ps ret %d\n", ret);
|
|
+ ret = 0;
|
|
+ }
|
|
+
|
|
+ if (vif->type != NL80211_IFTYPE_MONITOR && ar->monitor_conf_enabled)
|
|
+ ath11k_mac_monitor_vdev_create(ar);
|
|
|
|
mutex_unlock(&ar->conf_mutex);
|
|
|
|
- return 0;
|
|
+ return ret;
|
|
|
|
err_peer_del:
|
|
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
|
@@ -5583,8 +5610,12 @@ static void ath11k_mac_op_remove_interfa
|
|
ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
|
|
vif->addr, arvif->vdev_id);
|
|
|
|
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
|
|
- ar->monitor_vdev_cnt--;
|
|
+ if (arvif->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 = ath11k_mac_monitor_vdev_delete(ar);
|
|
|
|
err_vdev_del:
|
|
spin_lock_bh(&ar->data_lock);
|
|
@@ -5751,20 +5782,6 @@ static void ath11k_mac_op_remove_chanctx
|
|
mutex_unlock(&ar->conf_mutex);
|
|
}
|
|
|
|
-static inline int ath11k_mac_vdev_setup_sync(struct ath11k *ar)
|
|
-{
|
|
- lockdep_assert_held(&ar->conf_mutex);
|
|
-
|
|
- if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
|
|
- return -ESHUTDOWN;
|
|
-
|
|
- if (!wait_for_completion_timeout(&ar->vdev_setup_done,
|
|
- ATH11K_VDEV_SETUP_TIMEOUT_HZ))
|
|
- return -ETIMEDOUT;
|
|
-
|
|
- return ar->last_wmi_vdev_start_status ? -EINVAL : 0;
|
|
-}
|
|
-
|
|
static int
|
|
ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
|
const struct cfg80211_chan_def *chandef,
|
|
@@ -5965,12 +5982,16 @@ ath11k_mac_update_vif_chan(struct ath11k
|
|
struct ath11k_vif *arvif;
|
|
int ret;
|
|
int i;
|
|
+ bool monitor_vif = false;
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
for (i = 0; i < n_vifs; i++) {
|
|
arvif = (void *)vifs[i].vif->drv_priv;
|
|
|
|
+ if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR)
|
|
+ monitor_vif = true;
|
|
+
|
|
ath11k_dbg(ab, ATH11K_DBG_MAC,
|
|
"mac chanctx switch vdev_id %i freq %u->%u width %d->%d\n",
|
|
arvif->vdev_id,
|
|
@@ -6028,6 +6049,12 @@ ath11k_mac_update_vif_chan(struct ath11k
|
|
continue;
|
|
}
|
|
}
|
|
+
|
|
+ /* Restart the internal monitor vdev on new channel */
|
|
+ if (!monitor_vif && ar->monitor_vdev_created) {
|
|
+ if (!ath11k_mac_monitor_stop(ar))
|
|
+ ath11k_mac_monitor_start(ar);
|
|
+ }
|
|
}
|
|
|
|
static void
|
|
@@ -6167,6 +6194,15 @@ ath11k_mac_op_assign_vif_chanctx(struct
|
|
}
|
|
}
|
|
|
|
+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
|
|
+ ret = ath11k_mac_monitor_start(ar);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ arvif->is_started = true;
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
ret = ath11k_mac_vdev_start(arvif, &ctx->def);
|
|
if (ret) {
|
|
ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
|
|
@@ -6174,17 +6210,14 @@ ath11k_mac_op_assign_vif_chanctx(struct
|
|
ctx->def.chan->center_freq, ret);
|
|
goto out;
|
|
}
|
|
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
|
|
- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr);
|
|
- if (ret)
|
|
- goto out;
|
|
- ar->monitor_vdev_cnt++;
|
|
- }
|
|
+
|
|
+ if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)
|
|
+ ath11k_mac_monitor_start(ar);
|
|
|
|
arvif->is_started = true;
|
|
|
|
/* TODO: Setup ps and cts/rts protection */
|
|
-
|
|
+exit:
|
|
ret = 0;
|
|
|
|
out:
|
|
@@ -6217,12 +6250,15 @@ ath11k_mac_op_unassign_vif_chanctx(struc
|
|
ath11k_peer_delete(ar, arvif->vdev_id, ar->mac_addr);
|
|
|
|
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
|
|
- ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id);
|
|
- if (ret)
|
|
- ath11k_warn(ar->ab, "failed to down monitor vdev %i: %d\n",
|
|
- arvif->vdev_id, ret);
|
|
- arvif->is_up = false;
|
|
- ar->monitor_vdev_cnt--;
|
|
+ ret = ath11k_mac_monitor_stop(ar);
|
|
+ if (ret) {
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ arvif->is_started = false;
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ return;
|
|
}
|
|
|
|
ret = ath11k_mac_vdev_stop(arvif);
|
|
@@ -6236,6 +6272,10 @@ ath11k_mac_op_unassign_vif_chanctx(struc
|
|
arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
|
|
ath11k_wmi_vdev_down(ar, arvif->vdev_id);
|
|
|
|
+ if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
|
|
+ ar->num_started_vdevs == 1 && ar->monitor_vdev_created)
|
|
+ ath11k_mac_monitor_stop(ar);
|
|
+
|
|
mutex_unlock(&ar->conf_mutex);
|
|
}
|
|
|
|
@@ -7657,9 +7697,9 @@ int ath11k_mac_allocate(struct ath11k_ba
|
|
|
|
INIT_WORK(&ar->wmi_mgmt_tx_work, ath11k_mgmt_over_wmi_tx_work);
|
|
skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
|
|
- clear_bit(ATH11K_MONITOR_FLAG_STARTED, &ar->monitor_flags);
|
|
ar->monitor_vdev_id = -1;
|
|
- ar->monitor_vdev_cnt = 0;
|
|
+ ar->monitor_vdev_created = false;
|
|
+ ar->monitor_started = false;
|
|
}
|
|
|
|
return 0;
|
|
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
|
@@ -5542,7 +5542,7 @@ int ath11k_dp_rx_process_mon_rings(struc
|
|
struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id);
|
|
int ret = 0;
|
|
|
|
- if (test_bit(ATH11K_MONITOR_FLAG_STARTED, &ar->monitor_flags))
|
|
+ if (ar->monitor_started)
|
|
ret = ath11k_dp_mon_process_rx(ab, mac_id, napi, budget);
|
|
else
|
|
ret = ath11k_dp_rx_process_mon_status(ab, mac_id, napi, budget);
|