mirror of
https://github.com/breeze303/openwrt-ipq.git
synced 2025-12-17 00:21:06 +00:00
NSS patches should always get applied last as to avoid fuzzing issues with upstream patches. Also cleanup patches that introduced spaces as indents vs. tabs Signed-off-by: Sean Khan <datapronix@protonmail.com> ath11k_nss: drop upstreamed patch A variation of this patch 'wifi: mac80211: Use flexible array in struct ieee80211_tim_ie' was upstreamed in commit 'e6e4d90b69027d74ba7e9a0a586b95a5714e10c0'. Remove it to avoid compilation issues. Signed-off-by: Sean Khan <datapronix@protonmail.com> ath11k_nss: Fix patch conflict Signed-off-by: Sean Khan <datapronix@protonmail.com>
258 lines
8.9 KiB
Diff
258 lines
8.9 KiB
Diff
From: Baochen Qiang <quic_bqiang@quicinc.com>
|
|
To: <ath11k@lists.infradead.org>
|
|
Subject: [PATCH 4/4] wifi: ath11k: fix connection failure due to unexpected
|
|
peer delete
|
|
Date: Tue, 23 Jan 2024 10:57:00 +0800
|
|
|
|
Currently ath11k_mac_op_unassign_vif_chanctx() deletes peer but
|
|
ath11k_mac_op_assign_vif_chanctx() doesn't create it. This results in
|
|
connection failure if MAC80211 calls drv_unassign_vif_chanctx() and
|
|
drv_assign_vif_chanctx() during AUTH and ASSOC, see below log:
|
|
|
|
[ 102.372431] wlan0: authenticated
|
|
[ 102.372585] ath11k_pci 0000:01:00.0: wlan0: disabling HT/VHT/HE as WMM/QoS is not supported by the AP
|
|
[ 102.372593] ath11k_pci 0000:01:00.0: mac chanctx unassign ptr ffff895084638598 vdev_id 0
|
|
[ 102.372808] ath11k_pci 0000:01:00.0: WMI vdev stop id 0x0
|
|
[ 102.383114] ath11k_pci 0000:01:00.0: vdev stopped for vdev id 0
|
|
[ 102.384689] ath11k_pci 0000:01:00.0: WMI peer delete vdev_id 0 peer_addr 20:e5:2a:21:c4:51
|
|
[ 102.396676] ath11k_pci 0000:01:00.0: htt peer unmap vdev 0 peer 20:e5:2a:21:c4:51 id 3
|
|
[ 102.396711] ath11k_pci 0000:01:00.0: peer delete resp for vdev id 0 addr 20:e5:2a:21:c4:51
|
|
[ 102.396722] ath11k_pci 0000:01:00.0: mac removed peer 20:e5:2a:21:c4:51 vdev 0 after vdev stop
|
|
[ 102.396780] ath11k_pci 0000:01:00.0: mac chanctx assign ptr ffff895084639c18 vdev_id 0
|
|
[ 102.400628] wlan0: associate with 20:e5:2a:21:c4:51 (try 1/3)
|
|
[ 102.508864] wlan0: associate with 20:e5:2a:21:c4:51 (try 2/3)
|
|
[ 102.612815] wlan0: associate with 20:e5:2a:21:c4:51 (try 3/3)
|
|
[ 102.720846] wlan0: association with 20:e5:2a:21:c4:51 timed out
|
|
|
|
The peer delete logic in ath11k_mac_op_unassign_vif_chanctx() is
|
|
introduced by commit b4a0f54156ac ("ath11k: move peer delete after
|
|
vdev stop of station for QCA6390 and WCN6855") to fix firmware
|
|
crash issue caused by unexpected vdev stop/peer delete sequence.
|
|
|
|
Actually for a STA interface peer should be deleted in
|
|
ath11k_mac_op_sta_state() when STA's state changes from
|
|
IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST, which also coincides
|
|
with current peer creation design that peer is created during
|
|
IEEE80211_STA_NOTEXIST -> IEEE80211_STA_NONE transition. So move
|
|
peer delete back to ath11k_mac_op_sta_state(), also stop vdev before
|
|
deleting peer to fix the firmware crash issue mentioned there. In
|
|
this way the connection failure mentioned here is also fixed.
|
|
|
|
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
|
|
Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23
|
|
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
|
|
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
|
|
|
|
Fixes: b4a0f54156ac ("ath11k: move peer delete after vdev stop of station for QCA6390 and WCN6855")
|
|
Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
|
|
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
|
|
---
|
|
drivers/net/wireless/ath/ath11k/mac.c | 139 ++++++++++++++++----------
|
|
1 file changed, 85 insertions(+), 54 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -7928,6 +7928,30 @@ static int ath11k_mac_start_vdev_delay(s
|
|
return 0;
|
|
}
|
|
|
|
+static int ath11k_mac_stop_vdev_early(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_vif *vif)
|
|
+{
|
|
+ struct ath11k *ar = hw->priv;
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
|
+ int ret;
|
|
+
|
|
+ if (WARN_ON(!arvif->is_started))
|
|
+ return -EBUSY;
|
|
+
|
|
+ ret = ath11k_mac_vdev_stop(arvif);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ab, "failed to stop vdev %i: %d\n",
|
|
+ arvif->vdev_id, ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ arvif->is_started = false;
|
|
+
|
|
+ /* TODO: Setup ps and cts/rts protection */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int
|
|
ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|
struct ieee80211_vif *vif,
|
|
@@ -7972,15 +7996,17 @@ ath11k_mac_op_assign_vif_chanctx(struct
|
|
goto out;
|
|
}
|
|
|
|
- ret = ath11k_mac_vdev_start(arvif, ctx);
|
|
- if (ret) {
|
|
- ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
|
|
- arvif->vdev_id, vif->addr,
|
|
- ctx->def.chan->center_freq, ret);
|
|
- goto out;
|
|
- }
|
|
+ if (!arvif->is_started) {
|
|
+ ret = ath11k_mac_vdev_start(arvif, ctx);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
|
|
+ arvif->vdev_id, vif->addr,
|
|
+ ctx->def.chan->center_freq, ret);
|
|
+ goto out;
|
|
+ }
|
|
|
|
- arvif->is_started = true;
|
|
+ arvif->is_started = true;
|
|
+ }
|
|
|
|
if (arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
|
|
test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags)) {
|
|
@@ -8020,8 +8046,6 @@ ath11k_mac_op_unassign_vif_chanctx(struc
|
|
"chanctx unassign ptr %p vdev_id %i\n",
|
|
ctx, arvif->vdev_id);
|
|
|
|
- WARN_ON(!arvif->is_started);
|
|
-
|
|
if (ab->hw_params.vdev_start_delay &&
|
|
arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
|
|
spin_lock_bh(&ab->base_lock);
|
|
@@ -8045,24 +8069,13 @@ ath11k_mac_op_unassign_vif_chanctx(struc
|
|
return;
|
|
}
|
|
|
|
- ret = ath11k_mac_vdev_stop(arvif);
|
|
- if (ret)
|
|
- ath11k_warn(ab, "failed to stop vdev %i: %d\n",
|
|
- arvif->vdev_id, ret);
|
|
-
|
|
- arvif->is_started = false;
|
|
-
|
|
- if (ab->hw_params.vdev_start_delay &&
|
|
- arvif->vdev_type == WMI_VDEV_TYPE_STA) {
|
|
- ret = ath11k_peer_delete(ar, arvif->vdev_id, arvif->bssid);
|
|
+ if (arvif->is_started) {
|
|
+ ret = ath11k_mac_vdev_stop(arvif);
|
|
if (ret)
|
|
- ath11k_warn(ar->ab,
|
|
- "failed to delete peer %pM for vdev %d: %d\n",
|
|
- arvif->bssid, arvif->vdev_id, ret);
|
|
- else
|
|
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
|
- "removed peer %pM vdev %d after vdev stop\n",
|
|
- arvif->bssid, arvif->vdev_id);
|
|
+ ath11k_warn(ab, "failed to stop vdev %i: %d\n",
|
|
+ arvif->vdev_id, ret);
|
|
+
|
|
+ arvif->is_started = false;
|
|
}
|
|
|
|
if (ab->hw_params.vdev_start_delay &&
|
|
@@ -9552,6 +9565,46 @@ exit:
|
|
return ret;
|
|
}
|
|
|
|
+static int ath11k_mac_station_remove(struct ath11k *ar,
|
|
+ struct ieee80211_vif *vif,
|
|
+ struct ieee80211_sta *sta)
|
|
+{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
|
+ struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
|
+ int ret;
|
|
+
|
|
+ if (ab->hw_params.vdev_start_delay &&
|
|
+ arvif->is_started &&
|
|
+ arvif->vdev_type != WMI_VDEV_TYPE_AP) {
|
|
+ ret = ath11k_mac_stop_vdev_early(ar->hw, vif);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ab, "failed to do early vdev stop: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ath11k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr);
|
|
+
|
|
+ ret = ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
|
+ if (ret)
|
|
+ ath11k_warn(ab, "Failed to delete peer: %pM for VDEV: %d\n",
|
|
+ sta->addr, arvif->vdev_id);
|
|
+ else
|
|
+ ath11k_dbg(ab, ATH11K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",
|
|
+ sta->addr, arvif->vdev_id);
|
|
+
|
|
+ ath11k_mac_dec_num_stations(arvif, sta);
|
|
+
|
|
+ kfree(arsta->tx_stats);
|
|
+ arsta->tx_stats = NULL;
|
|
+
|
|
+ kfree(arsta->rx_stats);
|
|
+ arsta->rx_stats = NULL;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_sta *sta,
|
|
@@ -9587,31 +9640,15 @@ static int ath11k_mac_op_sta_state(struc
|
|
sta->addr, arvif->vdev_id);
|
|
} else if ((old_state == IEEE80211_STA_NONE &&
|
|
new_state == IEEE80211_STA_NOTEXIST)) {
|
|
- bool skip_peer_delete = ar->ab->hw_params.vdev_start_delay &&
|
|
- vif->type == NL80211_IFTYPE_STATION;
|
|
-
|
|
- ath11k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr);
|
|
-
|
|
- if (!skip_peer_delete) {
|
|
- ret = ath11k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
|
- if (ret)
|
|
- ath11k_warn(ar->ab,
|
|
- "Failed to delete peer: %pM for VDEV: %d\n",
|
|
- sta->addr, arvif->vdev_id);
|
|
- else
|
|
- ath11k_dbg(ar->ab,
|
|
- ATH11K_DBG_MAC,
|
|
- "Removed peer: %pM for VDEV: %d\n",
|
|
- sta->addr, arvif->vdev_id);
|
|
- }
|
|
+ ret = ath11k_mac_station_remove(ar, vif, sta);
|
|
+ if (ret)
|
|
+ ath11k_warn(ar->ab, "Failed to remove station: %pM for VDEV: %d\n",
|
|
+ sta->addr, arvif->vdev_id);
|
|
|
|
- ath11k_mac_dec_num_stations(arvif, sta);
|
|
mutex_lock(&ar->ab->tbl_mtx_lock);
|
|
spin_lock_bh(&ar->ab->base_lock);
|
|
peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
|
|
- if (skip_peer_delete && peer) {
|
|
- peer->sta = NULL;
|
|
- } else if (peer && peer->sta == sta) {
|
|
+ if (peer && peer->sta == sta) {
|
|
ath11k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
|
|
vif->addr, arvif->vdev_id);
|
|
ath11k_peer_rhash_delete(ar->ab, peer);
|
|
@@ -9622,12 +9659,6 @@ static int ath11k_mac_op_sta_state(struc
|
|
}
|
|
spin_unlock_bh(&ar->ab->base_lock);
|
|
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
|
-
|
|
- kfree(arsta->tx_stats);
|
|
- arsta->tx_stats = NULL;
|
|
-
|
|
- kfree(arsta->rx_stats);
|
|
- arsta->rx_stats = NULL;
|
|
} else if (old_state == IEEE80211_STA_AUTH &&
|
|
new_state == IEEE80211_STA_ASSOC &&
|
|
(vif->type == NL80211_IFTYPE_AP ||
|
|
@@ -10200,6 +10231,8 @@ static int __ath11k_mac_register(struct
|
|
|
|
wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
|
|
|
+ wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
|
+
|
|
ar->hw->queues = ATH11K_HW_MAX_QUEUES;
|
|
ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN;
|
|
ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1;
|