mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-11-07 19:23:01 -05:00
qcacld-3.0: Fix memory leaks of TSO num segments
Fix memory leaks of TSO num segments by freeing remaining TSO num segments in ol_tx_ll_fast and ol_tx_ll if somehow allocated tx desc is NULL. Change-Id: I577a95b784c776633cf685cd16b101755a48c521 CRs-Fixed: 2014587
This commit is contained in:
parent
33faae85d7
commit
39ba8e0481
2 changed files with 76 additions and 14 deletions
|
|
@ -82,7 +82,7 @@ int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t msdu,
|
|||
*/ \
|
||||
if (qdf_nbuf_is_tso(msdu)) \
|
||||
ol_free_remaining_tso_segs( \
|
||||
vdev, msdu_info); \
|
||||
vdev, msdu_info, true); \
|
||||
TXRX_STATS_MSDU_LIST_INCR( \
|
||||
pdev, tx.dropped.host_reject, msdu); \
|
||||
return msdu; /* the list of unaccepted MSDUs */ \
|
||||
|
|
@ -91,17 +91,77 @@ int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t msdu,
|
|||
|
||||
#if defined(FEATURE_TSO)
|
||||
void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev,
|
||||
struct ol_txrx_msdu_info_t *msdu_info)
|
||||
struct ol_txrx_msdu_info_t *msdu_info,
|
||||
bool is_tso_seg_mapping_done)
|
||||
{
|
||||
struct qdf_tso_seg_elem_t *next_seg;
|
||||
struct qdf_tso_seg_elem_t *free_seg = msdu_info->tso_info.curr_seg;
|
||||
struct ol_txrx_pdev_t *pdev;
|
||||
bool is_last_seg = false;
|
||||
|
||||
while (free_seg) {
|
||||
next_seg = free_seg->next;
|
||||
ol_tso_free_segment(vdev->pdev, free_seg);
|
||||
free_seg = next_seg;
|
||||
if (qdf_unlikely(!vdev)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s:vdev is null", __func__);
|
||||
return;
|
||||
} else {
|
||||
pdev = vdev->pdev;
|
||||
if (qdf_unlikely(!pdev)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s:pdev is null", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_tso_seg_mapping_done) {
|
||||
/*
|
||||
* TSO segment are mapped already, therefore,
|
||||
* 1. unmap the tso segments,
|
||||
* 2. free tso num segment if it is a last segment, and
|
||||
* 3. free the tso segments.
|
||||
*/
|
||||
struct qdf_tso_num_seg_elem_t *tso_num_desc =
|
||||
msdu_info->tso_info.tso_num_seg_list;
|
||||
|
||||
if (qdf_unlikely(tso_num_desc == NULL)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s %d TSO common info is NULL!",
|
||||
__func__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
while (free_seg) {
|
||||
qdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex);
|
||||
tso_num_desc->num_seg.tso_cmn_num_seg--;
|
||||
|
||||
is_last_seg = (tso_num_desc->num_seg.tso_cmn_num_seg ==
|
||||
0) ? true : false;
|
||||
qdf_nbuf_unmap_tso_segment(pdev->osdev, free_seg,
|
||||
is_last_seg);
|
||||
qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
|
||||
|
||||
if (is_last_seg) {
|
||||
ol_tso_num_seg_free(pdev,
|
||||
msdu_info->tso_info.tso_num_seg_list);
|
||||
msdu_info->tso_info.tso_num_seg_list = NULL;
|
||||
}
|
||||
|
||||
next_seg = free_seg->next;
|
||||
ol_tso_free_segment(pdev, free_seg);
|
||||
free_seg = next_seg;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* TSO segment are not mapped therefore,
|
||||
* free the tso segments only.
|
||||
*/
|
||||
while (free_seg) {
|
||||
next_seg = free_seg->next;
|
||||
ol_tso_free_segment(pdev, free_seg);
|
||||
free_seg = next_seg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ol_tx_prepare_tso() - Given a jumbo msdu, prepare the TSO
|
||||
* related information in the msdu_info meta data
|
||||
|
|
@ -135,7 +195,8 @@ static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev,
|
|||
/* Free above alocated TSO segements till now */
|
||||
msdu_info->tso_info.curr_seg =
|
||||
msdu_info->tso_info.tso_seg_list;
|
||||
ol_free_remaining_tso_segs(vdev, msdu_info);
|
||||
ol_free_remaining_tso_segs(vdev, msdu_info,
|
||||
false);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -148,7 +209,7 @@ static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev,
|
|||
/* 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);
|
||||
ol_free_remaining_tso_segs(vdev, msdu_info, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +218,7 @@ static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev,
|
|||
/* 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);
|
||||
ol_free_remaining_tso_segs(vdev, msdu_info, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -725,7 +786,7 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
|
|||
tso_info->curr_seg =
|
||||
tso_info->curr_seg->next;
|
||||
ol_free_remaining_tso_segs(vdev,
|
||||
&msdu_info);
|
||||
&msdu_info, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -757,7 +818,7 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
|
|||
*/
|
||||
if (qdf_nbuf_is_tso(msdu))
|
||||
ol_free_remaining_tso_segs(vdev,
|
||||
&msdu_info);
|
||||
&msdu_info, true);
|
||||
|
||||
TXRX_STATS_MSDU_LIST_INCR(
|
||||
pdev, tx.dropped.host_reject, msdu);
|
||||
|
|
|
|||
|
|
@ -233,15 +233,16 @@ struct qdf_tso_num_seg_elem_t *ol_tso_num_seg_alloc(
|
|||
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);
|
||||
struct ol_txrx_msdu_info_t *msdu_info,
|
||||
bool is_tso_seg_mapping_done);
|
||||
|
||||
#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*/
|
||||
|
||||
/*no-op*/
|
||||
#define ol_free_remaining_tso_segs(vdev, msdu_info, is_tso_seg_mapping_done)
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue