qcacld-3.0: Avoid double free of tx_desc in ol_tx_download_done_hl_free

If tx_desc is freed as part of ol_tx_download_done_base
then do not free again in ol_tx_download_done_hl_free.

Change-Id: I006603f0fad40c0cfce59b8c14b521705cec7ebc
CRs-Fixed: 2544447
Esse commit está contido em:
Nirav Shah
2019-10-16 11:46:29 +05:30
commit de nshrivas
commit fc0848cb38

Ver arquivo

@@ -259,11 +259,12 @@ ol_tx_send_nonstd(struct ol_txrx_pdev_t *pdev,
} }
} }
static inline void static inline bool
ol_tx_download_done_base(struct ol_txrx_pdev_t *pdev, ol_tx_download_done_base(struct ol_txrx_pdev_t *pdev,
A_STATUS status, qdf_nbuf_t msdu, uint16_t msdu_id) A_STATUS status, qdf_nbuf_t msdu, uint16_t msdu_id)
{ {
struct ol_tx_desc_t *tx_desc; struct ol_tx_desc_t *tx_desc;
bool is_frame_freed = false;
tx_desc = ol_tx_desc_find(pdev, msdu_id); tx_desc = ol_tx_desc_find(pdev, msdu_id);
qdf_assert(tx_desc); qdf_assert(tx_desc);
@@ -286,6 +287,7 @@ ol_tx_download_done_base(struct ol_txrx_pdev_t *pdev,
ol_tx_target_credit_incr(pdev, msdu); ol_tx_target_credit_incr(pdev, msdu);
ol_tx_desc_frame_free_nonstd(pdev, tx_desc, ol_tx_desc_frame_free_nonstd(pdev, tx_desc,
1 /* download err */); 1 /* download err */);
is_frame_freed = true;
} else { } else {
if (OL_TX_DESC_NO_REFS(tx_desc)) { if (OL_TX_DESC_NO_REFS(tx_desc)) {
/* /*
@@ -296,8 +298,10 @@ ol_tx_download_done_base(struct ol_txrx_pdev_t *pdev,
ol_tx_desc_frame_free_nonstd(pdev, tx_desc, ol_tx_desc_frame_free_nonstd(pdev, tx_desc,
tx_desc->status != tx_desc->status !=
htt_tx_status_ok); htt_tx_status_ok);
is_frame_freed = true;
} }
} }
return is_frame_freed;
} }
void void
@@ -324,6 +328,7 @@ ol_tx_download_done_hl_free(void *txrx_pdev,
{ {
struct ol_txrx_pdev_t *pdev = txrx_pdev; struct ol_txrx_pdev_t *pdev = txrx_pdev;
struct ol_tx_desc_t *tx_desc; struct ol_tx_desc_t *tx_desc;
bool is_frame_freed;
tx_desc = ol_tx_desc_find(pdev, msdu_id); tx_desc = ol_tx_desc_find(pdev, msdu_id);
qdf_assert(tx_desc); qdf_assert(tx_desc);
@@ -335,13 +340,12 @@ ol_tx_download_done_hl_free(void *txrx_pdev,
sizeof(qdf_nbuf_data(msdu)), tx_desc->id, sizeof(qdf_nbuf_data(msdu)), tx_desc->id,
status)); status));
ol_tx_download_done_base(pdev, status, msdu, msdu_id); is_frame_freed = ol_tx_download_done_base(pdev, status, msdu, msdu_id);
/* /*
* Incase of error return from here since netbuf and tx_desc would * if frame is freed in ol_tx_download_done_base then return.
* have been freed in ol_tx_download_done_base().
*/ */
if (status != A_OK) { if (is_frame_freed) {
qdf_atomic_add(1, &pdev->tx_queue.rsrc_cnt); qdf_atomic_add(1, &pdev->tx_queue.rsrc_cnt);
return; return;
} }