wlan-ap-Telecominfraproject/feeds/ipq807x/mac80211/patches/116-ath11k-clean-up-monitor-vdev-del.patch
John Crispin 3affbc1cad QualComm/AX: add Hawkeye and Cypress support
This series is based on
* 2020-07-10 ipq6018-ilq-11-0_qca_oem-034672b0676c37b1f4519e5720e18e95fe6236ef

Add support for
* qsdk kernel/v4.4
* qsdk ethernet subsystem
* v5.7 ath11k backport + QualComm staging patches (wlan_ap_1.0)
* ath11k-firmware
* hostapd/iw/...

Feature support
* full boot, system detection
* sysupgrade to nand
* HE support via latest hostapd
* driver support for usb, crypto, hwmon, cpufreq, ...

Missing
* NSS/HW flow offloading - FW blob is not redistributable

Using the qsdk v4.4 is an intermediate solution while the vanilla is being
tested. Vanilla kernel is almost on feature par. Work has already started
to upstream the ethernet and switch drivers. Once complete the target will
be fully upstream.

Signed-off-by: John Crispin <john@phrozen.org>
2020-07-23 18:54:03 +02:00

513 lines
15 KiB
Diff

--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -197,10 +197,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;
@@ -526,7 +522,6 @@ struct ath11k {
} mac;
unsigned long dev_flags;
unsigned int filter_flags;
- unsigned long monitor_flags;
u32 min_tx_power;
u32 max_tx_power;
u32 txpower_limit_2g;
@@ -536,7 +531,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.
*/
@@ -624,7 +620,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
@@ -680,6 +680,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;
@@ -751,16 +765,19 @@ 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);
if (ret)
ath11k_warn(ar->ab, "failed to to request monitor vdev %i stop: %d\n",
ar->monitor_vdev_id, ret);
+
ret = ath11k_mac_vdev_setup_sync(ar);
if (ret)
ath11k_warn(ar->ab, "failed to synchronize monitor vdev %i stop: %d\n",
ar->monitor_vdev_id, ret);
+
ret = ath11k_wmi_vdev_down(ar, ar->monitor_vdev_id);
if (ret)
ath11k_warn(ar->ab, "failed to put down monitor vdev %i: %d\n",
@@ -778,8 +795,14 @@ static int ath11k_mac_monitor_vdev_creat
int bit, ret = 0;
u8 tmp_addr[6] = {0};
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) {
ath11k_warn(ar->ab, "failed to find free vdev id for monitor vdev\n");
return -ENOMEM;
@@ -802,6 +825,7 @@ static int ath11k_mac_monitor_vdev_creat
param.chains[NL80211_BAND_5GHZ].tx = ar->num_tx_chains;
param.chains[NL80211_BAND_5GHZ].rx = ar->num_rx_chains;
}
+
ret = ath11k_wmi_vdev_create(ar, tmp_addr, &param);
if (ret) {
ath11k_warn(ar->ab, "failed to request monitor vdev %i creation: %d\n",
@@ -823,7 +847,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);
@@ -834,8 +861,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);
@@ -849,86 +880,62 @@ 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;
}
static int ath11k_mac_monitor_start(struct ath11k *ar)
{
- int ret;
+ int ret;
- lockdep_assert_held(&ar->conf_mutex);
+ lockdep_assert_held(&ar->conf_mutex);
- if (ar->monitor_vdev_cnt > 0)
- goto set_monitor_status;
+ if (ar->monitor_started)
+ return 0;
- 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;
- }
- ret = ath11k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id);
- if (ret) {
- ath11k_warn(ar->ab, "failed to start monitor vdev: %d\n", ret);
- ath11k_mac_monitor_vdev_delete(ar);
- return ret;
- }
+ ret = ath11k_mac_monitor_vdev_start(ar, ar->monitor_vdev_id);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to start monitor vdev: %d\n", ret);
+ ath11k_mac_monitor_vdev_delete(ar);
+ return ret;
+ }
- ar->monitor_vdev_cnt++;
- set_bit(ATH11K_MONITOR_FLAG_STARTED, &ar->monitor_flags);
-set_monitor_status:
- 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);
+ 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);
- return ret;
+ return ret;
}
static int ath11k_mac_monitor_stop(struct ath11k *ar)
{
- int ret;
-
- lockdep_assert_held(&ar->conf_mutex);
+ int ret;
- if (!ar->monitor_vdev_cnt)
- goto clear_monitor_status;
+ lockdep_assert_held(&ar->conf_mutex);
- ret = ath11k_mac_monitor_vdev_stop(ar);
- if (ret) {
- ath11k_warn(ar->ab, "failed to stop monitor vdev: %d\n", ret);
- 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:
- 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;
-}
+ if (!ar->monitor_started)
+ return 0;
-int ath11k_mac_monitor_recalc(struct ath11k *ar, bool needed)
-{
- bool started = !!ar->monitor_vdev_cnt;
+ ret = ath11k_mac_monitor_vdev_stop(ar);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to stop monitor vdev: %d\n", ret);
+ return ret;
+ }
- 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);
+ 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);
+ return ret;
}
static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
@@ -937,16 +944,35 @@ static int ath11k_mac_op_config(struct i
struct ieee80211_conf *conf = &hw->conf;
int ret = 0;
- /* 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);
return ret;
@@ -4812,6 +4838,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",
@@ -4888,8 +4916,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;
}
@@ -4934,6 +4962,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);
@@ -5080,7 +5109,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;
@@ -5103,12 +5132,20 @@ 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) {
+ ret = ath11k_mac_monitor_vdev_create(ar);
+ if (ret)
+ goto err_peer_del;
+ }
mutex_unlock(&ar->conf_mutex);
- return 0;
+ return ret;
err_peer_del:
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
@@ -5202,8 +5239,11 @@ static void ath11k_mac_op_remove_interfa
ar->num_created_vdevs--;
}
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
- ar->monitor_vdev_cnt--;
+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
+ 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);
@@ -5366,20 +5406,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,
@@ -5581,12 +5607,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 %hu->%hu width %d->%d\n",
arvif->vdev_id,
@@ -5644,6 +5674,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
@@ -5724,6 +5760,15 @@ ath11k_mac_op_assign_vif_chanctx(struct
return -EBUSY;
}
+ 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",
@@ -5732,17 +5777,14 @@ ath11k_mac_op_assign_vif_chanctx(struct
goto err;
}
- if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr);
- if (ret)
- goto err;
- ar->monitor_vdev_cnt++;
- }
-
arvif->is_started = true;
+ if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ar->monitor_vdev_created)
+ ath11k_mac_monitor_start(ar);
+
/* TODO: Setup ps and cts/rts protection */
+exit:
mutex_unlock(&ar->conf_mutex);
return 0;
@@ -5772,12 +5814,15 @@ ath11k_mac_op_unassign_vif_chanctx(struc
WARN_ON(!arvif->is_started);
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);
@@ -5787,6 +5832,10 @@ ath11k_mac_op_unassign_vif_chanctx(struc
arvif->is_started = false;
+ 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);
}
@@ -7102,9 +7151,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
@@ -5350,7 +5350,7 @@ int ath11k_dp_rx_process_mon_rings(struc
struct ath11k *ar = ab->pdevs[mac_id].ar;
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);