summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimanshu Agarwal <himanaga@codeaurora.org>2017-03-24 17:28:40 +0530
committerHimanshu Agarwal <himanaga@codeaurora.org>2017-04-11 12:11:22 +0530
commit2fb1de7283c0e8753601d77100a86e65f31b3608 (patch)
treebfaf605a00d0204cb0d0109604d01284724d3356
parent5574bd0379303340bf57850e8d5c58b76afa48d5 (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.c53
-rw-r--r--core/dp/txrx/ol_tx_desc.h3
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