diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 72ce664be6..8bedec49e6 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -6389,6 +6389,8 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("HAL Ring Access Fail = %d", soc->stats.rx.err.hal_ring_access_fail); DP_PRINT_STATS("RX frags: %d", soc->stats.rx.rx_frags); + DP_PRINT_STATS("RX frag wait: %d", soc->stats.rx.rx_frag_wait); + DP_PRINT_STATS("RX frag err: %d", soc->stats.rx.rx_frag_err); DP_PRINT_STATS("RX HP out_of_sync: %d", soc->stats.rx.hp_oos); for (i = 0; i < HAL_RXDMA_ERR_MAX; i++) { diff --git a/dp/wifi3.0/dp_rx_defrag.c b/dp/wifi3.0/dp_rx_defrag.c index 29aa2c636f..add2db2be5 100644 --- a/dp/wifi3.0/dp_rx_defrag.c +++ b/dp/wifi3.0/dp_rx_defrag.c @@ -23,6 +23,7 @@ #include "hal_api.h" #include "qdf_trace.h" #include "qdf_nbuf.h" +#include "dp_internal.h" #include "dp_rx_defrag.h" #include /* LLC_SNAP_HDR_LEN */ #include "dp_rx_defrag.h" @@ -182,6 +183,7 @@ void dp_rx_defrag_waitlist_flush(struct dp_soc *soc) TAILQ_REMOVE(&soc->rx.defrag.waitlist, rx_reorder, defrag_waitlist_elem); + DP_STATS_DEC(soc, rx.rx_frag_wait, 1); /* Move to temp list and clean-up later */ TAILQ_INSERT_TAIL(&temp_list, rx_reorder, @@ -226,6 +228,7 @@ static void dp_rx_defrag_waitlist_add(struct dp_peer *peer, unsigned tid) qdf_spin_lock_bh(&psoc->rx.defrag.defrag_lock); TAILQ_INSERT_TAIL(&psoc->rx.defrag.waitlist, rx_reorder, defrag_waitlist_elem); + DP_STATS_INC(psoc, rx.rx_frag_wait, 1); qdf_spin_unlock_bh(&psoc->rx.defrag.defrag_lock); } @@ -262,9 +265,11 @@ void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid) rx_tid[rx_reorder->tid]); /* Ensure it is TID for same peer */ - if (peer_on_waitlist == peer && rx_reorder->tid == tid) + if (peer_on_waitlist == peer && rx_reorder->tid == tid) { TAILQ_REMOVE(&soc->rx.defrag.waitlist, rx_reorder, defrag_waitlist_elem); + DP_STATS_DEC(soc, rx.rx_frag_wait, 1); + } } qdf_spin_unlock_bh(&soc->rx.defrag.defrag_lock); } @@ -1384,7 +1389,7 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, dp_rx_add_to_free_desc_list(head, tail, rx_desc); *rx_bfs = 1; - return QDF_STATUS_E_DEFRAG_ERROR; + goto end; } pdev = peer->vdev->pdev; @@ -1458,11 +1463,9 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, /* Drop stored fragments if out of sequence * fragment is received */ - dp_rx_defrag_frames_free(rx_reorder_array_elem->head); - - rx_reorder_array_elem->head = NULL; - rx_reorder_array_elem->tail = NULL; + dp_rx_reorder_flush_frag(peer, tid); + DP_STATS_INC(soc, rx.rx_frag_err, 1); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s mismatch, dropping earlier sequence ", (rxseq == rx_tid->curr_seq_num) @@ -1474,7 +1477,6 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, * new sequence number to be processed */ rx_tid->curr_seq_num = rxseq; - } } else { /* Start of a new sequence */ @@ -1584,8 +1586,10 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, return QDF_STATUS_SUCCESS; end: - dp_peer_unref_del_find_by_id(peer); + if (peer) + dp_peer_unref_del_find_by_id(peer); + DP_STATS_INC(soc, rx.rx_frag_err, 1); return QDF_STATUS_E_DEFRAG_ERROR; } @@ -1621,7 +1625,8 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc, uint32_t tid, msdu_len; int idx, rx_bfs = 0; struct dp_pdev *pdev; - QDF_STATUS status; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_rx_desc *rx_desc = NULL; qdf_assert(soc); qdf_assert(mpdu_desc_info); @@ -1649,7 +1654,7 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc, &mpdu_desc_info->msdu_count); /* Process all MSDUs in the current MPDU */ - for (idx = 0; (idx < mpdu_desc_info->msdu_count) && quota--; idx++) { + for (idx = 0; (idx < mpdu_desc_info->msdu_count); idx++) { struct dp_rx_desc *rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, msdu_list.sw_cookie[idx]); @@ -1698,6 +1703,29 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc, } } + if (!QDF_IS_STATUS_SUCCESS(status)) { + /* drop any remaining buffers in current descriptor */ + idx++; + for (; (idx < mpdu_desc_info->msdu_count); idx++) { + rx_desc = + dp_rx_cookie_2_va_rxdma_buf(soc, + msdu_list.sw_cookie[idx]); + qdf_assert(rx_desc); + msdu = rx_desc->nbuf; + qdf_nbuf_unmap_single(soc->osdev, msdu, + QDF_DMA_BIDIRECTIONAL); + qdf_nbuf_free(msdu); + dp_rx_add_to_free_desc_list(&pdev->free_list_head, + &pdev->free_list_tail, + rx_desc); + rx_bufs_used++; + } + if (dp_rx_link_desc_return(soc, ring_desc, + HAL_BM_ACTION_PUT_IN_IDLE_LIST) != + QDF_STATUS_SUCCESS) + dp_err("Failed to return link desc"); + } + return rx_bufs_used; } diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 90f63f26ef..8980efa4e5 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -592,6 +592,10 @@ struct dp_soc_stats { uint32_t err_ring_pkts; /* No of Fragments */ uint32_t rx_frags; + /* No of incomplete fragments in waitlist */ + uint32_t rx_frag_wait; + /* Fragments dropped due to errors */ + uint32_t rx_frag_err; /* No of reinjected packets */ uint32_t reo_reinject; /* Head pointer Out of sync */