From 0497d105b0a64fdafccbb0186d4da872104bf3ab Mon Sep 17 00:00:00 2001 From: Dustin Brown Date: Wed, 28 Nov 2018 15:07:37 -0800 Subject: [PATCH] qcacmn: Panic before unlock on missing unmap Currently, qdf_nbuf_map_check_for_leaks() logs the leak information under spinlock before inducing a panic. This can cause a confusing false positive panic upon releasing the spinlock if the logging took longer than the spinlock timeout threshold. Since we already know we are going to panic, panic under spinlock to ensure the panic message is always appropriate. Change-Id: Ib98b21e8feac0314b7c1f00f08b9e81112c4f2ba CRs-Fixed: 2357806 --- qdf/linux/src/qdf_nbuf.c | 44 +++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 993cb95669f3..ba305b24aa9b 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -601,40 +601,34 @@ static void qdf_nbuf_map_tracking_init(void) qdf_spinlock_create(&qdf_nbuf_map_lock); } -void qdf_nbuf_map_check_for_leaks(void) +static void qdf_nbuf_map_leaks_print(void) { struct qdf_nbuf_map_metadata *meta; int bucket; uint32_t count = 0; - bool is_empty; + QDF_BUG(qdf_spin_is_locked(&qdf_nbuf_map_lock)); + + qdf_nofl_alert("Nbuf map-no-unmap events detected!"); + qdf_nofl_alert("-----------------------------------------------------"); + + hash_for_each(qdf_nbuf_map_ht, bucket, meta, node) { + count++; + qdf_nofl_alert("0x%zx @ %s:%u", + (uintptr_t)meta->nbuf, meta->file, meta->line); + } + + QDF_DEBUG_PANIC("%u fatal nbuf map-no-unmap events detected!", count); +} + +void qdf_nbuf_map_check_for_leaks(void) +{ qdf_flex_mem_release(&qdf_nbuf_map_pool); qdf_spin_lock_irqsave(&qdf_nbuf_map_lock); - is_empty = hash_empty(qdf_nbuf_map_ht); + if (!hash_empty(qdf_nbuf_map_ht)) + qdf_nbuf_map_leaks_print(); qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock); - - if (is_empty) - return; - - qdf_err("Nbuf map without unmap events detected!"); - qdf_err("------------------------------------------------------------"); - - /* Hold the lock for the entire iteration for safe list/meta access. We - * are explicitly preferring the chance to watchdog on the print, over - * the posibility of invalid list/memory access. Since we are going to - * panic anyway, the worst case is loading up the crash dump to find out - * what was in the hash table. - */ - qdf_spin_lock_irqsave(&qdf_nbuf_map_lock); - hash_for_each(qdf_nbuf_map_ht, bucket, meta, node) { - count++; - qdf_err("0x%pk @ %s:%u", - meta->nbuf, meta->file, meta->line); - } - qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock); - - panic("%u fatal nbuf map without unmap events detected!", count); } static void qdf_nbuf_map_tracking_deinit(void)