wlan-ap-Telecominfraproject/feeds/wifi-ax/mac80211/patches/qca/116-ath11k-clean-up-monitor-vdev-del.patch
John Crispin 8cd26b4b50 ipq807x: update to 11.4-CS
Signed-off-by: John Crispin <john@phrozen.org>
2021-09-14 09:16:23 +02:00

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(&param, 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);