diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index b411ba7fe0..7a68b374b6 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -125,7 +125,7 @@ dp_pdev_frag_alloc_and_map(struct dp_soc *dp_soc, QDF_STATUS ret = QDF_STATUS_E_FAILURE; (nbuf_frag_info_t->virt_addr).vaddr = - qdf_frag_alloc(rx_desc_pool->buf_size); + qdf_frag_alloc(NULL, rx_desc_pool->buf_size); if (!((nbuf_frag_info_t->virt_addr).vaddr)) { dp_err("Frag alloc failed"); diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c index 804e3b2bf0..47391608ff 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c @@ -194,7 +194,8 @@ dp_mon_frag_alloc_and_map(struct dp_soc *dp_soc, { QDF_STATUS ret = QDF_STATUS_E_FAILURE; - mon_desc->buf_addr = qdf_frag_alloc(mon_desc_pool->buf_size); + mon_desc->buf_addr = qdf_frag_alloc(&mon_desc_pool->pf_cache, + mon_desc_pool->buf_size); if (!mon_desc->buf_addr) { dp_mon_err("Frag alloc failed"); diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h index 177a8a3eb2..b6e30c9d9c 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h +++ b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h @@ -117,6 +117,7 @@ union dp_mon_desc_list_elem_t { * @owner: owner for nbuf * @buf_size: Buffer size * @buf_alignment: Buffer alignment + * @pf_cache: page frag cache */ struct dp_mon_desc_pool { uint32_t pool_size; @@ -126,6 +127,7 @@ struct dp_mon_desc_pool { uint8_t owner; uint16_t buf_size; uint8_t buf_alignment; + qdf_frag_cache_t pf_cache; }; /** diff --git a/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c index 7f78485528..70792a5495 100644 --- a/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c @@ -23,6 +23,8 @@ #include "hal_be_api_mon.h" #include "dp_internal.h" #include "qdf_mem.h" /* qdf_mem_malloc,free */ +#include +#include "qdf_nbuf_frag.h" #include "dp_mon.h" #include #include @@ -1508,6 +1510,8 @@ dp_rx_mon_buf_desc_pool_deinit(struct dp_soc *soc) struct dp_mon_soc *mon_soc = soc->monitor_soc; struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc); + /* Drain page frag cachce before pool deinit */ + qdf_frag_cache_drain(&mon_soc_be->rx_desc_mon.pf_cache); dp_mon_desc_pool_deinit(&mon_soc_be->rx_desc_mon); } diff --git a/qdf/inc/qdf_nbuf_frag.h b/qdf/inc/qdf_nbuf_frag.h index 61b42caa0d..1e82d504fe 100644 --- a/qdf/inc/qdf_nbuf_frag.h +++ b/qdf/inc/qdf_nbuf_frag.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -28,6 +29,12 @@ #include #include +/* + * typedef qdf_frag_cache_t - Platform independent + * frag cache abstraction + */ +typedef __qdf_frag_cache_t qdf_frag_cache_t; + /* * typedef qdf_frag_t - Platform independent frag address abstraction */ @@ -109,18 +116,21 @@ void qdf_frag_debug_delete_node(qdf_frag_t fragp, const char *func_name, void qdf_frag_debug_update_addr(qdf_frag_t p_fragp, qdf_frag_t n_fragp, const char *func_name, uint32_t line_num); -#define qdf_frag_alloc(s) \ - qdf_frag_alloc_debug(s, __func__, __LINE__) +#define qdf_frag_alloc(p, s) \ + qdf_frag_alloc_debug(p, s, __func__, __LINE__) /** * qdf_frag_alloc_debug() - Allocate frag memory + * @pf_cache: page frag cache * @fragsz: Size of frag memory to be allocated * @func_name: Caller function name * @line_num: Caller function line no. * * Return: Allocated frag address */ -qdf_frag_t qdf_frag_alloc_debug(unsigned int fragsz, const char *func_name, +qdf_frag_t qdf_frag_alloc_debug(qdf_frag_cache_t *pf_cache, + unsigned int fragsz, + const char *func_name, uint32_t line_num); #define qdf_frag_free(p) \ @@ -180,13 +190,15 @@ static inline void qdf_frag_debug_update_addr(qdf_frag_t p_fragp, /** * qdf_frag_alloc() - Allocate frag memory + * @pf_cache: page frag cache * @fragsz: Size of frag memory to be allocated * * Return: Allocated frag address */ -static inline qdf_frag_t qdf_frag_alloc(unsigned int fragsz) +static inline qdf_frag_t qdf_frag_alloc(qdf_frag_cache_t *pf_cache, + unsigned int fragsz) { - return __qdf_frag_alloc(fragsz); + return __qdf_frag_alloc(pf_cache, fragsz); } /** @@ -284,4 +296,15 @@ static inline void qdf_mem_unmap_page(qdf_device_t osdev, qdf_dma_addr_t paddr, __qdf_mem_unmap_page(osdev, paddr, nbytes, dir); } +/* + * qdf_frag_cache_drain() - Drain page frag cache + * + * @pf_cache: page frag cache + * + * Return: void + */ +static inline void qdf_frag_cache_drain(qdf_frag_cache_t *pf_cache) +{ + __qdf_frag_cache_drain(pf_cache); +} #endif /* _QDF_NBUF_FRAG_H */ diff --git a/qdf/linux/src/i_qdf_nbuf_frag.h b/qdf/linux/src/i_qdf_nbuf_frag.h index a83aa07374..8694047f85 100644 --- a/qdf/linux/src/i_qdf_nbuf_frag.h +++ b/qdf/linux/src/i_qdf_nbuf_frag.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -30,6 +31,11 @@ #define QDF_NBUF_FRAG_DEBUG_COUNT_ZERO 0 #define QDF_NBUF_FRAG_DEBUG_COUNT_ONE 1 +/** + * typedef __qdf_frag_cache_t - Abstraction for void * for frag address + */ +typedef struct page_frag_cache __qdf_frag_cache_t; + /** * typedef __qdf_frag_t - Abstraction for void * for frag address */ @@ -126,6 +132,14 @@ QDF_STATUS __qdf_mem_map_page(qdf_device_t osdev, __qdf_frag_t buf, qdf_dma_dir_t dir, size_t nbytes, qdf_dma_addr_t *phy_addr); +/** + * __qdf_frag_cache_drain() - Drain page frag cache + * @pf_cache: page frag cache + * + * Return: void + */ +void __qdf_frag_cache_drain(__qdf_frag_cache_t *pf_cache); + /** * __qdf_frag_free() - Free allocated frag memory * @vaddr: Frag address to be freed @@ -142,17 +156,39 @@ static inline void __qdf_frag_free(__qdf_frag_t vaddr) /** * __qdf_frag_alloc() - Allocate frag Memory + * @pf_cache: page frag cache * @fragsz: Size of frag memory to be allocated * * Return: Allocated frag addr. */ -static inline __qdf_frag_t __qdf_frag_alloc(unsigned int fragsz) +#if defined(QDF_FRAG_CACHE_SUPPORT) +static inline __qdf_frag_t __qdf_frag_alloc(__qdf_frag_cache_t *pf_cache, + unsigned int fragsz) +{ + __qdf_frag_t p_frag; + + if (pf_cache) { + unsigned int sz = SKB_DATA_ALIGN(fragsz); + + p_frag = page_frag_alloc(pf_cache, sz, GFP_ATOMIC); + } else { + p_frag = netdev_alloc_frag(fragsz); + } + if (p_frag) + __qdf_frag_count_inc(QDF_NBUF_FRAG_DEBUG_COUNT_ONE); + return p_frag; +} +#else +static inline __qdf_frag_t __qdf_frag_alloc(__qdf_frag_cache_t *pf_cache, + unsigned int fragsz) { __qdf_frag_t p_frag = netdev_alloc_frag(fragsz); if (p_frag) __qdf_frag_count_inc(QDF_NBUF_FRAG_DEBUG_COUNT_ONE); + return p_frag; } +#endif #endif /* _I_QDF_NBUF_FRAG_H */ diff --git a/qdf/linux/src/qdf_nbuf_frag.c b/qdf/linux/src/qdf_nbuf_frag.c index 695c6b0edc..90c476ad4d 100644 --- a/qdf/linux/src/qdf_nbuf_frag.c +++ b/qdf/linux/src/qdf_nbuf_frag.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -748,15 +749,17 @@ void qdf_frag_debug_update_addr(qdf_frag_t p_fragp, qdf_frag_t n_fragp, } } -qdf_frag_t qdf_frag_alloc_debug(unsigned int frag_size, const char *func_name, +qdf_frag_t qdf_frag_alloc_debug(qdf_frag_cache_t *pf_cache, + unsigned int frag_size, + const char *func_name, uint32_t line_num) { qdf_frag_t p_frag; if (is_initial_mem_debug_disabled) - return __qdf_frag_alloc(frag_size); + return __qdf_frag_alloc(pf_cache, frag_size); - p_frag = __qdf_frag_alloc(frag_size); + p_frag = __qdf_frag_alloc(pf_cache, frag_size); /* Store frag in QDF Frag Tracking Table */ if (qdf_likely(p_frag)) @@ -827,3 +830,20 @@ void __qdf_mem_unmap_page(qdf_device_t osdev, qdf_dma_addr_t paddr, #endif qdf_export_symbol(__qdf_mem_unmap_page); + +#if defined(QDF_FRAG_CACHE_SUPPORT) +void __qdf_frag_cache_drain(qdf_frag_cache_t *pf_cache) +{ + struct page *page; + + page = virt_to_page(pf_cache->va); + __page_frag_cache_drain(page, pf_cache->pagecnt_bias); + memset(pf_cache, 0, sizeof(*pf_cache)); +} +#else +void __qdf_frag_cache_drain(qdf_frag_cache_t *pf_cache) +{ +} +#endif + +qdf_export_symbol(__qdf_frag_cache_drain);