Browse Source

qcacmn: Add support to add memory tracking in tx path

Add support to add memory tracking in tx path in WLAN driver using
already present infrastructure for memory tracking.

Change-Id: I6a2c9890e0af1fd51c4e2dfcded68f0075a3a4ef
CRs-Fixed: 2025670
Himanshu Agarwal 8 years ago
parent
commit
33d0d707bd
3 changed files with 92 additions and 73 deletions
  1. 70 39
      qdf/inc/qdf_nbuf.h
  2. 1 28
      qdf/linux/src/i_qdf_nbuf.h
  3. 21 6
      qdf/linux/src/qdf_nbuf.c

+ 70 - 39
qdf/inc/qdf_nbuf.h

@@ -630,12 +630,66 @@ qdf_nbuf_dma_map_info(qdf_dma_map_t bmap, qdf_dmamap_info_t *sg)
 	__qdf_nbuf_dma_map_info(bmap, sg);
 }
 
+/**
+ * qdf_nbuf_is_tso() - is the network buffer a jumbo packet?
+ * @buf: Network buffer
+ *
+ * Return: 1 - this is a jumbo packet 0 - not a jumbo packet
+ */
+static inline uint8_t qdf_nbuf_is_tso(qdf_nbuf_t nbuf)
+{
+	return __qdf_nbuf_is_tso(nbuf);
+}
+
+/**
+ * qdf_nbuf_get_users() - function to get the number of users referencing this
+ * network buffer
+ *
+ * @nbuf:   network buffer
+ *
+ * Return: number of user references to nbuf.
+ */
+static inline int qdf_nbuf_get_users(qdf_nbuf_t nbuf)
+{
+	return __qdf_nbuf_get_users(nbuf);
+}
+
+/**
+ * qdf_nbuf_next() - get the next packet in the linked list
+ * @buf: Network buffer
+ *
+ * This function can be used when nbufs are directly linked into a list,
+ * rather than using a separate network buffer queue object.
+ *
+ * Return: next network buffer in the linked list
+ */
+static inline qdf_nbuf_t qdf_nbuf_next(qdf_nbuf_t buf)
+{
+	return __qdf_nbuf_next(buf);
+}
+
 #ifdef MEMORY_DEBUG
 void qdf_net_buf_debug_init(void);
 void qdf_net_buf_debug_exit(void);
 void qdf_net_buf_debug_clean(void);
 void qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf, size_t size,
 			uint8_t *file_name, uint32_t line_num);
+void qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf);
+
+/**
+ * qdf_net_buf_debug_acquire_skb() - acquire skb to avoid memory leak
+ * @net_buf: Network buf holding head segment (single)
+ * @file_name: pointer to file name
+ * @line_num: line number
+ *
+ * WLAN driver module's SKB which are allocated by network stack are
+ * suppose to call this API before freeing it such that the SKB
+ * is not reported as memory leak.
+ *
+ * Return: none
+ */
+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);
 
 /* nbuf allocation rouines */
@@ -659,10 +713,15 @@ qdf_nbuf_alloc_debug(qdf_device_t osdev, qdf_size_t size, int reserve,
 
 static inline void qdf_nbuf_free(qdf_nbuf_t net_buf)
 {
+	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))
 		qdf_net_buf_debug_delete_node(net_buf);
 
+free_buf:
 	__qdf_nbuf_free(net_buf);
 }
 
@@ -727,6 +786,11 @@ qdf_nbuf_copy_debug(qdf_nbuf_t buf, uint8_t *file_name,
 
 #else
 
+static inline void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf,
+			uint8_t *file_name, uint32_t line_num)
+{
+}
+
 static inline void qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf)
 {
 	return;
@@ -795,7 +859,12 @@ static inline void qdf_nbuf_init_fast(qdf_nbuf_t nbuf)
 
 static inline void qdf_nbuf_tx_free(qdf_nbuf_t buf_list, int tx_err)
 {
-	__qdf_nbuf_tx_free(buf_list, tx_err);
+	while (buf_list) {
+		qdf_nbuf_t next = qdf_nbuf_next(buf_list);
+
+		qdf_nbuf_free(buf_list);
+		buf_list = next;
+	}
 }
 
 static inline void qdf_nbuf_ref(qdf_nbuf_t buf)
@@ -1087,20 +1156,6 @@ qdf_nbuf_queue_first(qdf_nbuf_queue_t *head)
 	return __qdf_nbuf_queue_first(head);
 }
 
-/**
- * qdf_nbuf_next() - get the next packet in the linked list
- * @buf: Network buffer
- *
- * This function can be used when nbufs are directly linked into a list,
- * rather than using a separate network buffer queue object.
- *
- * Return: next network buffer in the linked list
- */
-static inline qdf_nbuf_t qdf_nbuf_next(qdf_nbuf_t buf)
-{
-	return __qdf_nbuf_next(buf);
-}
-
 /**
  * qdf_nbuf_get_protocol() - return the protocol value of the skb
  * @skb: Pointer to network buffer
@@ -1929,17 +1984,6 @@ static inline void qdf_dmaaddr_to_32s(qdf_dma_addr_t dmaaddr,
 	return __qdf_dmaaddr_to_32s(dmaaddr, lo, hi);
 }
 
-/**
- * qdf_nbuf_is_tso() - is the network buffer a jumbo packet?
- * @buf: Network buffer
- *
- * Return: 1 - this is a jumbo packet 0 - not a jumbo packet
- */
-static inline uint8_t qdf_nbuf_is_tso(qdf_nbuf_t nbuf)
-{
-	return __qdf_nbuf_is_tso(nbuf);
-}
-
 /**
  * qdf_nbuf_get_tso_info() - function to divide a jumbo TSO
  * network buffer into segments
@@ -2006,19 +2050,6 @@ static inline qdf_nbuf_t qdf_nbuf_inc_users(qdf_nbuf_t nbuf)
 	return __qdf_nbuf_inc_users(nbuf);
 }
 
-/**
- * qdf_nbuf_get_users() - function to get the number of users referencing this
- * network buffer
- *
- * @nbuf:   network buffer
- *
- * Return: number of user references to nbuf.
- */
-static inline int qdf_nbuf_get_users(qdf_nbuf_t nbuf)
-{
-	return __qdf_nbuf_get_users(nbuf);
-}
-
 /**
  * qdf_nbuf_data_attr_get() - Get data_attr field from cvg_nbuf_cb
  *

+ 1 - 28
qdf/linux/src/i_qdf_nbuf.h

@@ -116,7 +116,6 @@ typedef union {
  * @tx.trace       : combined structure for DP and protocol trace
  * @tx.trace.packet_state: {NBUF_TX_PKT_[(HDD)|(TXRX_ENQUEUE)|(TXRX_DEQUEUE)|
  *                       +               (TXRX)|(HTT)|(HTC)|(HIF)|(CE)|(FREE)]
- * @tx.trace.is_packet_priv: flag, pkt generated internally or come from NS
  * @tx.trace.packet_track: {NBUF_TX_PKT_[(DATA)|(MGMT)]_TRACK}
  * @tx.trace.proto_type  : bitmap of NBUF_PKT_TRAC_TYPE[(EAPOL)|(DHCP)|
  *                       +                              (MGMT_ACTION)] - 4 bits
@@ -186,8 +185,7 @@ struct qdf_nbuf_cb {
 				struct {
 					uint32_t data_attr; /* 4 bytes */
 					struct{
-						uint8_t packet_state:7,
-							is_packet_priv:1;
+						uint8_t packet_state;
 						uint8_t packet_track:4,
 							proto_type:4;
 						uint8_t dp_trace:1,
@@ -286,9 +284,6 @@ struct qdf_nbuf_cb {
 #define QDF_NBUF_CB_TX_PACKET_STATE(skb) \
 	(((struct qdf_nbuf_cb *) \
 		((skb)->cb))->u.tx.dev.mcl.trace.packet_state)
-#define QDF_NBUF_CB_TX_IS_PACKET_PRIV(skb) \
-	(((struct qdf_nbuf_cb *) \
-		((skb)->cb))->u.tx.dev.mcl.trace.is_packet_priv)
 #define QDF_NBUF_CB_TX_PACKET_TRACK(skb) \
 	(((struct qdf_nbuf_cb *) \
 		((skb)->cb))->u.tx.dev.mcl.trace.packet_track)
@@ -540,7 +535,6 @@ void __qdf_nbuf_unmap_nbytes_single(
 void __qdf_nbuf_dma_map_info(__qdf_dma_map_t bmap, qdf_dmamap_info_t *sg);
 uint32_t __qdf_nbuf_get_frag_size(__qdf_nbuf_t nbuf, uint32_t cur_frag);
 void __qdf_nbuf_frag_info(struct sk_buff *skb, qdf_sglist_t  *sg);
-void qdf_net_buf_debug_delete_node(struct sk_buff *net_buf);
 QDF_STATUS __qdf_nbuf_frag_map(
 	qdf_device_t osdev, __qdf_nbuf_t nbuf,
 	int offset, qdf_dma_dir_t dir, int cur_frag);
@@ -966,27 +960,6 @@ static inline struct sk_buff *__qdf_nbuf_get_ext_list(struct sk_buff *head_buf)
 	return (skb_shinfo(head_buf)->frag_list);
 }
 
-/**
- * __qdf_nbuf_tx_free() - free skb list
- * @skb: Pointer to network buffer
- * @tx_err: TX error
- *
- * Return: none
- */
-static inline void __qdf_nbuf_tx_free(struct sk_buff *bufs, int tx_err)
-{
-	while (bufs) {
-		struct sk_buff *next = __qdf_nbuf_next(bufs);
-
-		if (QDF_NBUF_CB_TX_IS_PACKET_PRIV(bufs)) {
-			if (qdf_likely(bufs))
-				qdf_net_buf_debug_delete_node(bufs);
-		}
-		__qdf_nbuf_free(bufs);
-		bufs = next;
-	}
-}
-
 /**
  * __qdf_nbuf_get_age() - return the checksum value of the skb
  * @skb: Pointer to network buffer

+ 21 - 6
qdf/linux/src/qdf_nbuf.c

@@ -1477,6 +1477,7 @@ void qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf, size_t size,
 				  "Mem alloc failed ! Could not track skb from %s %d of size %zu",
 				  file_name, line_num, size);
 	}
+
 	spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
 
 	return;
@@ -1540,6 +1541,26 @@ done:
 }
 EXPORT_SYMBOL(qdf_net_buf_debug_delete_node);
 
+void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf,
+			uint8_t *file_name, uint32_t line_num)
+{
+	qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(net_buf);
+
+	while (ext_list) {
+		/*
+		 * Take care to add if it is Jumbo packet connected using
+		 * frag_list
+		 */
+		qdf_nbuf_t next;
+
+		next = qdf_nbuf_queue_next(ext_list);
+		qdf_net_buf_debug_add_node(ext_list, 0, file_name, line_num);
+		ext_list = next;
+	}
+	qdf_net_buf_debug_add_node(net_buf, 0, file_name, line_num);
+}
+EXPORT_SYMBOL(qdf_net_buf_debug_acquire_skb);
+
 /**
  * qdf_net_buf_debug_release_skb() - release skb to avoid memory leak
  * @net_buf: Network buf holding head segment (single)
@@ -1569,13 +1590,7 @@ void qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf)
 }
 EXPORT_SYMBOL(qdf_net_buf_debug_release_skb);
 
-#else
-void qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf)
-{
-}
-EXPORT_SYMBOL(qdf_net_buf_debug_delete_node);
 #endif /*MEMORY_DEBUG */
-
 #if defined(FEATURE_TSO)
 
 /**