diff options
| author | Himanshu Agarwal <himanaga@codeaurora.org> | 2017-03-24 17:28:40 +0530 |
|---|---|---|
| committer | Himanshu Agarwal <himanaga@codeaurora.org> | 2017-04-11 12:11:22 +0530 |
| commit | 2fb1de7283c0e8753601d77100a86e65f31b3608 (patch) | |
| tree | bfaf605a00d0204cb0d0109604d01284724d3356 | |
| parent | 5574bd0379303340bf57850e8d5c58b76afa48d5 (diff) | |
qcacld-3.0: Fix memory leaks of TSO segments and corresponding nbufs
Fix memory leaks of TSO segments and corresponding nbufs by:
1) Freeing TSO segments if qdf_nbuf_get_tso_info returns failure.
2) Freeing remaining TSO segments in ol_tx_ll_fast and ol_tx_ll if
somehow allocated tx desc. is NULL.
Change-Id: I69d5b3fedde6e78ca49ef26ed8c0654a08a4b6db
CRs-Fixed: 2023657
| -rw-r--r-- | core/dp/txrx/ol_tx.c | 53 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx_desc.h | 3 |
2 files changed, 42 insertions, 14 deletions
diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index 85c608a54fcc..49ec3aa3528e 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -76,6 +76,13 @@ int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t msdu, (msdu_info)->htt.info.frame_type = pdev->htt_pkt_type; \ tx_desc = ol_tx_desc_ll(pdev, vdev, msdu, msdu_info); \ if (qdf_unlikely(!tx_desc)) { \ + /* \ + * If TSO packet, free associated \ + * remaining TSO segment descriptors \ + */ \ + if (qdf_nbuf_is_tso(msdu)) \ + ol_free_remaining_tso_segs( \ + vdev, msdu_info); \ TXRX_STATS_MSDU_LIST_INCR( \ pdev, tx.dropped.host_reject, msdu); \ return msdu; /* the list of unaccepted MSDUs */ \ @@ -83,7 +90,7 @@ int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t msdu, } while (0) #if defined(FEATURE_TSO) -static void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev, +void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev, struct ol_txrx_msdu_info_t *msdu_info) { struct qdf_tso_seg_elem_t *next_seg; @@ -144,8 +151,16 @@ static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev, ol_free_remaining_tso_segs(vdev, msdu_info); return 1; } - qdf_nbuf_get_tso_info(vdev->pdev->osdev, - msdu, &(msdu_info->tso_info)); + + if (qdf_unlikely(!qdf_nbuf_get_tso_info(vdev->pdev->osdev, + msdu, &(msdu_info->tso_info)))) { + /* Free the already allocated num of segments */ + msdu_info->tso_info.curr_seg = + msdu_info->tso_info.tso_seg_list; + ol_free_remaining_tso_segs(vdev, msdu_info); + return 1; + } + msdu_info->tso_info.curr_seg = msdu_info->tso_info.tso_seg_list; num_seg = msdu_info->tso_info.num_segs; @@ -345,6 +360,8 @@ qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) segments--; + ol_tx_prepare_ll(tx_desc, vdev, msdu, &msdu_info); + /** * if this is a jumbo nbuf, then increment the number * of nbuf users for each additional segment of the msdu. @@ -354,8 +371,6 @@ qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) if (segments) qdf_nbuf_inc_users(msdu); - ol_tx_prepare_ll(tx_desc, vdev, msdu, &msdu_info); - TXRX_STATS_MSDU_INCR(vdev->pdev, tx.from_stack, msdu); /* @@ -649,15 +664,6 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) segments--; - /** - * if this is a jumbo nbuf, then increment the number - * of nbuf users for each additional segment of the msdu. - * This will ensure that the skb is freed only after - * receiving tx completion for all segments of an nbuf - */ - if (segments) - qdf_nbuf_inc_users(msdu); - msdu_info.htt.info.frame_type = pdev->htt_pkt_type; msdu_info.htt.info.vdev_id = vdev->vdev_id; msdu_info.htt.action.cksum_offload = @@ -685,6 +691,17 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) TXRX_STATS_MSDU_INCR(pdev, tx.from_stack, msdu); if (qdf_likely(tx_desc)) { + + /* + * if this is a jumbo nbuf, then increment the + * number of nbuf users for each additional + * segment of the msdu. This will ensure that + * the skb is freed only after receiving tx + * completion for all segments of an nbuf. + */ + if (segments) + qdf_nbuf_inc_users(msdu); + DPTRACE(qdf_dp_trace_ptr(msdu, QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD, qdf_nbuf_data_addr(msdu), @@ -740,6 +757,14 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list) tso_msdu_stats_idx); } } else { + /* + * If TSO packet, free associated + * remaining TSO segment descriptors + */ + if (qdf_nbuf_is_tso(msdu)) + ol_free_remaining_tso_segs(vdev, + &msdu_info); + TXRX_STATS_MSDU_LIST_INCR( pdev, tx.dropped.host_reject, msdu); /* the list of unaccepted MSDUs */ diff --git a/core/dp/txrx/ol_tx_desc.h b/core/dp/txrx/ol_tx_desc.h index 37379effc2e1..f74de0216d0e 100644 --- a/core/dp/txrx/ol_tx_desc.h +++ b/core/dp/txrx/ol_tx_desc.h @@ -232,12 +232,15 @@ struct qdf_tso_num_seg_elem_t *ol_tso_num_seg_alloc( struct ol_txrx_pdev_t *pdev); void ol_tso_num_seg_free(struct ol_txrx_pdev_t *pdev, struct qdf_tso_num_seg_elem_t *tso_num_seg); +void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev, + struct ol_txrx_msdu_info_t *msdu_info); #else #define ol_tso_alloc_segment(pdev) /*no-op*/ #define ol_tso_free_segment(pdev, tso_seg) /*no-op*/ #define ol_tso_num_seg_alloc(pdev) /*no-op*/ #define ol_tso_num_seg_free(pdev, tso_num_seg) /*no-op*/ +#define ol_free_remaining_tso_segs(vdev, msdu_info) /*no-op*/ #endif |
