qcacmn: Handle the duplicate entries in reo exception ring
We have come across scenarios where rxdma is pushing a certain entry more than once to the reo exception ring. In this scenario, when we try to unmap a buffer, it can lead to multiple unmap of the same buffer. Handle this case, by skipping the process of this duplicate entry, if alrady unmapped, and proceed to the next entry. Change-Id: Iae66f27e432f795ba4730911029fa1d63a75cb06 CRs-Fixed: 2739176
This commit is contained in:
@@ -1840,8 +1840,7 @@ QDF_STATUS dp_rx_desc_nbuf_sanity_check(hal_ring_desc_t ring_desc,
|
|||||||
|
|
||||||
hal_rx_reo_buf_paddr_get(ring_desc, &hbi);
|
hal_rx_reo_buf_paddr_get(ring_desc, &hbi);
|
||||||
/* Sanity check for possible buffer paddr corruption */
|
/* Sanity check for possible buffer paddr corruption */
|
||||||
if ((&hbi)->paddr ==
|
if (dp_rx_desc_paddr_sanity_check(rx_desc, (&hbi)->paddr))
|
||||||
qdf_nbuf_get_frag_paddr(rx_desc->nbuf, 0))
|
|
||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
|
|
||||||
return QDF_STATUS_E_FAILURE;
|
return QDF_STATUS_E_FAILURE;
|
||||||
|
@@ -721,6 +721,20 @@ void dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list,
|
|||||||
struct dp_peer *peer);
|
struct dp_peer *peer);
|
||||||
|
|
||||||
#ifdef RX_DESC_DEBUG_CHECK
|
#ifdef RX_DESC_DEBUG_CHECK
|
||||||
|
/**
|
||||||
|
* dp_rx_desc_paddr_sanity_check() - paddr sanity for ring desc vs rx_desc
|
||||||
|
* @rx_desc: rx descriptor
|
||||||
|
* @ring_paddr: paddr obatined from the ring
|
||||||
|
*
|
||||||
|
* Returns: QDF_STATUS
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
bool dp_rx_desc_paddr_sanity_check(struct dp_rx_desc *rx_desc,
|
||||||
|
uint64_t ring_paddr)
|
||||||
|
{
|
||||||
|
return (ring_paddr == qdf_nbuf_get_frag_paddr(rx_desc->nbuf, 0));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dp_rx_desc_alloc_dbg_info() - Alloc memory for rx descriptor debug
|
* dp_rx_desc_alloc_dbg_info() - Alloc memory for rx descriptor debug
|
||||||
* structure
|
* structure
|
||||||
@@ -775,6 +789,13 @@ void dp_rx_desc_update_dbg_info(struct dp_rx_desc *rx_desc,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
static inline
|
||||||
|
bool dp_rx_desc_paddr_sanity_check(struct dp_rx_desc *rx_desc,
|
||||||
|
uint64_t ring_paddr)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void dp_rx_desc_alloc_dbg_info(struct dp_rx_desc *rx_desc)
|
void dp_rx_desc_alloc_dbg_info(struct dp_rx_desc *rx_desc)
|
||||||
{
|
{
|
||||||
|
@@ -1905,6 +1905,10 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, hal_ring_desc_t ring_desc,
|
|||||||
msdu = rx_desc->nbuf;
|
msdu = rx_desc->nbuf;
|
||||||
|
|
||||||
rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id];
|
rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id];
|
||||||
|
|
||||||
|
if (rx_desc->unmapped)
|
||||||
|
return rx_bufs_used;
|
||||||
|
|
||||||
dp_ipa_handle_rx_buf_smmu_mapping(soc, rx_desc->nbuf,
|
dp_ipa_handle_rx_buf_smmu_mapping(soc, rx_desc->nbuf,
|
||||||
rx_desc_pool->buf_size,
|
rx_desc_pool->buf_size,
|
||||||
false);
|
false);
|
||||||
|
@@ -1524,6 +1524,7 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
|
|||||||
uint16_t num_msdus;
|
uint16_t num_msdus;
|
||||||
struct dp_rx_desc *rx_desc = NULL;
|
struct dp_rx_desc *rx_desc = NULL;
|
||||||
QDF_STATUS status;
|
QDF_STATUS status;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
/* Debug -- Remove later */
|
/* Debug -- Remove later */
|
||||||
qdf_assert(soc && hal_ring_hdl);
|
qdf_assert(soc && hal_ring_hdl);
|
||||||
@@ -1630,6 +1631,32 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
|
|||||||
goto next_entry;
|
goto next_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this is a unlikely scenario where the host is reaping
|
||||||
|
* a descriptor which it already reaped just a while ago
|
||||||
|
* but is yet to replenish it back to HW.
|
||||||
|
* In this case host will dump the last 128 descriptors
|
||||||
|
* including the software descriptor rx_desc and assert.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (qdf_unlikely(!rx_desc->in_use)) {
|
||||||
|
DP_STATS_INC(soc, rx.err.hal_reo_dest_dup, 1);
|
||||||
|
dp_info_rl("Reaping rx_desc not in use!");
|
||||||
|
dp_rx_dump_info_and_assert(soc, hal_ring_hdl,
|
||||||
|
ring_desc, rx_desc);
|
||||||
|
/* ignore duplicate RX desc and continue */
|
||||||
|
/* Pop out the descriptor */
|
||||||
|
goto next_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dp_rx_desc_paddr_sanity_check(rx_desc,
|
||||||
|
msdu_list.paddr[0]);
|
||||||
|
if (!ret) {
|
||||||
|
DP_STATS_INC(soc, rx.err.nbuf_sanity_fail, 1);
|
||||||
|
rx_desc->in_err_state = 1;
|
||||||
|
goto next_entry;
|
||||||
|
}
|
||||||
|
|
||||||
count = dp_rx_frag_handle(soc,
|
count = dp_rx_frag_handle(soc,
|
||||||
ring_desc, &mpdu_desc_info,
|
ring_desc, &mpdu_desc_info,
|
||||||
rx_desc, &mac_id, quota);
|
rx_desc, &mac_id, quota);
|
||||||
|
Reference in New Issue
Block a user