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:
@@ -6859,10 +6859,14 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
|
|||||||
soc->stats.rx.err.rx_invalid_peer.num);
|
soc->stats.rx.err.rx_invalid_peer.num);
|
||||||
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("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 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 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 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);
|
||||||
|
DP_PRINT_STATS("RX DESC invalid magic: %u",
|
||||||
|
soc->stats.rx.err.rx_desc_invalid_magic);
|
||||||
DP_PRINT_STATS("RX DUP DESC: %d",
|
DP_PRINT_STATS("RX DUP DESC: %d",
|
||||||
soc->stats.rx.err.hal_reo_dest_dup);
|
soc->stats.rx.err.hal_reo_dest_dup);
|
||||||
DP_PRINT_STATS("RX REL DUP DESC: %d",
|
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,
|
DP_RXDMA_ERR_LENGTH - index,
|
||||||
" %d", soc->stats.rx.err.rxdma_error[i]);
|
" %d", soc->stats.rx.err.rxdma_error[i]);
|
||||||
}
|
}
|
||||||
DP_PRINT_STATS("RXDMA Error (0-31):%s",
|
DP_PRINT_STATS("RXDMA Error (0-31):%s", rxdma_error);
|
||||||
rxdma_error);
|
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
for (i = 0; i < HAL_REO_ERR_MAX; i++) {
|
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,
|
DP_REO_ERR_LENGTH - index,
|
||||||
" %d", soc->stats.rx.err.reo_error[i]);
|
" %d", soc->stats.rx.err.reo_error[i]);
|
||||||
}
|
}
|
||||||
DP_PRINT_STATS("REO Error(0-14):%s",
|
DP_PRINT_STATS("REO Error(0-14):%s", reo_error);
|
||||||
reo_error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -30,19 +30,6 @@
|
|||||||
#include "dp_rx_mon.h"
|
#include "dp_rx_mon.h"
|
||||||
#include "dp_ipa.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
|
#ifdef CONFIG_WIN
|
||||||
static inline bool dp_rx_check_ap_bridge(struct dp_vdev *vdev)
|
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);
|
dp_rx_desc_dump(rx_desc);
|
||||||
hal_srng_dump_ring_desc(hal_soc, hal_ring, ring_desc);
|
hal_srng_dump_ring_desc(hal_soc, hal_ring, ring_desc);
|
||||||
hal_srng_dump_ring(hal_soc, hal_ring);
|
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,
|
ret = qdf_nbuf_map_single(dp_soc->osdev, rx_netbuf,
|
||||||
QDF_DMA_BIDIRECTIONAL);
|
QDF_DMA_BIDIRECTIONAL);
|
||||||
if (qdf_unlikely(QDF_IS_STATUS_ERROR(ret))) {
|
if (qdf_unlikely(QDF_IS_STATUS_ERROR(ret))) {
|
||||||
qdf_nbuf_free(rx_netbuf);
|
qdf_nbuf_free(rx_netbuf);
|
||||||
DP_STATS_INC(dp_pdev, replenish.map_err, 1);
|
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++;
|
count++;
|
||||||
|
|
||||||
rxdma_ring_entry = hal_srng_src_get_next(dp_soc->hal_soc,
|
rxdma_ring_entry = hal_srng_src_get_next(dp_soc->hal_soc,
|
||||||
rxdma_srng);
|
rxdma_srng);
|
||||||
qdf_assert_always(rxdma_ring_entry);
|
qdf_assert_always(rxdma_ring_entry);
|
||||||
|
|
||||||
next = (*desc_list)->next;
|
next = (*desc_list)->next;
|
||||||
|
|
||||||
dp_rx_desc_prep(&((*desc_list)->rx_desc), rx_netbuf);
|
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;
|
(*desc_list)->rx_desc.in_use = 1;
|
||||||
|
|
||||||
dp_verbose_debug("rx_netbuf=%pK, buf=%pK, paddr=0x%llx, cookie=%d",
|
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)) {
|
if (qdf_unlikely(!rx_desc->in_use)) {
|
||||||
DP_STATS_INC(soc, rx.err.hal_reo_dest_dup, 1);
|
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,
|
dp_rx_dump_info_and_assert(soc, hal_ring,
|
||||||
ring_desc, rx_desc);
|
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_nbuf_unmap_single(soc->osdev, rx_desc->nbuf,
|
||||||
QDF_DMA_BIDIRECTIONAL);
|
QDF_DMA_BIDIRECTIONAL);
|
||||||
|
rx_desc->unmapped = 1;
|
||||||
|
|
||||||
core_id = smp_processor_id();
|
core_id = smp_processor_id();
|
||||||
DP_STATS_INC(soc, rx.ring_packets[core_id][ring_id], 1);
|
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);
|
dp_rx_save_tid_ts(nbuf, tid, rx_pdev->delay_stats_flag);
|
||||||
tid_stats = &rx_pdev->stats.tid_stats.tid_rx_stats[tid];
|
tid_stats = &rx_pdev->stats.tid_stats.tid_rx_stats[tid];
|
||||||
if (qdf_unlikely(!hal_rx_attn_msdu_done_get(rx_tlv_hdr))) {
|
if (qdf_unlikely(!hal_rx_attn_msdu_done_get(rx_tlv_hdr))) {
|
||||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
dp_err("MSDU DONE failure");
|
||||||
FL("MSDU DONE failure"));
|
DP_STATS_INC(soc, rx.err.msdu_done_fail, 1);
|
||||||
hal_rx_dump_pkt_tlvs(hal_soc, rx_tlv_hdr,
|
hal_rx_dump_pkt_tlvs(hal_soc, rx_tlv_hdr,
|
||||||
QDF_TRACE_LEVEL_INFO);
|
QDF_TRACE_LEVEL_INFO);
|
||||||
tid_stats->fail_cnt[MSDU_DONE_FAILURE]++;
|
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++;
|
tid_stats->msdu_cnt++;
|
||||||
|
@@ -56,6 +56,7 @@
|
|||||||
#endif /* QCA_HOST2FW_RXBUF_RING */
|
#endif /* QCA_HOST2FW_RXBUF_RING */
|
||||||
|
|
||||||
#define RX_BUFFER_RESERVATION 0
|
#define RX_BUFFER_RESERVATION 0
|
||||||
|
#define RX_BUFFER_SIZE 2048
|
||||||
|
|
||||||
#define DP_PEER_METADATA_PEER_ID_MASK 0x0000ffff
|
#define DP_PEER_METADATA_PEER_ID_MASK 0x0000ffff
|
||||||
#define DP_PEER_METADATA_PEER_ID_SHIFT 0
|
#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->nbuf = NULL;
|
||||||
new->in_use = 0;
|
new->in_use = 0;
|
||||||
new->unmapped = 0;
|
|
||||||
|
|
||||||
((union dp_rx_desc_list_elem_t *)new)->next = *head;
|
((union dp_rx_desc_list_elem_t *)new)->next = *head;
|
||||||
*head = (union dp_rx_desc_list_elem_t *)new;
|
*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 *ring_desc, struct dp_rx_desc *rx_desc);
|
||||||
|
|
||||||
void dp_rx_compute_delay(struct dp_vdev *vdev, qdf_nbuf_t nbuf);
|
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 */
|
#endif /* _DP_RX_H */
|
||||||
|
@@ -32,22 +32,6 @@
|
|||||||
#include "dp_rx_defrag.h"
|
#include "dp_rx_defrag.h"
|
||||||
#include <enet.h> /* LLC_SNAP_HDR_LEN */
|
#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
|
* dp_rx_mcast_echo_check() - check if the mcast pkt is a loop
|
||||||
* back on same vap or a different vap.
|
* back on same vap or a different vap.
|
||||||
|
@@ -609,8 +609,11 @@ struct dp_soc_stats {
|
|||||||
uint32_t invalid_vdev;
|
uint32_t invalid_vdev;
|
||||||
/* Invalid PDEV error count */
|
/* Invalid PDEV error count */
|
||||||
uint32_t invalid_pdev;
|
uint32_t invalid_pdev;
|
||||||
|
|
||||||
/* Invalid sa_idx or da_idx*/
|
/* Invalid sa_idx or da_idx*/
|
||||||
uint32_t invalid_sa_da_idx;
|
uint32_t invalid_sa_da_idx;
|
||||||
|
/* MSDU DONE failures */
|
||||||
|
uint32_t msdu_done_fail;
|
||||||
/* Invalid PEER Error count */
|
/* Invalid PEER Error count */
|
||||||
struct cdp_pkt_info rx_invalid_peer;
|
struct cdp_pkt_info rx_invalid_peer;
|
||||||
/* Invalid PEER ID count */
|
/* Invalid PEER ID count */
|
||||||
@@ -619,6 +622,8 @@ struct dp_soc_stats {
|
|||||||
uint32_t hal_ring_access_fail;
|
uint32_t hal_ring_access_fail;
|
||||||
/* RX DMA error count */
|
/* RX DMA error count */
|
||||||
uint32_t rxdma_error[HAL_RXDMA_ERR_MAX];
|
uint32_t rxdma_error[HAL_RXDMA_ERR_MAX];
|
||||||
|
/* RX REO DEST Desc Invalid Magic count */
|
||||||
|
uint32_t rx_desc_invalid_magic;
|
||||||
/* REO Error count */
|
/* REO Error count */
|
||||||
uint32_t reo_error[HAL_REO_ERR_MAX];
|
uint32_t reo_error[HAL_REO_ERR_MAX];
|
||||||
/* HAL REO ERR Count */
|
/* 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};
|
WLAN_CFG_RX_MON_RING_MASK_3};
|
||||||
|
|
||||||
static const int host2rxdma_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {
|
static const int host2rxdma_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {
|
||||||
WLAN_CFG_HOST2RXDMA_RING_MASK_0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
Reference in New Issue
Block a user