From ad8457136c5af02857518a5b9af20dc0a88fc66d Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Tue, 12 Mar 2019 15:40:39 -0700 Subject: [PATCH] qcacmn: Use qdf_tracker for nbuf mapping qdf_tracker generically implements all of the logic necessary to implement the qdf_nbuf map tracking. Rather than using the current custom tracking solution for qdf_nbuf map tracking, use qdf_tracker instead. Change-Id: Id33138a9035653b45c66b712bd11e54873266a17 CRs-Fixed: 2425623 --- qdf/linux/src/qdf_nbuf.c | 161 +++++++++------------------------------ qdf/src/qdf_tracker.c | 2 +- 2 files changed, 35 insertions(+), 128 deletions(-) diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 27323906a79a..97a026e9d60a 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -28,20 +28,18 @@ #include #include #include -#include -#include -#include "qdf_flex_mem.h" -#include -#include -#include -#include #include -#include -#include -#include -#include +#include +#include #include +#include +#include #include "qdf_str.h" +#include +#include "qdf_tracker.h" +#include +#include +#include #if defined(FEATURE_TSO) #include @@ -583,105 +581,28 @@ qdf_nbuf_history_add(qdf_nbuf_t nbuf, const char *func, uint32_t line, #endif /* NBUF_MEMORY_DEBUG */ #ifdef NBUF_MAP_UNMAP_DEBUG -struct qdf_nbuf_map_metadata { - struct hlist_node node; - qdf_nbuf_t nbuf; - char func[QDF_MEM_FUNC_NAME_SIZE]; - uint32_t line; -}; - -DEFINE_QDF_FLEX_MEM_POOL(qdf_nbuf_map_pool, - sizeof(struct qdf_nbuf_map_metadata), 0); -#define QDF_NBUF_MAP_HT_BITS 10 /* 1024 buckets */ -static DECLARE_HASHTABLE(qdf_nbuf_map_ht, QDF_NBUF_MAP_HT_BITS); -static qdf_spinlock_t qdf_nbuf_map_lock; +#define qdf_nbuf_map_tracker_bits 11 /* 2048 buckets */ +qdf_tracker_declare(qdf_nbuf_map_tracker, qdf_nbuf_map_tracker_bits, + "nbuf map-no-unmap events", "nbuf map", "nbuf unmap"); static void qdf_nbuf_map_tracking_init(void) { - qdf_flex_mem_init(&qdf_nbuf_map_pool); - hash_init(qdf_nbuf_map_ht); - qdf_spinlock_create(&qdf_nbuf_map_lock); -} - -static void qdf_nbuf_map_leaks_print(void) -{ - struct qdf_nbuf_map_metadata *meta; - int bucket; - uint32_t count = 0; - - 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->func, meta->line); - } - - QDF_DEBUG_PANIC("%u fatal nbuf map-no-unmap events detected!", count); -} - -void qdf_nbuf_map_check_for_leaks(void) -{ - qdf_spin_lock_irqsave(&qdf_nbuf_map_lock); - if (!hash_empty(qdf_nbuf_map_ht)) - qdf_nbuf_map_leaks_print(); - qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock); + qdf_tracker_init(&qdf_nbuf_map_tracker); } static void qdf_nbuf_map_tracking_deinit(void) { - qdf_nbuf_map_check_for_leaks(); - qdf_spinlock_destroy(&qdf_nbuf_map_lock); - qdf_flex_mem_deinit(&qdf_nbuf_map_pool); -} - -static struct qdf_nbuf_map_metadata *qdf_nbuf_meta_get(qdf_nbuf_t nbuf) -{ - struct qdf_nbuf_map_metadata *meta; - - hash_for_each_possible(qdf_nbuf_map_ht, meta, node, (size_t)nbuf) { - if (meta->nbuf == nbuf) - return meta; - } - - return NULL; + qdf_tracker_deinit(&qdf_nbuf_map_tracker); } static QDF_STATUS qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *func, uint32_t line) { - struct qdf_nbuf_map_metadata *meta; + QDF_STATUS status; - QDF_BUG(nbuf); - if (!nbuf) { - qdf_err("Cannot map null nbuf"); - return QDF_STATUS_E_INVAL; - } - - qdf_spin_lock_irqsave(&qdf_nbuf_map_lock); - meta = qdf_nbuf_meta_get(nbuf); - qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock); - if (meta) - QDF_DEBUG_PANIC( - "Double nbuf map detected @ %s:%u; last map from %s:%u", - func, line, meta->func, meta->line); - - meta = qdf_flex_mem_alloc(&qdf_nbuf_map_pool); - if (!meta) { - qdf_err("Failed to allocate nbuf map tracking metadata"); - return QDF_STATUS_E_NOMEM; - } - - meta->nbuf = nbuf; - qdf_str_lcopy(meta->func, func, QDF_MEM_FUNC_NAME_SIZE); - meta->line = line; - - qdf_spin_lock_irqsave(&qdf_nbuf_map_lock); - hash_add(qdf_nbuf_map_ht, &meta->node, (size_t)nbuf); - qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock); + status = qdf_tracker_track(&qdf_nbuf_map_tracker, nbuf, func, line); + if (QDF_IS_STATUS_ERROR(status)) + return status; qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_MAP); @@ -691,28 +612,13 @@ qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *func, uint32_t line) static void qdf_nbuf_untrack_map(qdf_nbuf_t nbuf, const char *func, uint32_t line) { - struct qdf_nbuf_map_metadata *meta; - - QDF_BUG(nbuf); - if (!nbuf) { - qdf_err("Cannot unmap null nbuf"); - return; - } - - qdf_spin_lock_irqsave(&qdf_nbuf_map_lock); - meta = qdf_nbuf_meta_get(nbuf); - - if (!meta) - QDF_DEBUG_PANIC( - "Double nbuf unmap or unmap without map detected @ %s:%u", - func, line); - - hash_del(&meta->node); - qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock); - - qdf_flex_mem_free(&qdf_nbuf_map_pool, meta); - qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_UNMAP); + qdf_tracker_untrack(&qdf_nbuf_map_tracker, nbuf, func, line); +} + +void qdf_nbuf_map_check_for_leaks(void) +{ + qdf_tracker_check_for_leaks(&qdf_nbuf_map_tracker); } QDF_STATUS qdf_nbuf_map_debug(qdf_device_t osdev, @@ -851,18 +757,19 @@ void qdf_nbuf_unmap_nbytes_single_debug(qdf_device_t osdev, qdf_export_symbol(qdf_nbuf_unmap_nbytes_single_debug); -static void qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf, const char *func, +static void qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf, + const char *func, uint32_t line) { - struct qdf_nbuf_map_metadata *meta; + char map_func[QDF_TRACKER_FUNC_SIZE]; + uint32_t map_line; - qdf_spin_lock_irqsave(&qdf_nbuf_map_lock); - meta = qdf_nbuf_meta_get(nbuf); - if (meta) - QDF_DEBUG_PANIC( - "Nbuf freed @ %s:%u while mapped from %s:%u", - kbasename(func), line, meta->func, meta->line); - qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock); + if (!qdf_tracker_lookup(&qdf_nbuf_map_tracker, nbuf, + &map_func, &map_line)) + return; + + QDF_DEBUG_PANIC("Nbuf freed @ %s:%u while mapped from %s:%u", + func, line, map_func, map_line); } #else static inline void qdf_nbuf_map_tracking_init(void) diff --git a/qdf/src/qdf_tracker.c b/qdf/src/qdf_tracker.c index 7fe001114326..2061a4b5537a 100644 --- a/qdf/src/qdf_tracker.c +++ b/qdf/src/qdf_tracker.c @@ -81,7 +81,7 @@ static uint32_t qdf_tracker_leaks_print(struct qdf_tracker *tracker, } count++; - qdf_nofl_alert("0x%zx @ %s:%u", node->entry.key, + qdf_nofl_alert("0x%lx @ %s:%u", node->entry.key, node->func, node->line); }