qcacmn: Account for frags attached to chained nbufs in frag_list
Page fragments can be attached to the chained nbufs present in the frag_list of the parent nbuf. Update the debug entries for such fragments in different scenarios. Change-Id: Ib114ec43dcb6cbcd707552bcca19f1ac0d3c2a22 CRs-Fixed: 2791903
This commit is contained in:

committed by
snandini

parent
ef806a62d2
commit
e3907fda5d
@@ -3900,6 +3900,22 @@ void qdf_net_buf_debug_acquire_frag(qdf_nbuf_t buf, const char *func,
|
||||
void qdf_net_buf_debug_release_frag(qdf_nbuf_t buf, const char *func,
|
||||
uint32_t line);
|
||||
|
||||
/**
|
||||
* qdf_nbuf_frag_count_inc() - Increment global frag counter
|
||||
* @buf: qdf_nbuf_t
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void qdf_nbuf_frag_count_inc(qdf_nbuf_t buf);
|
||||
|
||||
/**
|
||||
* qdf_nbuf_frag_count_dec() - Decrement global frag counter
|
||||
* @buf: qdf_nbuf_t
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void qdf_nbuf_frag_count_dec(qdf_nbuf_t buf);
|
||||
|
||||
#else /* NBUF_FRAG_MEMORY_DEBUG */
|
||||
|
||||
/**
|
||||
@@ -3954,6 +3970,15 @@ static inline void qdf_net_buf_debug_release_frag(qdf_nbuf_t buf,
|
||||
uint32_t line)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void qdf_nbuf_frag_count_inc(qdf_nbuf_t buf)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void qdf_nbuf_frag_count_dec(qdf_nbuf_t buf)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* NBUF_FRAG_MEMORY_DEBUG */
|
||||
|
||||
#ifdef MEMORY_DEBUG
|
||||
|
@@ -772,6 +772,20 @@ __qdf_nbuf_alloc(__qdf_device_t osdev, size_t size, int reserve, int align,
|
||||
__qdf_nbuf_t __qdf_nbuf_alloc_no_recycler(size_t size, int reserve, int align,
|
||||
const char *func, uint32_t line);
|
||||
|
||||
/**
|
||||
* __qdf_nbuf_clone() - clone the nbuf (copy is readonly)
|
||||
* @skb: Pointer to network buffer
|
||||
*
|
||||
* if GFP_ATOMIC is overkill then we can check whether its
|
||||
* called from interrupt context and then do it or else in
|
||||
* normal case use GFP_KERNEL
|
||||
*
|
||||
* example use "in_irq() || irqs_disabled()"
|
||||
*
|
||||
* Return: cloned skb
|
||||
*/
|
||||
__qdf_nbuf_t __qdf_nbuf_clone(__qdf_nbuf_t nbuf);
|
||||
|
||||
void __qdf_nbuf_free(struct sk_buff *skb);
|
||||
QDF_STATUS __qdf_nbuf_map(__qdf_device_t osdev,
|
||||
struct sk_buff *skb, qdf_dma_dir_t dir);
|
||||
@@ -1039,30 +1053,6 @@ static inline size_t __qdf_nbuf_get_nr_frags(struct sk_buff *skb)
|
||||
*/
|
||||
#define __qdf_nbuf_pool_delete(osdev)
|
||||
|
||||
/**
|
||||
* __qdf_nbuf_clone() - clone the nbuf (copy is readonly)
|
||||
* @skb: Pointer to network buffer
|
||||
*
|
||||
* if GFP_ATOMIC is overkill then we can check whether its
|
||||
* called from interrupt context and then do it or else in
|
||||
* normal case use GFP_KERNEL
|
||||
*
|
||||
* example use "in_irq() || irqs_disabled()"
|
||||
*
|
||||
* Return: cloned skb
|
||||
*/
|
||||
static inline struct sk_buff *__qdf_nbuf_clone(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *skb_new = NULL;
|
||||
|
||||
skb_new = skb_clone(skb, GFP_ATOMIC);
|
||||
if (skb_new) {
|
||||
__qdf_frag_count_inc(__qdf_nbuf_get_nr_frags(skb_new));
|
||||
__qdf_nbuf_count_inc(skb_new);
|
||||
}
|
||||
return skb_new;
|
||||
}
|
||||
|
||||
/**
|
||||
* __qdf_nbuf_copy() - returns a private copy of the skb
|
||||
* @skb: Pointer to network buffer
|
||||
@@ -1078,7 +1068,6 @@ static inline struct sk_buff *__qdf_nbuf_copy(struct sk_buff *skb)
|
||||
|
||||
skb_new = skb_copy(skb, GFP_ATOMIC);
|
||||
if (skb_new) {
|
||||
__qdf_frag_count_inc(__qdf_nbuf_get_nr_frags(skb_new));
|
||||
__qdf_nbuf_count_inc(skb_new);
|
||||
}
|
||||
return skb_new;
|
||||
|
@@ -445,6 +445,64 @@ void __qdf_nbuf_count_dec(__qdf_nbuf_t nbuf)
|
||||
qdf_export_symbol(__qdf_nbuf_count_dec);
|
||||
#endif
|
||||
|
||||
#ifdef NBUF_FRAG_MEMORY_DEBUG
|
||||
void qdf_nbuf_frag_count_inc(qdf_nbuf_t nbuf)
|
||||
{
|
||||
qdf_nbuf_t ext_list;
|
||||
uint32_t num_nr_frags;
|
||||
uint32_t total_num_nr_frags;
|
||||
|
||||
num_nr_frags = qdf_nbuf_get_nr_frags(nbuf);
|
||||
qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
|
||||
|
||||
total_num_nr_frags = num_nr_frags;
|
||||
|
||||
/* Take into account the frags attached to frag_list */
|
||||
ext_list = qdf_nbuf_get_ext_list(nbuf);
|
||||
while (ext_list) {
|
||||
num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
|
||||
qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
|
||||
total_num_nr_frags += num_nr_frags;
|
||||
ext_list = qdf_nbuf_queue_next(ext_list);
|
||||
}
|
||||
|
||||
qdf_frag_count_inc(total_num_nr_frags);
|
||||
}
|
||||
|
||||
qdf_export_symbol(qdf_nbuf_frag_count_inc);
|
||||
|
||||
void qdf_nbuf_frag_count_dec(qdf_nbuf_t nbuf)
|
||||
{
|
||||
qdf_nbuf_t ext_list;
|
||||
uint32_t num_nr_frags;
|
||||
uint32_t total_num_nr_frags;
|
||||
|
||||
if (qdf_nbuf_get_users(nbuf) > 1)
|
||||
return;
|
||||
|
||||
num_nr_frags = qdf_nbuf_get_nr_frags(nbuf);
|
||||
qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
|
||||
|
||||
total_num_nr_frags = num_nr_frags;
|
||||
|
||||
/* Take into account the frags attached to frag_list */
|
||||
ext_list = qdf_nbuf_get_ext_list(nbuf);
|
||||
while (ext_list) {
|
||||
if (qdf_nbuf_get_users(ext_list) == 1) {
|
||||
num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
|
||||
qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
|
||||
total_num_nr_frags += num_nr_frags;
|
||||
}
|
||||
ext_list = qdf_nbuf_queue_next(ext_list);
|
||||
}
|
||||
|
||||
qdf_frag_count_dec(total_num_nr_frags);
|
||||
}
|
||||
|
||||
qdf_export_symbol(qdf_nbuf_frag_count_dec);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_WIFI_EMULATION_WIFI_3_0) && defined(BUILD_X86) && \
|
||||
!defined(QCA_WIFI_QCN9000)
|
||||
struct sk_buff *__qdf_nbuf_alloc(qdf_device_t osdev, size_t size, int reserve,
|
||||
@@ -636,13 +694,7 @@ void __qdf_nbuf_free(struct sk_buff *skb)
|
||||
if (pld_nbuf_pre_alloc_free(skb))
|
||||
return;
|
||||
|
||||
/**
|
||||
* Decrement global frag counter only when last user of nbuf
|
||||
* does free so as to avoid decrementing count on every free
|
||||
* expect the last one in case where nbuf has multiple users
|
||||
*/
|
||||
if (qdf_nbuf_get_users(skb) == 1)
|
||||
qdf_frag_count_dec(qdf_nbuf_get_nr_frags(skb));
|
||||
qdf_nbuf_frag_count_dec(skb);
|
||||
|
||||
qdf_nbuf_count_dec(skb);
|
||||
qdf_mem_skb_dec(skb->truesize);
|
||||
@@ -654,6 +706,20 @@ void __qdf_nbuf_free(struct sk_buff *skb)
|
||||
|
||||
qdf_export_symbol(__qdf_nbuf_free);
|
||||
|
||||
__qdf_nbuf_t __qdf_nbuf_clone(__qdf_nbuf_t skb)
|
||||
{
|
||||
qdf_nbuf_t skb_new = NULL;
|
||||
|
||||
skb_new = skb_clone(skb, GFP_ATOMIC);
|
||||
if (skb_new) {
|
||||
qdf_nbuf_frag_count_inc(skb_new);
|
||||
qdf_nbuf_count_inc(skb_new);
|
||||
}
|
||||
return skb_new;
|
||||
}
|
||||
|
||||
qdf_export_symbol(__qdf_nbuf_clone);
|
||||
|
||||
#ifdef NBUF_MEMORY_DEBUG
|
||||
enum qdf_nbuf_event_type {
|
||||
QDF_NBUF_ALLOC,
|
||||
@@ -2885,11 +2951,24 @@ void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, const char *func, uint32_t line)
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Take care to delete the debug entries for frag_list */
|
||||
/**
|
||||
* Take care to update the debug entries for frag_list and also
|
||||
* for the frags attached to frag_list
|
||||
*/
|
||||
ext_list = qdf_nbuf_get_ext_list(nbuf);
|
||||
while (ext_list) {
|
||||
if (qdf_nbuf_get_users(ext_list) == 1) {
|
||||
qdf_nbuf_panic_on_free_if_mapped(ext_list, func, line);
|
||||
idx = 0;
|
||||
num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
|
||||
qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
|
||||
while (idx < num_nr_frags) {
|
||||
p_frag = qdf_nbuf_get_frag_addr(ext_list, idx);
|
||||
if (qdf_likely(p_frag))
|
||||
qdf_frag_debug_refcount_dec(p_frag,
|
||||
func, line);
|
||||
idx++;
|
||||
}
|
||||
qdf_net_buf_debug_delete_node(ext_list);
|
||||
}
|
||||
|
||||
@@ -2905,6 +2984,7 @@ qdf_nbuf_t qdf_nbuf_clone_debug(qdf_nbuf_t buf, const char *func, uint32_t line)
|
||||
{
|
||||
uint32_t num_nr_frags;
|
||||
uint32_t idx = 0;
|
||||
qdf_nbuf_t ext_list;
|
||||
qdf_frag_t p_frag;
|
||||
|
||||
qdf_nbuf_t cloned_buf = __qdf_nbuf_clone(buf);
|
||||
@@ -2927,6 +3007,23 @@ qdf_nbuf_t qdf_nbuf_clone_debug(qdf_nbuf_t buf, const char *func, uint32_t line)
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Take care to update debug entries for frags attached to frag_list */
|
||||
ext_list = qdf_nbuf_get_ext_list(cloned_buf);
|
||||
while (ext_list) {
|
||||
idx = 0;
|
||||
num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
|
||||
|
||||
qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
|
||||
|
||||
while (idx < num_nr_frags) {
|
||||
p_frag = qdf_nbuf_get_frag_addr(ext_list, idx);
|
||||
if (qdf_likely(p_frag))
|
||||
qdf_frag_debug_refcount_inc(p_frag, func, line);
|
||||
idx++;
|
||||
}
|
||||
ext_list = qdf_nbuf_queue_next(ext_list);
|
||||
}
|
||||
|
||||
/* Store SKB in internal QDF tracking table */
|
||||
qdf_net_buf_debug_add_node(cloned_buf, 0, func, line);
|
||||
qdf_nbuf_history_add(cloned_buf, func, line, QDF_NBUF_ALLOC_CLONE);
|
||||
@@ -4878,6 +4975,7 @@ void qdf_net_buf_debug_acquire_frag(qdf_nbuf_t buf, const char *func,
|
||||
{
|
||||
uint32_t num_nr_frags;
|
||||
uint32_t idx = 0;
|
||||
qdf_nbuf_t ext_list;
|
||||
qdf_frag_t p_frag;
|
||||
|
||||
if (qdf_unlikely(!buf))
|
||||
@@ -4894,6 +4992,26 @@ void qdf_net_buf_debug_acquire_frag(qdf_nbuf_t buf, const char *func,
|
||||
qdf_frag_debug_refcount_inc(p_frag, func, line);
|
||||
idx++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take care to update the refcount in the debug entries for the
|
||||
* frags attached to frag_list
|
||||
*/
|
||||
ext_list = qdf_nbuf_get_ext_list(buf);
|
||||
while (ext_list) {
|
||||
idx = 0;
|
||||
num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
|
||||
|
||||
qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
|
||||
|
||||
while (idx < num_nr_frags) {
|
||||
p_frag = qdf_nbuf_get_frag_addr(ext_list, idx);
|
||||
if (qdf_likely(p_frag))
|
||||
qdf_frag_debug_refcount_inc(p_frag, func, line);
|
||||
idx++;
|
||||
}
|
||||
ext_list = qdf_nbuf_queue_next(ext_list);
|
||||
}
|
||||
}
|
||||
|
||||
qdf_export_symbol(qdf_net_buf_debug_acquire_frag);
|
||||
@@ -4902,6 +5020,7 @@ void qdf_net_buf_debug_release_frag(qdf_nbuf_t buf, const char *func,
|
||||
uint32_t line)
|
||||
{
|
||||
uint32_t num_nr_frags;
|
||||
qdf_nbuf_t ext_list;
|
||||
uint32_t idx = 0;
|
||||
qdf_frag_t p_frag;
|
||||
|
||||
@@ -4928,6 +5047,24 @@ void qdf_net_buf_debug_release_frag(qdf_nbuf_t buf, const char *func,
|
||||
qdf_frag_debug_refcount_dec(p_frag, func, line);
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Take care to update debug entries for frags attached to frag_list */
|
||||
ext_list = qdf_nbuf_get_ext_list(buf);
|
||||
while (ext_list) {
|
||||
if (qdf_nbuf_get_users(ext_list) == 1) {
|
||||
idx = 0;
|
||||
num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
|
||||
qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
|
||||
while (idx < num_nr_frags) {
|
||||
p_frag = qdf_nbuf_get_frag_addr(ext_list, idx);
|
||||
if (qdf_likely(p_frag))
|
||||
qdf_frag_debug_refcount_dec(p_frag,
|
||||
func, line);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
ext_list = qdf_nbuf_queue_next(ext_list);
|
||||
}
|
||||
}
|
||||
|
||||
qdf_export_symbol(qdf_net_buf_debug_release_frag);
|
||||
|
Reference in New Issue
Block a user