diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index 312c0ce7c2..d5cac604a2 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -1635,6 +1635,20 @@ qdf_nbuf_t qdf_nbuf_copy_expand_debug(qdf_nbuf_t buf, int headroom, int tailroom, const char *func, uint32_t line); +/** + * qdf_nbuf_unshare() - make a copy of the shared nbuf + * @buf: Network buf instance + * + * Return: New nbuf which is a copy of the received nbuf if it is cloned, + * else, return the original nbuf + */ +#define qdf_nbuf_unshare(d) \ + qdf_nbuf_unshare_debug(d, __func__, __LINE__) + +qdf_nbuf_t +qdf_nbuf_unshare_debug(qdf_nbuf_t buf, const char *func_name, + uint32_t line_num); + #else /* NBUF_MEMORY_DEBUG */ static inline void qdf_net_buf_debug_init(void) {} @@ -1766,6 +1780,10 @@ static inline qdf_nbuf_t qdf_nbuf_copy_expand(qdf_nbuf_t buf, int headroom, return __qdf_nbuf_copy_expand(buf, headroom, tailroom); } +static inline qdf_nbuf_t qdf_nbuf_unshare(qdf_nbuf_t buf) +{ + return __qdf_nbuf_unshare(buf); +} #endif /* NBUF_MEMORY_DEBUG */ /** @@ -3449,36 +3467,6 @@ qdf_nbuf_linearize(qdf_nbuf_t buf) return __qdf_nbuf_linearize(buf); } -#ifdef NBUF_MEMORY_DEBUG -#define qdf_nbuf_unshare(d) \ - qdf_nbuf_unshare_debug(d, __func__, __LINE__) - -static inline qdf_nbuf_t -qdf_nbuf_unshare_debug(qdf_nbuf_t buf, const char *func_name, uint32_t line_num) -{ - qdf_nbuf_t unshared_buf; - - unshared_buf = __qdf_nbuf_unshare(buf); - - if (qdf_likely(buf != unshared_buf)) { - qdf_net_buf_debug_delete_node(buf); - - if (unshared_buf) - qdf_net_buf_debug_add_node(unshared_buf, 0, - func_name, line_num); - } - - return unshared_buf; -} - -#else -static inline qdf_nbuf_t -qdf_nbuf_unshare(qdf_nbuf_t buf) -{ - return __qdf_nbuf_unshare(buf); -} -#endif - static inline bool qdf_nbuf_is_cloned(qdf_nbuf_t buf) { diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index 6c39baa142..8e881bd5da 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -1886,7 +1886,15 @@ __qdf_nbuf_linearize(struct sk_buff *skb) static inline struct sk_buff * __qdf_nbuf_unshare(struct sk_buff *skb) { - return skb_unshare(skb, GFP_ATOMIC); + struct sk_buff *skb_new; + + __qdf_frag_count_dec(__qdf_nbuf_get_nr_frags(skb)); + + skb_new = skb_unshare(skb, GFP_ATOMIC); + if (skb_new) + __qdf_frag_count_inc(__qdf_nbuf_get_nr_frags(skb_new)); + + return skb_new; } /** diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index bcd115034e..e69dea5596 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -2911,6 +2911,58 @@ qdf_nbuf_copy_expand_debug(qdf_nbuf_t buf, int headroom, int tailroom, qdf_export_symbol(qdf_nbuf_copy_expand_debug); +qdf_nbuf_t +qdf_nbuf_unshare_debug(qdf_nbuf_t buf, const char *func_name, + uint32_t line_num) +{ + qdf_nbuf_t unshared_buf; + qdf_frag_t p_frag; + uint32_t num_nr_frags; + uint32_t idx = 0; + + if (is_initial_mem_debug_disabled) + return __qdf_nbuf_unshare(buf); + + /* Take care to delete the debug entries for frags */ + num_nr_frags = qdf_nbuf_get_nr_frags(buf); + + while (idx < num_nr_frags) { + p_frag = qdf_nbuf_get_frag_addr(buf, idx); + if (qdf_likely(p_frag)) + qdf_frag_debug_refcount_dec(p_frag, func_name, + line_num); + idx++; + } + + unshared_buf = __qdf_nbuf_unshare(buf); + + if (qdf_likely(buf != unshared_buf)) { + qdf_net_buf_debug_delete_node(buf); + + if (unshared_buf) + qdf_net_buf_debug_add_node(unshared_buf, 0, + func_name, line_num); + } + + if (unshared_buf) { + /* Take care to add the debug entries for frags */ + num_nr_frags = qdf_nbuf_get_nr_frags(unshared_buf); + + idx = 0; + while (idx < num_nr_frags) { + p_frag = qdf_nbuf_get_frag_addr(unshared_buf, idx); + if (qdf_likely(p_frag)) + qdf_frag_debug_refcount_inc(p_frag, func_name, + line_num); + idx++; + } + } + + return unshared_buf; +} + +qdf_export_symbol(qdf_nbuf_unshare_debug); + #endif /* NBUF_MEMORY_DEBUG */ #if defined(FEATURE_TSO)