qcacmn: Fix memory leaks in Rx monitor path
Fix the following 2 memory leaks in Rx monitor path: 1. When MPDU queue is empty and MON_BUF_ADDR_TLV is received, then free page fragment memory. 2. In case of small size packets, 1 MPDU can have more than 2*QDF_NBUF_MAX_FRAGS fragments wherein each nbuf can have maximum of QDF_NBUF_MAX_FRAGS frags. In this case, add the frags to nbuf in the following way. parent_nbuf (QDF_NBUF_MAX_FRAGS frags attached) | | (fraglist) | ----> tmp_nbuf1 (QDF_NBUF_MAX_FRAGS frags attached) ----> tmp_nbuf2 (next) Change-Id: I54e8162bf0b9da8629a3c80d123421fbeaf8df11 CRs-Fixed: 3453676
This commit is contained in:

committed by
Madan Koyyalamudi

parent
58b1c384df
commit
2be2bf6a69
@@ -1372,6 +1372,31 @@ dp_rx_mon_handle_flush_n_trucated_ppdu(struct dp_soc *soc,
|
||||
rx_mon_desc_pool);
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_rx_mon_append_nbuf() - Append nbuf to parent nbuf
|
||||
* @nbuf: Parent nbuf
|
||||
* @tmp_nbuf: nbuf to be attached to parent
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void dp_rx_mon_append_nbuf(qdf_nbuf_t nbuf, qdf_nbuf_t tmp_nbuf)
|
||||
{
|
||||
qdf_nbuf_t last_nbuf;
|
||||
|
||||
/*
|
||||
* If nbuf does not have fraglist, then append tmp_nbuf as fraglist,
|
||||
* else append tmp_nbuf as next of last_nbuf present in nbuf fraglist.
|
||||
*/
|
||||
if (!qdf_nbuf_has_fraglist(nbuf))
|
||||
qdf_nbuf_append_ext_list(nbuf, tmp_nbuf,
|
||||
qdf_nbuf_len(tmp_nbuf));
|
||||
else {
|
||||
last_nbuf = qdf_nbuf_get_last_frag_list_nbuf(nbuf);
|
||||
|
||||
if (qdf_likely(last_nbuf))
|
||||
qdf_nbuf_set_next(last_nbuf, tmp_nbuf);
|
||||
}
|
||||
}
|
||||
uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
|
||||
struct hal_rx_ppdu_info *ppdu_info,
|
||||
void *status_frag,
|
||||
@@ -1468,9 +1493,7 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
|
||||
qdf_assert_always(0);
|
||||
}
|
||||
mon_pdev->rx_mon_stats.parent_buf_alloc++;
|
||||
/* add new skb to frag list */
|
||||
qdf_nbuf_append_ext_list(nbuf, tmp_nbuf,
|
||||
qdf_nbuf_len(tmp_nbuf));
|
||||
dp_rx_mon_append_nbuf(nbuf, tmp_nbuf);
|
||||
}
|
||||
dp_rx_mon_nbuf_add_rx_frag(tmp_nbuf, status_frag,
|
||||
ppdu_info->hdr_len - DP_RX_MON_RX_HDR_OFFSET,
|
||||
@@ -1522,6 +1545,9 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
|
||||
nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
|
||||
if (qdf_unlikely(!nbuf)) {
|
||||
dp_mon_debug("nbuf is NULL");
|
||||
DP_STATS_INC(mon_soc, frag_free, 1);
|
||||
DP_STATS_INC(mon_soc, empty_queue, 1);
|
||||
qdf_frag_free(addr);
|
||||
return num_buf_reaped;
|
||||
}
|
||||
|
||||
@@ -1559,9 +1585,7 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
|
||||
return num_buf_reaped;
|
||||
}
|
||||
mon_pdev->rx_mon_stats.parent_buf_alloc++;
|
||||
/* add new skb to frag list */
|
||||
qdf_nbuf_append_ext_list(nbuf, tmp_nbuf,
|
||||
qdf_nbuf_len(tmp_nbuf));
|
||||
dp_rx_mon_append_nbuf(nbuf, tmp_nbuf);
|
||||
}
|
||||
mpdu_info->full_pkt = true;
|
||||
|
||||
@@ -2153,7 +2177,7 @@ dp_rx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
|
||||
status = dp_rx_mon_add_ppdu_info_to_wq(pdev, ppdu_info);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
if (ppdu_info)
|
||||
__dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info);
|
||||
dp_rx_mon_free_ppdu_info(pdev, ppdu_info);
|
||||
}
|
||||
|
||||
work_done++;
|
||||
@@ -2399,8 +2423,10 @@ void dp_mon_rx_print_advanced_stats_2_0(struct dp_soc *soc,
|
||||
rx_mon_stats->mpdus_buf_to_stack);
|
||||
DP_PRINT_STATS("frag_alloc = %d",
|
||||
mon_soc->stats.frag_alloc);
|
||||
DP_PRINT_STATS("frag_free = %d",
|
||||
DP_PRINT_STATS("total frag_free = %d",
|
||||
mon_soc->stats.frag_free);
|
||||
DP_PRINT_STATS("frag_free due to empty queue= %d",
|
||||
mon_soc->stats.empty_queue);
|
||||
DP_PRINT_STATS("status_buf_count = %d",
|
||||
rx_mon_stats->status_buf_count);
|
||||
DP_PRINT_STATS("pkt_buf_count = %d",
|
||||
|
@@ -845,10 +845,12 @@ struct dp_mon_ops {
|
||||
* struct dp_mon_soc_stats - monitor stats
|
||||
* @frag_alloc: Number of frags allocated
|
||||
* @frag_free: Number of frags freed
|
||||
* @empty_queue: Number of frags freed due to empty queue
|
||||
*/
|
||||
struct dp_mon_soc_stats {
|
||||
uint32_t frag_alloc;
|
||||
uint32_t frag_free;
|
||||
uint32_t empty_queue;
|
||||
};
|
||||
|
||||
struct dp_mon_soc {
|
||||
|
@@ -4890,6 +4890,31 @@ qdf_nbuf_get_priv_ptr(qdf_nbuf_t buf)
|
||||
return __qdf_nbuf_get_priv_ptr(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* qdf_nbuf_has_fraglist() - check if nbuf has attached frag list
|
||||
* @nbuf: Pointer to nbuf
|
||||
*
|
||||
* Return: bool
|
||||
*/
|
||||
static inline bool
|
||||
qdf_nbuf_has_fraglist(qdf_nbuf_t nbuf)
|
||||
{
|
||||
return __qdf_nbuf_has_fraglist(nbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* qdf_nbuf_get_last_frag_list_nbuf() - Fetch pointer to last nbuf in frag list
|
||||
* @nbuf: Pointer to nbuf
|
||||
*
|
||||
* Return: Pointer to last nbuf in frag list if parent nbuf has extended frag
|
||||
* list or else return NULL
|
||||
*/
|
||||
static inline qdf_nbuf_t
|
||||
qdf_nbuf_get_last_frag_list_nbuf(qdf_nbuf_t nbuf)
|
||||
{
|
||||
return __qdf_nbuf_get_last_frag_list_nbuf(nbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* qdf_nbuf_update_radiotap() - update radiotap at head of nbuf.
|
||||
* @rx_status: rx_status containing required info to update radiotap
|
||||
|
Reference in New Issue
Block a user