diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 8ef37679e9e7..fdcce494a511 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -2253,6 +2253,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) wlan_cfg_get_rx_defrag_min_timeout(soc->wlan_cfg_ctx); soc->rx.flags.defrag_timeout_check = wlan_cfg_get_defrag_timeout_check(soc->wlan_cfg_ctx); + qdf_spinlock_create(&soc->rx.defrag.defrag_lock); out: /* @@ -3048,6 +3049,8 @@ static void dp_soc_detach_wifi3(void *txrx_soc) htt_soc_detach(soc->htt_handle); + qdf_spinlock_destroy(&soc->rx.defrag.defrag_lock); + dp_reo_cmdlist_destroy(soc); qdf_spinlock_destroy(&soc->rx.reo_cmd_lock); dp_reo_desc_freelist_destroy(soc); diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index a2474e56894b..d947e46be1f9 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -22,6 +22,7 @@ #include "dp_types.h" #include "dp_internal.h" #include "dp_peer.h" +#include "dp_rx_defrag.h" #include #include #ifdef CONFIG_MCL @@ -1570,6 +1571,11 @@ void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer) for (tid = 0; tid < DP_MAX_TIDS; tid++) { if (peer->rx_tid[tid].hw_qdesc_vaddr_unaligned != NULL) { dp_rx_tid_delete_wifi3(peer, tid); + + /* Cleanup defrag related resource */ + dp_rx_defrag_waitlist_remove(peer, tid); + dp_rx_reorder_flush_frag(peer, tid); + tid_delete_mask |= (1 << tid); } } diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c index f2a63a654813..0f35d9cd59d2 100644 --- a/dp/wifi3.0/dp_rx_defrag.c +++ b/dp/wifi3.0/dp_rx_defrag.c @@ -150,10 +150,13 @@ void dp_rx_defrag_waitlist_flush(struct dp_soc *soc) struct dp_rx_tid *rx_reorder; struct dp_rx_tid *tmp; uint32_t now_ms = qdf_system_ticks_to_msecs(qdf_system_ticks()); + TAILQ_HEAD(, dp_rx_tid) temp_list; + TAILQ_INIT(&temp_list); + + qdf_spin_lock_bh(&soc->rx.defrag.defrag_lock); TAILQ_FOREACH_SAFE(rx_reorder, &soc->rx.defrag.waitlist, defrag_waitlist_elem, tmp) { - struct dp_peer *peer; unsigned int tid; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -170,14 +173,24 @@ void dp_rx_defrag_waitlist_flush(struct dp_soc *soc) continue; } + TAILQ_REMOVE(&soc->rx.defrag.waitlist, rx_reorder, + defrag_waitlist_elem); + + /* Move to temp list and clean-up later */ + TAILQ_INSERT_TAIL(&temp_list, rx_reorder, + defrag_waitlist_elem); + } + qdf_spin_unlock_bh(&soc->rx.defrag.defrag_lock); + + TAILQ_FOREACH_SAFE(rx_reorder, &temp_list, + defrag_waitlist_elem, tmp) { + struct dp_peer *peer; + /* get address of current peer */ peer = container_of(rx_reorder, struct dp_peer, - rx_tid[tid]); - - TAILQ_REMOVE(&soc->rx.defrag.waitlist, rx_reorder, - defrag_waitlist_elem); - dp_rx_reorder_flush_frag(peer, tid); + rx_tid[rx_reorder->tid]); + dp_rx_reorder_flush_frag(peer, rx_reorder->tid); } } @@ -200,8 +213,10 @@ static void dp_rx_defrag_waitlist_add(struct dp_peer *peer, unsigned tid) tid, peer); /* TODO: use LIST macros instead of TAIL macros */ + qdf_spin_lock_bh(&psoc->rx.defrag.defrag_lock); TAILQ_INSERT_TAIL(&psoc->rx.defrag.waitlist, rx_reorder, defrag_waitlist_elem); + qdf_spin_unlock_bh(&psoc->rx.defrag.defrag_lock); } /* @@ -230,6 +245,7 @@ void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid) FL("Remove TID %u from waitlist for peer %pK"), tid, peer); + qdf_spin_lock_bh(&soc->rx.defrag.defrag_lock); TAILQ_FOREACH(rx_reorder, &soc->rx.defrag.waitlist, defrag_waitlist_elem) { struct dp_peer *peer_on_waitlist; @@ -244,6 +260,7 @@ void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid) TAILQ_REMOVE(&soc->rx.defrag.waitlist, rx_reorder, defrag_waitlist_elem); } + qdf_spin_unlock_bh(&soc->rx.defrag.defrag_lock); } /* diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 8251fbb7c9ad..4fcfe2d059e5 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -755,6 +755,7 @@ struct dp_soc { struct { TAILQ_HEAD(, dp_rx_tid) waitlist; uint32_t timeout_ms; + qdf_spinlock_t defrag_lock; } defrag; struct { int defrag_timeout_check;