summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPoddar, Siddarth <siddpodd@codeaurora.org>2017-01-12 18:50:43 +0530
committerqcabuildsw <qcabuildsw@localhost>2017-01-12 20:28:54 -0800
commit4106a5ad7568d3d2df5f7d37a25a8a99a9921eb8 (patch)
treec6340a225a23c86d656c4366d6b5c33b626c2e36
parent937fa5f6e453e4af8171bf61407368c35a41b742 (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.c17
-rw-r--r--core/dp/txrx/ol_tx_desc.c33
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);