summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimanshu Agarwal <himanaga@codeaurora.org>2017-04-04 19:15:30 +0530
committerSandeep Puligilla <spuligil@codeaurora.org>2017-04-13 07:37:48 -0700
commitedba4e9d28f39f50f5857020dec590743c217cbd (patch)
treea5857469d59ce238aafe3effbc4e06d78131b761
parent92a1d1b0adea4299c7e03653abbec245ef55ae1c (diff)
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
-rw-r--r--qdf/inc/qdf_nbuf.h109
-rw-r--r--qdf/linux/src/i_qdf_nbuf.h29
-rw-r--r--qdf/linux/src/qdf_nbuf.c27
3 files changed, 92 insertions, 73 deletions
diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h
index 7d54fdda8dbf..632f1f584907 100644
--- a/qdf/inc/qdf_nbuf.h
+++ b/qdf/inc/qdf_nbuf.h
@@ -602,12 +602,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 */
@@ -632,10 +686,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);
}
@@ -700,6 +759,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)
{
}
@@ -767,7 +831,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)
@@ -1060,20 +1129,6 @@ qdf_nbuf_queue_first(qdf_nbuf_queue_t *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
*
@@ -1954,17 +2009,6 @@ static inline void qdf_dmaaddr_to_32s(qdf_dma_addr_t dmaaddr,
}
/**
- * 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
* @nbuf: network buffer to be segmented
@@ -2031,19 +2075,6 @@ static inline qdf_nbuf_t qdf_nbuf_inc_users(qdf_nbuf_t 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
*
* @nbuf: Network buffer (skb on linux)
diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h
index d72db353677b..a46ef5cf8496 100644
--- a/qdf/linux/src/i_qdf_nbuf.h
+++ b/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
@@ -183,8 +182,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,
@@ -276,9 +274,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)
@@ -488,7 +483,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);
@@ -919,27 +913,6 @@ static inline struct sk_buff *__qdf_nbuf_get_ext_list(struct sk_buff *head_buf)
}
/**
- * __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
*
diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c
index cd9cfea6ca9d..a9d380b9e6e8 100644
--- a/qdf/linux/src/qdf_nbuf.c
+++ b/qdf/linux/src/qdf_nbuf.c
@@ -1539,6 +1539,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);
}
qdf_export_symbol(qdf_net_buf_debug_add_node);
@@ -1598,6 +1599,26 @@ done:
}
qdf_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);
+}
+qdf_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)
@@ -1627,13 +1648,7 @@ void qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf)
}
qdf_export_symbol(qdf_net_buf_debug_release_skb);
-#else
-void qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf)
-{
-}
-qdf_export_symbol(qdf_net_buf_debug_delete_node);
#endif /*MEMORY_DEBUG */
-
#if defined(FEATURE_TSO)
/**