diff options
| author | Poddar, Siddarth <siddpodd@codeaurora.org> | 2017-01-12 18:50:43 +0530 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2017-01-12 20:28:54 -0800 |
| commit | 4106a5ad7568d3d2df5f7d37a25a8a99a9921eb8 (patch) | |
| tree | c6340a225a23c86d656c4366d6b5c33b626c2e36 | |
| parent | 937fa5f6e453e4af8171bf61407368c35a41b742 (diff) | |
qcacld-3.0: Add cookie to tso seg structure to debug double mem free
Add a field in qdf_tso_seg_t. This cookie helps to check
double memory free or memory corruption case.
When double mem free hits, it will result into QDF_BUG.
Change-Id: I3c60f2603bce23b47224ae9a5d88881c2fbb8e01
CRs-Fixed: 1102423
| -rw-r--r-- | core/dp/txrx/ol_tx.c | 17 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx_desc.c | 33 |
2 files changed, 46 insertions, 4 deletions
diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index c0c5806c65bb..159846b98506 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1934,7 +1934,9 @@ void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg) qdf_spinlock_create(&pdev->tso_seg_pool.tso_mutex); return; } - + /* set the freelist bit and magic cookie*/ + c_element->on_freelist = 1; + c_element->cookie = TSO_SEG_MAGIC_COOKIE; c_element->next = qdf_mem_malloc(sizeof(struct qdf_tso_seg_elem_t)); c_element = c_element->next; @@ -1963,6 +1965,17 @@ void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev) while (i-- > 0 && c_element) { temp = c_element->next; + if (c_element->on_freelist != 1) { + qdf_print("this seg memory is already freed (double free?)"); + QDF_BUG(0); + return; + } else if (c_element->cookie != TSO_SEG_MAGIC_COOKIE) { + qdf_print("this seg cookie is bad (memory corruption?)"); + QDF_BUG(0); + return; + } + /* free this seg, so reset the cookie value*/ + c_element->cookie = 0; qdf_mem_free(c_element); c_element = temp; } diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c index 11490c035e08..b354be2eac7a 100644 --- a/core/dp/txrx/ol_tx_desc.c +++ b/core/dp/txrx/ol_tx_desc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -321,6 +321,7 @@ void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) qdf_assert(0); } else { ol_tso_free_segment(pdev, tx_desc->tso_desc); + tx_desc->tso_desc = NULL; } } ol_tx_desc_dup_detect_reset(pdev, tx_desc); @@ -350,8 +351,10 @@ void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc) if (qdf_unlikely(tx_desc->tso_desc == NULL)) qdf_print("%s %d TSO desc is NULL!\n", __func__, __LINE__); - else + else { ol_tso_free_segment(pdev, tx_desc->tso_desc); + tx_desc->tso_desc = NULL; + } } #endif ol_tx_desc_reset_pkt_type(tx_desc); @@ -728,6 +731,19 @@ struct qdf_tso_seg_elem_t *ol_tso_alloc_segment(struct ol_txrx_pdev_t *pdev) if (pdev->tso_seg_pool.freelist) { pdev->tso_seg_pool.num_free--; tso_seg = pdev->tso_seg_pool.freelist; + if (tso_seg->on_freelist != 1) { + qdf_print("Do not alloc tso seg as this seg is not in freelist\n"); + qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); + QDF_BUG(0); + return NULL; + } else if (tso_seg->cookie != TSO_SEG_MAGIC_COOKIE) { + qdf_print("Do not alloc tso seg as cookie is not good\n"); + qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); + QDF_BUG(0); + return NULL; + } + /*this tso seg is not a part of freelist now.*/ + tso_seg->on_freelist = 0; pdev->tso_seg_pool.freelist = pdev->tso_seg_pool.freelist->next; } qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); @@ -751,7 +767,20 @@ void ol_tso_free_segment(struct ol_txrx_pdev_t *pdev, struct qdf_tso_seg_elem_t *tso_seg) { qdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex); + if (tso_seg->on_freelist != 0) { + qdf_print("Do not free the tso seg as this seg is already freed"); + qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); + QDF_BUG(0); + return; + } else if (tso_seg->cookie != TSO_SEG_MAGIC_COOKIE) { + qdf_print("Do not free the tso seg as cookie is not good. Looks like memory corruption"); + qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); + QDF_BUG(0); + return; + } + /*this tso seg is now a part of freelist*/ tso_seg->next = pdev->tso_seg_pool.freelist; + tso_seg->on_freelist = 1; pdev->tso_seg_pool.freelist = tso_seg; pdev->tso_seg_pool.num_free++; qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex); |
