From f8ccc18f6a4ecd9d447f2f4edb24fe5391e896ef Mon Sep 17 00:00:00 2001 From: Om Prakash Tripathi Date: Wed, 14 Nov 2018 15:24:09 +0530 Subject: [PATCH] qcacmn: Check delete in progress before adding wds entry In Repeater configuration when a STA first associates to Root AP on some radio and then roams quickly to repeater AP on other radio, some times target assert is observed due to below race condition. 1. Root AP sends peer delete command to FW on radio X and clears its AST entry. This peer delete command not processed by FW yet. 2. STA roames to repeater AP and starts ping traffic to Root AP. 3. Root AP receives the ping frame and tries to add wds entry on radio Y as AST entry was not found. 4. FW receives add wds entry on radio Y while on radio X an direct peer ast entry for same mac was present. 5. FW asserts. Change-Id: I02ac409f2b4f6b2ea307d99c5f1fdab7776ca938 CRs-Fixed: 2347818 --- dp/wifi3.0/dp_rx.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index f6a266ee68ac..ef581e6511fd 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -398,8 +398,10 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, uint32_t ret = 0; uint8_t wds_src_mac[IEEE80211_ADDR_LEN]; struct dp_peer *sa_peer; + struct dp_peer *wds_peer; struct dp_ast_entry *ast; uint16_t sa_idx; + bool del_in_progress; if (qdf_unlikely(!ta_peer)) return; @@ -459,12 +461,31 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, * invalidate this GSE cache entry and new AST entry gets * cached. */ - if (!soc->ast_override_support) + if (!soc->ast_override_support) { + wds_peer = dp_peer_find_hash_find(soc, wds_src_mac, + 0, DP_VDEV_ALL); + if (wds_peer) { + del_in_progress = wds_peer->delete_in_progress; + dp_peer_unref_delete(wds_peer); + if (!del_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_FATAL, + "wds peer %pM found", + wds_src_mac); + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_FATAL, + "No AST no Del in progress"); + QDF_BUG(0); + } else { + return; + } + } ret = dp_peer_add_ast(soc, ta_peer, wds_src_mac, CDP_TXRX_AST_TYPE_WDS, flags); + } return; }