qcacmn: Add Sanity checks during RX processing
- Check for rx_desc.magic before using a rx_desc retrieved from the reo destination ring via rx_buf_cookie (dp_rx_process). Add stats. - Check if we end up re-using a rx_desc with rx_desc.in_use=1 in the replenish path (dp_rx_buffers_replenish). - Drop RX packet and assert in case MSDU Done failures are seen in in the TLV during dp_rx_process. Add stats. - Disable host2rxdma ring mask for MCL. MCL is not expected to be receiving these interrupts. Change-Id: Iaa345d04b8d48814f88ed6e2237fc67696f6a20c CRs-Fixed: 2382076
This commit is contained in:

committad av
nshrivas

förälder
9e4bb950e4
incheckning
16cd1b2e8d
@@ -6859,10 +6859,14 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
|
||||
soc->stats.rx.err.rx_invalid_peer.num);
|
||||
DP_PRINT_STATS("HAL Ring Access Fail = %d",
|
||||
soc->stats.rx.err.hal_ring_access_fail);
|
||||
DP_PRINT_STATS("MSDU Done failures = %d",
|
||||
soc->stats.rx.err.msdu_done_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);
|
||||
DP_PRINT_STATS("RX DESC invalid magic: %u",
|
||||
soc->stats.rx.err.rx_desc_invalid_magic);
|
||||
DP_PRINT_STATS("RX DUP DESC: %d",
|
||||
soc->stats.rx.err.hal_reo_dest_dup);
|
||||
DP_PRINT_STATS("RX REL DUP DESC: %d",
|
||||
@@ -6873,8 +6877,7 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
|
||||
DP_RXDMA_ERR_LENGTH - index,
|
||||
" %d", soc->stats.rx.err.rxdma_error[i]);
|
||||
}
|
||||
DP_PRINT_STATS("RXDMA Error (0-31):%s",
|
||||
rxdma_error);
|
||||
DP_PRINT_STATS("RXDMA Error (0-31):%s", rxdma_error);
|
||||
|
||||
index = 0;
|
||||
for (i = 0; i < HAL_REO_ERR_MAX; i++) {
|
||||
@@ -6882,8 +6885,7 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
|
||||
DP_REO_ERR_LENGTH - index,
|
||||
" %d", soc->stats.rx.err.reo_error[i]);
|
||||
}
|
||||
DP_PRINT_STATS("REO Error(0-14):%s",
|
||||
reo_error);
|
||||
DP_PRINT_STATS("REO Error(0-14):%s", reo_error);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -30,19 +30,6 @@
|
||||
#include "dp_rx_mon.h"
|
||||
#include "dp_ipa.h"
|
||||
|
||||
#ifdef RX_DESC_DEBUG_CHECK
|
||||
static inline void dp_rx_desc_prep(struct dp_rx_desc *rx_desc, qdf_nbuf_t nbuf)
|
||||
{
|
||||
rx_desc->magic = DP_RX_DESC_MAGIC;
|
||||
rx_desc->nbuf = nbuf;
|
||||
}
|
||||
#else
|
||||
static inline void dp_rx_desc_prep(struct dp_rx_desc *rx_desc, qdf_nbuf_t nbuf)
|
||||
{
|
||||
rx_desc->nbuf = nbuf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WIN
|
||||
static inline bool dp_rx_check_ap_bridge(struct dp_vdev *vdev)
|
||||
{
|
||||
@@ -93,7 +80,7 @@ void dp_rx_dump_info_and_assert(struct dp_soc *soc, void *hal_ring,
|
||||
dp_rx_desc_dump(rx_desc);
|
||||
hal_srng_dump_ring_desc(hal_soc, hal_ring, ring_desc);
|
||||
hal_srng_dump_ring(hal_soc, hal_ring);
|
||||
qdf_assert_always(rx_desc->in_use);
|
||||
qdf_assert_always(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -208,7 +195,7 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
|
||||
}
|
||||
|
||||
ret = qdf_nbuf_map_single(dp_soc->osdev, rx_netbuf,
|
||||
QDF_DMA_BIDIRECTIONAL);
|
||||
QDF_DMA_BIDIRECTIONAL);
|
||||
if (qdf_unlikely(QDF_IS_STATUS_ERROR(ret))) {
|
||||
qdf_nbuf_free(rx_netbuf);
|
||||
DP_STATS_INC(dp_pdev, replenish.map_err, 1);
|
||||
@@ -232,12 +219,16 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
|
||||
count++;
|
||||
|
||||
rxdma_ring_entry = hal_srng_src_get_next(dp_soc->hal_soc,
|
||||
rxdma_srng);
|
||||
rxdma_srng);
|
||||
qdf_assert_always(rxdma_ring_entry);
|
||||
|
||||
next = (*desc_list)->next;
|
||||
|
||||
dp_rx_desc_prep(&((*desc_list)->rx_desc), rx_netbuf);
|
||||
|
||||
/* rx_desc.in_use should be zero at this time*/
|
||||
qdf_assert_always((*desc_list)->rx_desc.in_use == 0);
|
||||
|
||||
(*desc_list)->rx_desc.in_use = 1;
|
||||
|
||||
dp_verbose_debug("rx_netbuf=%pK, buf=%pK, paddr=0x%llx, cookie=%d",
|
||||
@@ -1597,6 +1588,14 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring,
|
||||
*/
|
||||
if (qdf_unlikely(!rx_desc->in_use)) {
|
||||
DP_STATS_INC(soc, rx.err.hal_reo_dest_dup, 1);
|
||||
dp_err("Reaping rx_desc not in use!");
|
||||
dp_rx_dump_info_and_assert(soc, hal_ring,
|
||||
ring_desc, rx_desc);
|
||||
}
|
||||
|
||||
if (qdf_unlikely(!dp_rx_desc_check_magic(rx_desc))) {
|
||||
dp_err("Invalid rx_desc cookie=%d", rx_buf_cookie);
|
||||
DP_STATS_INC(soc, rx.err.rx_desc_invalid_magic, 1);
|
||||
dp_rx_dump_info_and_assert(soc, hal_ring,
|
||||
ring_desc, rx_desc);
|
||||
}
|
||||
@@ -1610,6 +1609,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring,
|
||||
*/
|
||||
qdf_nbuf_unmap_single(soc->osdev, rx_desc->nbuf,
|
||||
QDF_DMA_BIDIRECTIONAL);
|
||||
rx_desc->unmapped = 1;
|
||||
|
||||
core_id = smp_processor_id();
|
||||
DP_STATS_INC(soc, rx.ring_packets[core_id][ring_id], 1);
|
||||
@@ -1702,12 +1702,15 @@ done:
|
||||
dp_rx_save_tid_ts(nbuf, tid, rx_pdev->delay_stats_flag);
|
||||
tid_stats = &rx_pdev->stats.tid_stats.tid_rx_stats[tid];
|
||||
if (qdf_unlikely(!hal_rx_attn_msdu_done_get(rx_tlv_hdr))) {
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("MSDU DONE failure"));
|
||||
dp_err("MSDU DONE failure");
|
||||
DP_STATS_INC(soc, rx.err.msdu_done_fail, 1);
|
||||
hal_rx_dump_pkt_tlvs(hal_soc, rx_tlv_hdr,
|
||||
QDF_TRACE_LEVEL_INFO);
|
||||
tid_stats->fail_cnt[MSDU_DONE_FAILURE]++;
|
||||
qdf_assert(0);
|
||||
qdf_nbuf_free(nbuf);
|
||||
qdf_assert_always(0);
|
||||
nbuf = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
tid_stats->msdu_cnt++;
|
||||
|
@@ -56,6 +56,7 @@
|
||||
#endif /* QCA_HOST2FW_RXBUF_RING */
|
||||
|
||||
#define RX_BUFFER_RESERVATION 0
|
||||
#define RX_BUFFER_SIZE 2048
|
||||
|
||||
#define DP_PEER_METADATA_PEER_ID_MASK 0x0000ffff
|
||||
#define DP_PEER_METADATA_PEER_ID_SHIFT 0
|
||||
@@ -394,7 +395,6 @@ void dp_rx_add_to_free_desc_list(union dp_rx_desc_list_elem_t **head,
|
||||
|
||||
new->nbuf = NULL;
|
||||
new->in_use = 0;
|
||||
new->unmapped = 0;
|
||||
|
||||
((union dp_rx_desc_list_elem_t *)new)->next = *head;
|
||||
*head = (union dp_rx_desc_list_elem_t *)new;
|
||||
@@ -991,4 +991,45 @@ void dp_rx_dump_info_and_assert(struct dp_soc *soc, void *hal_ring,
|
||||
void *ring_desc, struct dp_rx_desc *rx_desc);
|
||||
|
||||
void dp_rx_compute_delay(struct dp_vdev *vdev, qdf_nbuf_t nbuf);
|
||||
#ifdef RX_DESC_DEBUG_CHECK
|
||||
/**
|
||||
* dp_rx_desc_check_magic() - check the magic value in dp_rx_desc
|
||||
* @rx_desc: rx descriptor pointer
|
||||
*
|
||||
* Return: true, if magic is correct, else false.
|
||||
*/
|
||||
static inline bool dp_rx_desc_check_magic(struct dp_rx_desc *rx_desc)
|
||||
{
|
||||
if (qdf_unlikely(rx_desc->magic != DP_RX_DESC_MAGIC))
|
||||
return false;
|
||||
|
||||
rx_desc->magic = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_rx_desc_prep() - prepare rx desc
|
||||
* @rx_desc: rx descriptor pointer to be prepared
|
||||
* @nbuf: nbuf to be associated with rx_desc
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
static inline void dp_rx_desc_prep(struct dp_rx_desc *rx_desc, qdf_nbuf_t nbuf)
|
||||
{
|
||||
rx_desc->magic = DP_RX_DESC_MAGIC;
|
||||
rx_desc->nbuf = nbuf;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline bool dp_rx_desc_check_magic(struct dp_rx_desc *rx_desc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void dp_rx_desc_prep(struct dp_rx_desc *rx_desc, qdf_nbuf_t nbuf)
|
||||
{
|
||||
rx_desc->nbuf = nbuf;
|
||||
}
|
||||
#endif /* RX_DESC_DEBUG_CHECK */
|
||||
#endif /* _DP_RX_H */
|
||||
|
@@ -32,22 +32,6 @@
|
||||
#include "dp_rx_defrag.h"
|
||||
#include <enet.h> /* LLC_SNAP_HDR_LEN */
|
||||
|
||||
#ifdef RX_DESC_DEBUG_CHECK
|
||||
static inline bool dp_rx_desc_check_magic(struct dp_rx_desc *rx_desc)
|
||||
{
|
||||
if (qdf_unlikely(rx_desc->magic != DP_RX_DESC_MAGIC)) {
|
||||
return false;
|
||||
}
|
||||
rx_desc->magic = 0;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static inline bool dp_rx_desc_check_magic(struct dp_rx_desc *rx_desc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* dp_rx_mcast_echo_check() - check if the mcast pkt is a loop
|
||||
* back on same vap or a different vap.
|
||||
|
@@ -609,8 +609,11 @@ struct dp_soc_stats {
|
||||
uint32_t invalid_vdev;
|
||||
/* Invalid PDEV error count */
|
||||
uint32_t invalid_pdev;
|
||||
|
||||
/* Invalid sa_idx or da_idx*/
|
||||
uint32_t invalid_sa_da_idx;
|
||||
/* MSDU DONE failures */
|
||||
uint32_t msdu_done_fail;
|
||||
/* Invalid PEER Error count */
|
||||
struct cdp_pkt_info rx_invalid_peer;
|
||||
/* Invalid PEER ID count */
|
||||
@@ -619,6 +622,8 @@ struct dp_soc_stats {
|
||||
uint32_t hal_ring_access_fail;
|
||||
/* RX DMA error count */
|
||||
uint32_t rxdma_error[HAL_RXDMA_ERR_MAX];
|
||||
/* RX REO DEST Desc Invalid Magic count */
|
||||
uint32_t rx_desc_invalid_magic;
|
||||
/* REO Error count */
|
||||
uint32_t reo_error[HAL_REO_ERR_MAX];
|
||||
/* HAL REO ERR Count */
|
||||
|
@@ -129,7 +129,7 @@ static const int rx_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {
|
||||
WLAN_CFG_RX_MON_RING_MASK_3};
|
||||
|
||||
static const int host2rxdma_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {
|
||||
WLAN_CFG_HOST2RXDMA_RING_MASK_0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
Referens i nytt ärende
Block a user