summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBian Guolei <gbian@codeaurora.org>2016-11-09 20:10:48 +0800
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-11-11 20:00:36 +0530
commitf6af4e0a516750fdae81ae5a9a02b36d482fd3fd (patch)
tree9aeae21e470e11fadbd6a6bb41b2b25e77ad0c29
parent029e8259c0ae4ba116deb2b05a5771a7e4de6146 (diff)
qcacld-2.0: Reset tx desc type after calling msdu complete conditionally
After calling ol_tx_msdu_complete, it will reset the tx desc's pakcet type to ol_tx_frm_freed state. So there might be a race condition if there is another thread try to allocate this tx description between these two operations. The ol_tx_msdu_complete doesn't always free the tx_desc according to the tx desc type. So need to reset the tx desc's packet type only when the ol_tx_msdu_complete hasn't freed it. Change-Id: I0d96ef60d10048c524e93209469e8cdf20ce22c6 CRs-Fixed: 1087688
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_tx_send.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/CORE/CLD_TXRX/TXRX/ol_tx_send.c b/CORE/CLD_TXRX/TXRX/ol_tx_send.c
index 4a5f196e56ea..041ac9d6f90b 100644
--- a/CORE/CLD_TXRX/TXRX/ol_tx_send.c
+++ b/CORE/CLD_TXRX/TXRX/ol_tx_send.c
@@ -453,17 +453,22 @@ ol_tx_delay_compute(
#ifdef QCA_TX_SINGLE_COMPLETIONS
#ifdef QCA_TX_STD_PATH_ONLY
#define ol_tx_msdu_complete(_pdev, _tx_desc, _tx_descs, _netbuf, _lcl_freelist, \
- _tx_desc_last, _status) \
+ _tx_desc_last, _status, is_tx_desc_freed) \
+ do { \
+ is_tx_desc_freed = 0; \
ol_tx_msdu_complete_single((_pdev), (_tx_desc), (_netbuf), (_lcl_freelist), \
- _tx_desc_last)
+ _tx_desc_last); \
+ } while (0)
#else /* !QCA_TX_STD_PATH_ONLY */
#define ol_tx_msdu_complete(_pdev, _tx_desc, _tx_descs, _netbuf, _lcl_freelist, \
- _tx_desc_last, _status) \
+ _tx_desc_last, _status, is_tx_desc_freed) \
do { \
if (adf_os_likely((_tx_desc)->pkt_type == ol_tx_frm_std)) { \
+ is_tx_desc_freed = 0; \
ol_tx_msdu_complete_single((_pdev), (_tx_desc), (_netbuf), (_lcl_freelist), \
(_tx_desc_last)); \
} else { \
+ is_tx_desc_freed = 1; \
ol_tx_desc_frame_free_nonstd( \
(_pdev), (_tx_desc), (_status) != htt_tx_status_ok); \
} \
@@ -472,15 +477,20 @@ ol_tx_delay_compute(
#else /* !QCA_TX_SINGLE_COMPLETIONS */
#ifdef QCA_TX_STD_PATH_ONLY
#define ol_tx_msdu_complete(_pdev, _tx_desc, _tx_descs, _netbuf, _lcl_freelist, \
- _tx_desc_last, _status) \
- ol_tx_msdus_complete_batch((_pdev), (_tx_desc), (_tx_descs), (_status))
+ _tx_desc_last, _status, is_tx_desc_freed) \
+ do { \
+ is_tx_desc_freed = 0; \
+ ol_tx_msdu_complete_batch((_pdev), (_tx_desc), (_tx_descs), (_status)); \
+ } while (0)
#else /* !QCA_TX_STD_PATH_ONLY */
#define ol_tx_msdu_complete(_pdev, _tx_desc, _tx_descs, _netbuf, _lcl_freelist, \
- _tx_desc_last, _status) \
+ _tx_desc_last, _status, is_tx_desc_freed) \
do { \
if (adf_os_likely((_tx_desc)->pkt_type == ol_tx_frm_std)) { \
+ is_tx_desc_freed = 0; \
ol_tx_msdu_complete_batch((_pdev), (_tx_desc), (_tx_descs), (_status)); \
} else { \
+ is_tx_desc_freed = 1; \
ol_tx_desc_frame_free_nonstd( \
(_pdev), (_tx_desc), (_status) != htt_tx_status_ok); \
} \
@@ -546,6 +556,8 @@ ol_tx_completion_handler(
union ol_tx_desc_list_elem_t *lcl_freelist = NULL;
union ol_tx_desc_list_elem_t *tx_desc_last = NULL;
ol_tx_desc_list tx_descs;
+ uint32_t is_tx_desc_freed = 0;
+
TAILQ_INIT(&tx_descs);
OL_TX_DELAY_COMPUTE(pdev, status, desc_ids, num_msdus);
@@ -580,14 +592,17 @@ ol_tx_completion_handler(
status != htt_tx_status_ok);
ol_tx_msdu_complete(
pdev, tx_desc, tx_descs, netbuf,
- lcl_freelist, tx_desc_last, status);
- }
+ lcl_freelist, tx_desc_last, status, is_tx_desc_freed);
+
#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS
- tx_desc->pkt_type = ol_tx_frm_freed;
+ if (!is_tx_desc_freed) {
+ tx_desc->pkt_type = ol_tx_frm_freed;
#ifdef QCA_COMPUTE_TX_DELAY
- tx_desc->entry_timestamp_ticks = 0xffffffff;
+ tx_desc->entry_timestamp_ticks = 0xffffffff;
#endif
+ }
#endif
+ }
}
/* One shot protected access to pdev freelist, when setup */
@@ -815,6 +830,8 @@ ol_tx_inspect_handler(
union ol_tx_desc_list_elem_t *tx_desc_last = NULL;
adf_nbuf_t netbuf;
ol_tx_desc_list tx_descs;
+ uint32_t is_tx_desc_freed = 0;
+
TAILQ_INIT(&tx_descs);
for (i = 0; i < num_msdus; i++) {
@@ -840,13 +857,16 @@ ol_tx_inspect_handler(
* for graceful freeing of this multicast frame
*/
ol_tx_msdu_complete(pdev, tx_desc, tx_descs, netbuf, lcl_freelist,
- tx_desc_last, htt_tx_status_ok);
+ tx_desc_last, htt_tx_status_ok,
+ is_tx_desc_freed);
#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS
- tx_desc->pkt_type = ol_tx_frm_freed;
+ if (!is_tx_desc_freed) {
+ tx_desc->pkt_type = ol_tx_frm_freed;
#ifdef QCA_COMPUTE_TX_DELAY
- tx_desc->entry_timestamp_ticks = 0xffffffff;
+ tx_desc->entry_timestamp_ticks = 0xffffffff;
#endif
+ }
#endif
}
}