From ce8c3108d5cea10b05edb03ba6ad7a99375d36b1 Mon Sep 17 00:00:00 2001 From: Saket Jha Date: Thu, 10 Oct 2019 19:48:09 -0700 Subject: [PATCH] qcacmn: Clear defrag waitlist in all cases Rx defrag waitlist was not getting cleared during dp_peer_rx_cleanup in the case of STA mode even though the tid was getting deleted. This created a scenario where the next time dp_rx_defrag_waitlist_remove was called, it was trying to access now invalid memory. If a vdev was disconnected in the middle of receiving traffic, then the tid would be deleted but the rx frag waitlist would not. Upon reconnecting, the reception of the next frag would cause a crash due to the now invalid memory in the waitlist. Change-Id: I5bb1a31f38fa45128d0f35fafaddaf729c99489d CRs-Fixed: 2538879 --- dp/wifi3.0/dp_peer.c | 4 ++-- dp/wifi3.0/dp_rx_defrag.c | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 8b2b0730ad..4593147d60 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -2298,12 +2298,12 @@ void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer, bool reuse) int tid; uint32_t tid_delete_mask = 0; - DP_TRACE(INFO_HIGH, FL("Remove tids for peer: %pK"), peer); + dp_info("Remove tids for peer: %pK", peer); for (tid = 0; tid < DP_MAX_TIDS; tid++) { struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; qdf_spin_lock_bh(&rx_tid->tid_lock); - if (!peer->bss_peer && peer->vdev->opmode != wlan_op_mode_sta) { + if (!peer->bss_peer || peer->vdev->opmode == wlan_op_mode_sta) { /* Cleanup defrag related resource */ dp_rx_defrag_waitlist_remove(peer, tid); dp_rx_reorder_flush_frag(peer, tid); diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c index c118404846..36188c5557 100644 --- a/dp/wifi3.0/dp_rx_defrag.c +++ b/dp/wifi3.0/dp_rx_defrag.c @@ -236,9 +236,8 @@ static void dp_rx_defrag_waitlist_add(struct dp_peer *peer, unsigned tid) struct dp_soc *psoc = peer->vdev->pdev->soc; struct dp_rx_tid *rx_reorder = &peer->rx_tid[tid]; - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - FL("Adding TID %u to waitlist for peer %pK"), - tid, peer); + dp_info("Adding TID %u to waitlist for peer %pK at MAC address %pM", + tid, peer, peer->mac_addr.raw); /* TODO: use LIST macros instead of TAIL macros */ qdf_spin_lock_bh(&psoc->rx.defrag.defrag_lock); @@ -266,11 +265,12 @@ void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid) struct dp_rx_tid *rx_reorder; struct dp_rx_tid *tmp; - if (tid > DP_MAX_TIDS) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "TID out of bounds: %d", tid); - qdf_assert(0); - return; + dp_info("Removing TID %u to waitlist for peer %pK at MAC address %pM", + tid, peer, peer->mac_addr.raw); + + if (tid >= DP_MAX_TIDS) { + dp_info("TID out of bounds: %d", tid); + qdf_assert_always(0); } qdf_spin_lock_bh(&soc->rx.defrag.defrag_lock); @@ -1431,6 +1431,11 @@ dp_rx_defrag_store_fragment(struct dp_soc *soc, goto discard_frag; } + if (tid >= DP_MAX_TIDS) { + dp_info("TID out of bounds: %d", tid); + qdf_assert_always(0); + } + pdev = peer->vdev->pdev; rx_tid = &peer->rx_tid[tid];