Przeglądaj źródła

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
Dustin Brown 6 lat temu
rodzic
commit
0497d105b0
1 zmienionych plików z 17 dodań i 23 usunięć
  1. 17 23
      qdf/linux/src/qdf_nbuf.c

+ 17 - 23
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_flex_mem_release(&qdf_nbuf_map_pool);
+	QDF_BUG(qdf_spin_is_locked(&qdf_nbuf_map_lock));
 
-	qdf_spin_lock_irqsave(&qdf_nbuf_map_lock);
-	is_empty = hash_empty(qdf_nbuf_map_ht);
-	qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock);
+	qdf_nofl_alert("Nbuf map-no-unmap events detected!");
+	qdf_nofl_alert("-----------------------------------------------------");
 
-	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_nofl_alert("0x%zx @ %s:%u",
+			       (uintptr_t)meta->nbuf, meta->file, meta->line);
 	}
-	qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock);
 
-	panic("%u fatal nbuf map without unmap events detected!", count);
+	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);
+	if (!hash_empty(qdf_nbuf_map_ht))
+		qdf_nbuf_map_leaks_print();
+	qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock);
 }
 
 static void qdf_nbuf_map_tracking_deinit(void)