qcacmn: Release link descriptors on defrag errors

Link descriptors should be returned to WBM release ring if
fragments are not reinjected due to defrag errors.

Change-Id: Ia37db9f195f6848092918cf7cc221dc50e827ac5
This commit is contained in:
Karunakar Dasineni
2018-11-14 19:28:41 -08:00
committed by nshrivas
parent eec199494e
commit 6fb46e2759
3 changed files with 44 additions and 10 deletions

View File

@@ -6389,6 +6389,8 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
DP_PRINT_STATS("HAL Ring Access Fail = %d", DP_PRINT_STATS("HAL Ring Access Fail = %d",
soc->stats.rx.err.hal_ring_access_fail); soc->stats.rx.err.hal_ring_access_fail);
DP_PRINT_STATS("RX frags: %d", soc->stats.rx.rx_frags); 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); DP_PRINT_STATS("RX HP out_of_sync: %d", soc->stats.rx.hp_oos);
for (i = 0; i < HAL_RXDMA_ERR_MAX; i++) { for (i = 0; i < HAL_RXDMA_ERR_MAX; i++) {

View File

@@ -23,6 +23,7 @@
#include "hal_api.h" #include "hal_api.h"
#include "qdf_trace.h" #include "qdf_trace.h"
#include "qdf_nbuf.h" #include "qdf_nbuf.h"
#include "dp_internal.h"
#include "dp_rx_defrag.h" #include "dp_rx_defrag.h"
#include <enet.h> /* LLC_SNAP_HDR_LEN */ #include <enet.h> /* LLC_SNAP_HDR_LEN */
#include "dp_rx_defrag.h" #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, TAILQ_REMOVE(&soc->rx.defrag.waitlist, rx_reorder,
defrag_waitlist_elem); defrag_waitlist_elem);
DP_STATS_DEC(soc, rx.rx_frag_wait, 1);
/* Move to temp list and clean-up later */ /* Move to temp list and clean-up later */
TAILQ_INSERT_TAIL(&temp_list, rx_reorder, 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); qdf_spin_lock_bh(&psoc->rx.defrag.defrag_lock);
TAILQ_INSERT_TAIL(&psoc->rx.defrag.waitlist, rx_reorder, TAILQ_INSERT_TAIL(&psoc->rx.defrag.waitlist, rx_reorder,
defrag_waitlist_elem); defrag_waitlist_elem);
DP_STATS_INC(psoc, rx.rx_frag_wait, 1);
qdf_spin_unlock_bh(&psoc->rx.defrag.defrag_lock); 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]); rx_tid[rx_reorder->tid]);
/* Ensure it is TID for same peer */ /* 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, TAILQ_REMOVE(&soc->rx.defrag.waitlist,
rx_reorder, defrag_waitlist_elem); rx_reorder, defrag_waitlist_elem);
DP_STATS_DEC(soc, rx.rx_frag_wait, 1);
}
} }
qdf_spin_unlock_bh(&soc->rx.defrag.defrag_lock); 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); dp_rx_add_to_free_desc_list(head, tail, rx_desc);
*rx_bfs = 1; *rx_bfs = 1;
return QDF_STATUS_E_DEFRAG_ERROR; goto end;
} }
pdev = peer->vdev->pdev; 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 /* Drop stored fragments if out of sequence
* fragment is received * fragment is received
*/ */
dp_rx_defrag_frames_free(rx_reorder_array_elem->head); dp_rx_reorder_flush_frag(peer, tid);
rx_reorder_array_elem->head = NULL;
rx_reorder_array_elem->tail = NULL;
DP_STATS_INC(soc, rx.rx_frag_err, 1);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s mismatch, dropping earlier sequence ", "%s mismatch, dropping earlier sequence ",
(rxseq == rx_tid->curr_seq_num) (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 * new sequence number to be processed
*/ */
rx_tid->curr_seq_num = rxseq; rx_tid->curr_seq_num = rxseq;
} }
} else { } else {
/* Start of a new sequence */ /* 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; return QDF_STATUS_SUCCESS;
end: end:
if (peer)
dp_peer_unref_del_find_by_id(peer); dp_peer_unref_del_find_by_id(peer);
DP_STATS_INC(soc, rx.rx_frag_err, 1);
return QDF_STATUS_E_DEFRAG_ERROR; 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; uint32_t tid, msdu_len;
int idx, rx_bfs = 0; int idx, rx_bfs = 0;
struct dp_pdev *pdev; 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(soc);
qdf_assert(mpdu_desc_info); 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); &mpdu_desc_info->msdu_count);
/* Process all MSDUs in the current MPDU */ /* 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 = struct dp_rx_desc *rx_desc =
dp_rx_cookie_2_va_rxdma_buf(soc, dp_rx_cookie_2_va_rxdma_buf(soc,
msdu_list.sw_cookie[idx]); 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; return rx_bufs_used;
} }

View File

@@ -592,6 +592,10 @@ struct dp_soc_stats {
uint32_t err_ring_pkts; uint32_t err_ring_pkts;
/* No of Fragments */ /* No of Fragments */
uint32_t rx_frags; 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 */ /* No of reinjected packets */
uint32_t reo_reinject; uint32_t reo_reinject;
/* Head pointer Out of sync */ /* Head pointer Out of sync */