From 96997b6d7c5f971c4af6331d1f245fffa7c73b4f Mon Sep 17 00:00:00 2001 From: Jinwei Chen Date: Sat, 8 Aug 2020 23:22:51 +0800 Subject: [PATCH] qcacld-3.0: prealloc for multiple pages allocation prealloc for multiple pages allocation. Change-Id: I4b6209eaf51f02165372290fc4912e26fb1ce139 CRs-Fixed: 2751340 --- core/cds/src/cds_api.c | 4 +- core/dp/txrx3.0/dp_txrx.c | 212 +++++++++++++++++++++++++++++++++++++- core/dp/txrx3.0/dp_txrx.h | 27 +++++ 3 files changed, 238 insertions(+), 5 deletions(-) diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 1b21aaef5490..3afc6d353740 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -124,7 +124,9 @@ static struct ol_if_ops dp_ol_if_ops = { .dp_rx_get_pending = dp_rx_tm_get_pending, #ifdef DP_MEM_PRE_ALLOC .dp_prealloc_get_consistent = dp_prealloc_get_coherent, - .dp_prealloc_put_consistent = dp_prealloc_put_coherent + .dp_prealloc_put_consistent = dp_prealloc_put_coherent, + .dp_get_multi_pages = dp_prealloc_get_multi_pages, + .dp_put_multi_pages = dp_prealloc_put_multi_pages #endif /* TODO: Add any other control path calls required to OL_IF/WMA layer */ }; diff --git a/core/dp/txrx3.0/dp_txrx.c b/core/dp/txrx3.0/dp_txrx.c index 94cd7182cbd2..4032d462d0bd 100644 --- a/core/dp/txrx3.0/dp_txrx.c +++ b/core/dp/txrx3.0/dp_txrx.c @@ -18,9 +18,13 @@ #include #include +#include #include #include #include +#include +#include + QDF_STATUS dp_txrx_init(ol_txrx_soc_handle soc, uint8_t pdev_id, struct dp_txrx_config *config) @@ -146,6 +150,9 @@ int dp_rx_tm_get_pending(ol_txrx_soc_handle soc) /* Num elements in WBM Idle Link */ #define WBM_IDLE_LINK_RING_SIZE (32 * 1024) +/* Num TX desc in TX desc pool */ +#define DP_TX_DESC_POOL_SIZE 4096 + /** * struct dp_consistent_prealloc - element representing DP pre-alloc memory * @ring_type: HAL ring type @@ -167,6 +174,25 @@ struct dp_consistent_prealloc { qdf_dma_addr_t pa_aligned; }; +/** + * struct dp_multi_page_prealloc - element representing DP pre-alloc multiple + pages memory + * @desc_type: source descriptor type for memory allocation + * @element_size: single element size + * @element_num: total number of elements should be allocated + * @in_use: whether this element is in use (occupied) + * @cacheable: coherent memory or cacheable memory + * @pages: multi page information storage + */ +struct dp_multi_page_prealloc { + enum dp_desc_type desc_type; + size_t element_size; + uint16_t element_num; + bool in_use; + bool cacheable; + struct qdf_mem_multi_page_t pages; +}; + static struct dp_consistent_prealloc g_dp_consistent_allocs[] = { /* 5 REO DST rings */ {REO_DST, (sizeof(struct reo_destination_ring)) * REO_DST_RING_SIZE, 0, NULL, NULL, 0, 0}, @@ -195,10 +221,78 @@ static struct dp_consistent_prealloc g_dp_consistent_allocs[] = { }; +/* Number of HW link descriptors needed (rounded to power of 2) */ +#define NUM_HW_LINK_DESCS (32 * 1024) + +/* Size in bytes of HW LINK DESC */ +#define HW_LINK_DESC_SIZE 128 + +/* Size in bytes of TX Desc (rounded to power of 2) */ +#define TX_DESC_SIZE 128 + +/* Size in bytes of TX TSO Desc (rounded to power of 2) */ +#define TX_TSO_DESC_SIZE 256 + +/* Size in bytes of TX TSO Num Seg Desc (rounded to power of 2) */ +#define TX_TSO_NUM_SEG_DESC_SIZE 16 + +#define NON_CACHEABLE 0 +#define CACHEABLE 1 + +static struct dp_multi_page_prealloc g_dp_multi_page_allocs[] = { + /* 4 TX DESC pools */ + {DP_TX_DESC_TYPE, TX_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_DESC_TYPE, TX_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_DESC_TYPE, TX_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_DESC_TYPE, TX_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + + /* 4 Tx EXT DESC NON Cacheable pools */ + {DP_TX_EXT_DESC_TYPE, HAL_TX_EXT_DESC_WITH_META_DATA, DP_TX_DESC_POOL_SIZE, 0, NON_CACHEABLE, { 0 } }, + {DP_TX_EXT_DESC_TYPE, HAL_TX_EXT_DESC_WITH_META_DATA, DP_TX_DESC_POOL_SIZE, 0, NON_CACHEABLE, { 0 } }, + {DP_TX_EXT_DESC_TYPE, HAL_TX_EXT_DESC_WITH_META_DATA, DP_TX_DESC_POOL_SIZE, 0, NON_CACHEABLE, { 0 } }, + {DP_TX_EXT_DESC_TYPE, HAL_TX_EXT_DESC_WITH_META_DATA, DP_TX_DESC_POOL_SIZE, 0, NON_CACHEABLE, { 0 } }, + + /* 4 Tx EXT DESC Link Cacheable pools */ + {DP_TX_EXT_DESC_LINK_TYPE, sizeof(struct dp_tx_ext_desc_elem_s), DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_EXT_DESC_LINK_TYPE, sizeof(struct dp_tx_ext_desc_elem_s), DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_EXT_DESC_LINK_TYPE, sizeof(struct dp_tx_ext_desc_elem_s), DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_EXT_DESC_LINK_TYPE, sizeof(struct dp_tx_ext_desc_elem_s), DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + + /* 4 TX TSO DESC pools */ + {DP_TX_TSO_DESC_TYPE, TX_TSO_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_TSO_DESC_TYPE, TX_TSO_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_TSO_DESC_TYPE, TX_TSO_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_TSO_DESC_TYPE, TX_TSO_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + + /* 4 TX TSO NUM SEG DESC pools */ + {DP_TX_TSO_NUM_SEG_TYPE, TX_TSO_NUM_SEG_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_TSO_NUM_SEG_TYPE, TX_TSO_NUM_SEG_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_TSO_NUM_SEG_TYPE, TX_TSO_NUM_SEG_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + {DP_TX_TSO_NUM_SEG_TYPE, TX_TSO_NUM_SEG_DESC_SIZE, DP_TX_DESC_POOL_SIZE, 0, CACHEABLE, { 0 } }, + + /* DP RX DESCs pools */ + {DP_RX_DESC_BUF_TYPE, sizeof(union dp_rx_desc_list_elem_t), + WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE * WLAN_CFG_RXDMA_REFILL_RING_SIZE, 0, CACHEABLE, { 0 } }, + +#ifdef DISABLE_MON_CONFIG + /* no op */ +#else + /* 2 DP RX DESCs Status pools */ + {DP_RX_DESC_STATUS_TYPE, sizeof(union dp_rx_desc_list_elem_t), + WLAN_CFG_RXDMA_MONITOR_STATUS_RING_SIZE + 1, 0, CACHEABLE, { 0 } }, + {DP_RX_DESC_STATUS_TYPE, sizeof(union dp_rx_desc_list_elem_t), + WLAN_CFG_RXDMA_MONITOR_STATUS_RING_SIZE + 1, 0, CACHEABLE, { 0 } }, +#endif + /* DP HW Link DESCs pools */ + {DP_HW_LINK_DESC_TYPE, HW_LINK_DESC_SIZE, NUM_HW_LINK_DESCS, 0, NON_CACHEABLE, { 0 } }, + +}; + void dp_prealloc_deinit(void) { int i; struct dp_consistent_prealloc *p; + struct dp_multi_page_prealloc *mp; qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); if (!qdf_ctx) { @@ -210,7 +304,7 @@ void dp_prealloc_deinit(void) p = &g_dp_consistent_allocs[i]; if (p->in_use) - dp_warn("i %d: in use while free", i); + dp_warn("i %d: consistent_mem in use while free", i); if (p->va_aligned) { dp_debug("i %d: va aligned %pK pa aligned %llx size %d", @@ -222,12 +316,31 @@ void dp_prealloc_deinit(void) qdf_mem_zero(p, sizeof(*p)); } } + + for (i = 0; i < QDF_ARRAY_SIZE(g_dp_multi_page_allocs); i++) { + mp = &g_dp_multi_page_allocs[i]; + + if (mp->in_use) + dp_warn("i %d: multi-page mem in use while free", i); + + if (mp->pages.num_pages) { + dp_info("i %d: type %d cacheable_pages %pK dma_pages %pK num_pages %d", + i, mp->desc_type, + mp->pages.cacheable_pages, + mp->pages.dma_pages, + mp->pages.num_pages); + qdf_mem_multi_pages_free(qdf_ctx, &mp->pages, + 0, mp->cacheable); + qdf_mem_zero(mp, sizeof(*mp)); + } + } } QDF_STATUS dp_prealloc_init(void) { int i; struct dp_consistent_prealloc *p; + struct dp_multi_page_prealloc *mp; qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); if (!qdf_ctx) { @@ -257,12 +370,39 @@ QDF_STATUS dp_prealloc_init(void) } if (i != QDF_ARRAY_SIZE(g_dp_consistent_allocs)) { - dp_err("unable to allocate memory!"); - dp_prealloc_deinit(); - return QDF_STATUS_E_FAILURE; + dp_err("unable to allocate consistent memory!"); + goto deinit; + } + + for (i = 0; i < QDF_ARRAY_SIZE(g_dp_multi_page_allocs); i++) { + mp = &g_dp_multi_page_allocs[i]; + mp->in_use = false; + qdf_mem_multi_pages_alloc(qdf_ctx, &mp->pages, + mp->element_size, + mp->element_num, + 0, mp->cacheable); + if (qdf_unlikely(!mp->pages.num_pages)) { + dp_warn("i %d: preallocate %d bytes multi-pages failed!", + i, (int)(mp->element_size * mp->element_num)); + break; + } + + mp->pages.is_mem_prealloc = true; + dp_info("i %d: cacheable_pages %pK dma_pages %pK num_pages %d", + i, mp->pages.cacheable_pages, + mp->pages.dma_pages, + mp->pages.num_pages); + } + + if (i != QDF_ARRAY_SIZE(g_dp_multi_page_allocs)) { + dp_err("unable to allocate multi-pages memory!"); + goto deinit; } return QDF_STATUS_SUCCESS; +deinit: + dp_prealloc_deinit(); + return QDF_STATUS_E_FAILURE; } void *dp_prealloc_get_coherent(uint32_t *size, void **base_vaddr_unaligned, @@ -318,4 +458,68 @@ void dp_prealloc_put_coherent(qdf_size_t size, void *vaddr_unligned, if (i == QDF_ARRAY_SIZE(g_dp_consistent_allocs)) dp_err("unable to find vaddr %pK", vaddr_unligned); } + +void dp_prealloc_get_multi_pages(uint32_t desc_type, + size_t element_size, + uint16_t element_num, + struct qdf_mem_multi_page_t *pages, + bool cacheable) +{ + int i; + struct dp_multi_page_prealloc *mp; + + for (i = 0; i < QDF_ARRAY_SIZE(g_dp_multi_page_allocs); i++) { + mp = &g_dp_multi_page_allocs[i]; + + if (desc_type == mp->desc_type && !mp->in_use && + mp->pages.num_pages && element_size == mp->element_size && + element_num <= mp->element_num) { + mp->in_use = true; + *pages = mp->pages; + + dp_info("i %d: desc_type %d cacheable_pages %pK" + "dma_pages %pK num_pages %d", + i, desc_type, + mp->pages.cacheable_pages, + mp->pages.dma_pages, + mp->pages.num_pages); + break; + } + } +} + +void dp_prealloc_put_multi_pages(uint32_t desc_type, + struct qdf_mem_multi_page_t *pages) +{ + int i; + struct dp_multi_page_prealloc *mp; + bool mp_found = false; + + for (i = 0; i < QDF_ARRAY_SIZE(g_dp_multi_page_allocs); i++) { + mp = &g_dp_multi_page_allocs[i]; + + if (desc_type == mp->desc_type) { + /* compare different address by cacheable flag */ + mp_found = mp->cacheable ? + (mp->pages.cacheable_pages == + pages->cacheable_pages) : + (mp->pages.dma_pages == pages->dma_pages); + /* find it, put back to prealloc pool */ + if (mp_found) { + dp_info("i %d: desc_type %d returned", + i, desc_type); + mp->in_use = false; + /* is page memory zero needed? */ + break; + } + } + } + + if (!mp_found) + dp_warn("Not prealloc pages %pK desc_type %d cacheable_pages %pK dma_pages %pK", + pages, + desc_type, + pages->cacheable_pages, + pages->dma_pages); +} #endif diff --git a/core/dp/txrx3.0/dp_txrx.h b/core/dp/txrx3.0/dp_txrx.h index 4a99a8debc20..ace61ee5ffa9 100644 --- a/core/dp/txrx3.0/dp_txrx.h +++ b/core/dp/txrx3.0/dp_txrx.h @@ -500,6 +500,33 @@ void *dp_prealloc_get_coherent(uint32_t *size, void **base_vaddr_unaligned, */ void dp_prealloc_put_coherent(qdf_size_t size, void *vaddr_unligned, qdf_dma_addr_t paddr); + +/** + * dp_prealloc_get_multi_page() - gets pre-alloc DP multi-pages memory + * @src_type: the source that do memory allocation + * @element_size: single element size + * @element_num: total number of elements should be allocated + * @pages: multi page information storage + * @cacheable: coherent memory or cacheable memory + * + * Return: None. + */ +void dp_prealloc_get_multi_pages(uint32_t src_type, + size_t element_size, + uint16_t element_num, + struct qdf_mem_multi_page_t *pages, + bool cacheable); + +/** + * dp_prealloc_put_multi_pages() - puts back pre-alloc DP multi-pages memory + * @src_type: the source that do memory freement + * @pages: multi page information storage + * + * Return: None + */ +void dp_prealloc_put_multi_pages(uint32_t src_type, + struct qdf_mem_multi_page_t *pages); + #else static inline QDF_STATUS dp_prealloc_init(void) { return QDF_STATUS_SUCCESS; }