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,
|
void qdf_net_buf_debug_release_frag(qdf_nbuf_t buf, const char *func,
|
||||||
uint32_t line);
|
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 */
|
#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)
|
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 */
|
#endif /* NBUF_FRAG_MEMORY_DEBUG */
|
||||||
|
|
||||||
#ifdef 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,
|
__qdf_nbuf_t __qdf_nbuf_alloc_no_recycler(size_t size, int reserve, int align,
|
||||||
const char *func, uint32_t line);
|
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);
|
void __qdf_nbuf_free(struct sk_buff *skb);
|
||||||
QDF_STATUS __qdf_nbuf_map(__qdf_device_t osdev,
|
QDF_STATUS __qdf_nbuf_map(__qdf_device_t osdev,
|
||||||
struct sk_buff *skb, qdf_dma_dir_t dir);
|
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)
|
#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
|
* __qdf_nbuf_copy() - returns a private copy of the skb
|
||||||
* @skb: Pointer to network buffer
|
* @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);
|
skb_new = skb_copy(skb, GFP_ATOMIC);
|
||||||
if (skb_new) {
|
if (skb_new) {
|
||||||
__qdf_frag_count_inc(__qdf_nbuf_get_nr_frags(skb_new));
|
|
||||||
__qdf_nbuf_count_inc(skb_new);
|
__qdf_nbuf_count_inc(skb_new);
|
||||||
}
|
}
|
||||||
return 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);
|
qdf_export_symbol(__qdf_nbuf_count_dec);
|
||||||
#endif
|
#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) && \
|
#if defined(CONFIG_WIFI_EMULATION_WIFI_3_0) && defined(BUILD_X86) && \
|
||||||
!defined(QCA_WIFI_QCN9000)
|
!defined(QCA_WIFI_QCN9000)
|
||||||
struct sk_buff *__qdf_nbuf_alloc(qdf_device_t osdev, size_t size, int reserve,
|
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))
|
if (pld_nbuf_pre_alloc_free(skb))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/**
|
qdf_nbuf_frag_count_dec(skb);
|
||||||
* 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_count_dec(skb);
|
qdf_nbuf_count_dec(skb);
|
||||||
qdf_mem_skb_dec(skb->truesize);
|
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_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
|
#ifdef NBUF_MEMORY_DEBUG
|
||||||
enum qdf_nbuf_event_type {
|
enum qdf_nbuf_event_type {
|
||||||
QDF_NBUF_ALLOC,
|
QDF_NBUF_ALLOC,
|
||||||
@@ -2885,11 +2951,24 @@ void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, const char *func, uint32_t line)
|
|||||||
idx++;
|
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);
|
ext_list = qdf_nbuf_get_ext_list(nbuf);
|
||||||
while (ext_list) {
|
while (ext_list) {
|
||||||
if (qdf_nbuf_get_users(ext_list) == 1) {
|
if (qdf_nbuf_get_users(ext_list) == 1) {
|
||||||
qdf_nbuf_panic_on_free_if_mapped(ext_list, func, line);
|
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);
|
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 num_nr_frags;
|
||||||
uint32_t idx = 0;
|
uint32_t idx = 0;
|
||||||
|
qdf_nbuf_t ext_list;
|
||||||
qdf_frag_t p_frag;
|
qdf_frag_t p_frag;
|
||||||
|
|
||||||
qdf_nbuf_t cloned_buf = __qdf_nbuf_clone(buf);
|
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++;
|
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 */
|
/* Store SKB in internal QDF tracking table */
|
||||||
qdf_net_buf_debug_add_node(cloned_buf, 0, func, line);
|
qdf_net_buf_debug_add_node(cloned_buf, 0, func, line);
|
||||||
qdf_nbuf_history_add(cloned_buf, func, line, QDF_NBUF_ALLOC_CLONE);
|
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 num_nr_frags;
|
||||||
uint32_t idx = 0;
|
uint32_t idx = 0;
|
||||||
|
qdf_nbuf_t ext_list;
|
||||||
qdf_frag_t p_frag;
|
qdf_frag_t p_frag;
|
||||||
|
|
||||||
if (qdf_unlikely(!buf))
|
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);
|
qdf_frag_debug_refcount_inc(p_frag, func, line);
|
||||||
idx++;
|
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);
|
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 line)
|
||||||
{
|
{
|
||||||
uint32_t num_nr_frags;
|
uint32_t num_nr_frags;
|
||||||
|
qdf_nbuf_t ext_list;
|
||||||
uint32_t idx = 0;
|
uint32_t idx = 0;
|
||||||
qdf_frag_t p_frag;
|
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);
|
qdf_frag_debug_refcount_dec(p_frag, func, line);
|
||||||
idx++;
|
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);
|
qdf_export_symbol(qdf_net_buf_debug_release_frag);
|
||||||
|
Reference in New Issue
Block a user