diff options
| author | Himanshu Agarwal <himanaga@codeaurora.org> | 2017-04-04 19:15:30 +0530 |
|---|---|---|
| committer | Sandeep Puligilla <spuligil@codeaurora.org> | 2017-04-13 07:37:48 -0700 |
| commit | edba4e9d28f39f50f5857020dec590743c217cbd (patch) | |
| tree | a5857469d59ce238aafe3effbc4e06d78131b761 | |
| parent | 92a1d1b0adea4299c7e03653abbec245ef55ae1c (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.h | 109 | ||||
| -rw-r--r-- | qdf/linux/src/i_qdf_nbuf.h | 29 | ||||
| -rw-r--r-- | qdf/linux/src/qdf_nbuf.c | 27 |
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) /** |
