浏览代码

qcacmn: Record nbuf free information for debug

During network buffer free record the information such as file name,
line number, net buff address and time stamp. This helps to debug
issues related to buffer access after free.

Change-Id: I579a4764d8ea08210a3eedd349780cab2c081e3a
CRs-Fixed: 2071563
Sravan Kumar Kairam 7 年之前
父节点
当前提交
66d15b2908
共有 2 个文件被更改,包括 79 次插入2 次删除
  1. 9 2
      qdf/inc/qdf_nbuf.h
  2. 70 0
      qdf/linux/src/qdf_nbuf.c

+ 9 - 2
qdf/inc/qdf_nbuf.h

@@ -779,6 +779,8 @@ void qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf);
 void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf,
 			uint8_t *file_name, uint32_t line_num);
 void qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf);
+void qdf_net_buf_free_debug_add(qdf_nbuf_t net_buf, uint8_t *file_name,
+				uint32_t line_num);
 
 /* nbuf allocation rouines */
 
@@ -800,15 +802,20 @@ qdf_nbuf_alloc_debug(qdf_device_t osdev, qdf_size_t size, int reserve,
 	return net_buf;
 }
 
-static inline void qdf_nbuf_free(qdf_nbuf_t net_buf)
+#define qdf_nbuf_free(d)			\
+	qdf_nbuf_free_debug(d, __FILE__, __LINE__)
+static inline void qdf_nbuf_free_debug(qdf_nbuf_t net_buf,
+				       uint8_t *file_name, uint32_t line_num)
 {
 	if (qdf_nbuf_is_tso(net_buf) &&
 			qdf_nbuf_get_users(net_buf) > 1)
 		goto free_buf;
 
 	/* Remove SKB from internal QDF tracking table */
-	if (qdf_likely(net_buf))
+	if (qdf_likely(net_buf)) {
+		qdf_net_buf_free_debug_add(net_buf, file_name, line_num);
 		qdf_net_buf_debug_delete_node(net_buf);
+	}
 
 free_buf:
 	__qdf_nbuf_free(net_buf);

+ 70 - 0
qdf/linux/src/qdf_nbuf.c

@@ -42,6 +42,7 @@
 #include <qdf_trace.h>
 #include <net/ieee80211_radiotap.h>
 #include <qdf_module.h>
+#include <qdf_atomic.h>
 #include <pld_common.h>
 
 #if defined(FEATURE_TSO)
@@ -1213,6 +1214,30 @@ static uint32_t qdf_net_buf_track_max_used;
 static uint32_t qdf_net_buf_track_max_free;
 static uint32_t qdf_net_buf_track_max_allocated;
 
+/**
+ * struct qdf_nbuf_free_track_t - Network buffer free track structure
+ * @p_next: Pointer to next
+ * @net_buf: Pointer to network buffer
+ * @file_name: File name
+ * @line_num: Line number
+ * @time: Time stamp
+ */
+struct qdf_nbuf_free_track_t {
+	struct qdf_nbuf_track_t *p_next;
+	qdf_nbuf_t net_buf;
+	uint8_t *file_name;
+	uint32_t line_num;
+	uint64_t time;
+};
+
+struct qdf_nbuf_free_record_t {
+	struct qdf_nbuf_free_track_t gp_qdf_netbuf_free_tbl[
+					QDF_NET_BUF_TRACK_MAX_SIZE];
+	qdf_atomic_t count;
+};
+
+static struct qdf_nbuf_free_record_t qdf_nbuf_free_record_info;
+
 /**
  * update_max_used() - update qdf_net_buf_track_max_used tracking variable
  *
@@ -1515,6 +1540,51 @@ void qdf_net_buf_debug_exit(void)
 }
 EXPORT_SYMBOL(qdf_net_buf_debug_exit);
 
+/**
+ * qdf_nbuf_free_dbg_get_index() - Get the next record index
+ * @tbl_index: atomic index variable to increment
+ * @size: array size of the circular buffer
+ *
+ * Return: array index
+ */
+static int qdf_nbuf_free_dbg_get_index(qdf_atomic_t *tbl_index, int size)
+{
+	int index = qdf_atomic_inc_return(tbl_index);
+
+	if (index == size)
+		qdf_atomic_sub(size, tbl_index);
+
+	while (index >= size)
+		index -= size;
+
+	return index;
+}
+
+/**
+ * qdf_netbuf_free_debug_add() - Add netbuff free info to the debug
+ * @netbuf: pointer to network buffer
+ * @file_name: fie name from where net buff is freed
+ * @line_num: line number
+ *
+ * Return: none
+ */
+void qdf_net_buf_free_debug_add(qdf_nbuf_t net_buf, uint8_t *file_name,
+				uint32_t line_num)
+{
+	struct qdf_nbuf_free_track_t *p_node;
+	uint16_t index;
+
+	index = qdf_nbuf_free_dbg_get_index(&qdf_nbuf_free_record_info.count,
+					  QDF_NET_BUF_TRACK_MAX_SIZE);
+
+	p_node = &qdf_nbuf_free_record_info.gp_qdf_netbuf_free_tbl[index];
+	p_node->net_buf = net_buf;
+	p_node->file_name = file_name;
+	p_node->line_num = line_num;
+	p_node->time = qdf_get_log_timestamp();
+}
+EXPORT_SYMBOL(qdf_net_buf_free_debug_add);
+
 /**
  * qdf_net_buf_debug_hash() - hash network buffer pointer
  *