From d4f5bd413d9526b608c11ec6818eb87e00f687e6 Mon Sep 17 00:00:00 2001 From: Jinwei Chen Date: Sun, 9 Aug 2020 22:24:33 -0700 Subject: [PATCH] qcacld-3.0: Support unaligned consistent memory prealloc Support unaligned consistent memory prealloc Change-Id: I5c4aea4991ab08519b821cb06c09e5abb9a90ef6 CRs-Fixed: 2758967 --- core/dp/txrx3.0/dp_txrx.c | 154 +++++++++++++++++++++++++++-- core/dp/txrx3.0/dp_txrx.h | 22 +++++ core/hdd/src/wlan_hdd_driver_ops.c | 53 ++++++++++ 3 files changed, 220 insertions(+), 9 deletions(-) diff --git a/core/dp/txrx3.0/dp_txrx.c b/core/dp/txrx3.0/dp_txrx.c index 936a943bd40d..2153e4c30a16 100644 --- a/core/dp/txrx3.0/dp_txrx.c +++ b/core/dp/txrx3.0/dp_txrx.c @@ -24,7 +24,8 @@ #include #include #include - +#include +#include QDF_STATUS dp_txrx_init(ol_txrx_soc_handle soc, uint8_t pdev_id, struct dp_txrx_config *config) @@ -193,6 +194,23 @@ struct dp_multi_page_prealloc { struct qdf_mem_multi_page_t pages; }; +/** + * struct dp_consistent_prealloc_unaligned - element representing DP pre-alloc + unaligned memory + * @ring_type: HAL ring type + * @size: size of pre-alloc memory + * @in_use: whether this element is in use (occupied) + * @va_unaligned: unaligned virtual address + * @pa_unaligned: unaligned physical address + */ +struct dp_consistent_prealloc_unaligned { + enum hal_ring_type ring_type; + uint32_t size; + bool in_use; + void *va_unaligned; + qdf_dma_addr_t pa_unaligned; +}; + 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}, @@ -270,7 +288,7 @@ static struct dp_multi_page_prealloc g_dp_multi_page_allocs[] = { {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 DESCs BUF 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 } }, @@ -288,11 +306,40 @@ static struct dp_multi_page_prealloc g_dp_multi_page_allocs[] = { }; +static struct dp_consistent_prealloc_unaligned + g_dp_consistent_unaligned_allocs[] = { + /* CE-0 */ + {CE_SRC, (sizeof(struct ce_srng_src_desc) * 16 + CE_DESC_RING_ALIGN), + false, NULL, 0}, + /* CE-1 */ + {CE_DST, (sizeof(struct ce_srng_dest_desc) * 512 + CE_DESC_RING_ALIGN), + false, NULL, 0}, + {CE_DST_STATUS, (sizeof(struct ce_srng_dest_status_desc) * 512 + + CE_DESC_RING_ALIGN), false, NULL, 0}, + /* CE-2 */ + {CE_DST, (sizeof(struct ce_srng_dest_desc) * 32 + CE_DESC_RING_ALIGN), + false, NULL, 0}, + {CE_DST_STATUS, (sizeof(struct ce_srng_dest_status_desc) * 32 + + CE_DESC_RING_ALIGN), false, NULL, 0}, + /* CE-3 */ + {CE_SRC, (sizeof(struct ce_srng_src_desc) * 32 + CE_DESC_RING_ALIGN), + false, NULL, 0}, + /* CE-4 */ + {CE_SRC, (sizeof(struct ce_srng_src_desc) * 256 + CE_DESC_RING_ALIGN), + false, NULL, 0}, + /* CE-5 */ + {CE_DST, (sizeof(struct ce_srng_dest_desc) * 512 + CE_DESC_RING_ALIGN), + false, NULL, 0}, + {CE_DST_STATUS, (sizeof(struct ce_srng_dest_status_desc) * 512 + + CE_DESC_RING_ALIGN), false, NULL, 0}, +}; + void dp_prealloc_deinit(void) { int i; struct dp_consistent_prealloc *p; struct dp_multi_page_prealloc *mp; + struct dp_consistent_prealloc_unaligned *up; qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); if (!qdf_ctx) { @@ -307,8 +354,9 @@ void dp_prealloc_deinit(void) 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", - i, p->va_aligned, p->pa_aligned, p->size); + dp_debug("i %d: va aligned %pK pa aligned %pK size %d", + i, p->va_aligned, (void *)p->pa_aligned, + p->size); qdf_mem_free_consistent(qdf_ctx, qdf_ctx->dev, p->size, p->va_unaligned, @@ -334,6 +382,24 @@ void dp_prealloc_deinit(void) qdf_mem_zero(mp, sizeof(*mp)); } } + + for (i = 0; i < QDF_ARRAY_SIZE(g_dp_consistent_unaligned_allocs); i++) { + up = &g_dp_consistent_unaligned_allocs[i]; + + if (qdf_unlikely(up->in_use)) + dp_info("i %d: unaligned mem in use while free", i); + + if (up->va_unaligned) { + dp_info("i %d: va unalign %pK pa unalign %pK size %d", + i, up->va_unaligned, + (void *)up->pa_unaligned, up->size); + qdf_mem_free_consistent(qdf_ctx, qdf_ctx->dev, + up->size, + up->va_unaligned, + up->pa_unaligned, 0); + qdf_mem_zero(up, sizeof(*up)); + } + } } QDF_STATUS dp_prealloc_init(void) @@ -341,6 +407,7 @@ QDF_STATUS dp_prealloc_init(void) int i; struct dp_consistent_prealloc *p; struct dp_multi_page_prealloc *mp; + struct dp_consistent_prealloc_unaligned *up; qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); if (!qdf_ctx) { @@ -359,14 +426,13 @@ QDF_STATUS dp_prealloc_init(void) &p->pa_unaligned, &p->pa_aligned, DP_RING_BASE_ALIGN); - if (!p->va_unaligned) { + if (qdf_unlikely(!p->va_unaligned)) { dp_warn("i %d: unable to preallocate %d bytes memory!", i, p->size); break; } - - dp_debug("i %d: va aligned %pK pa aligned %llx size %d", i, - p->va_aligned, p->pa_aligned, p->size); + dp_debug("i %d: va aligned %pK pa aligned %pK size %d", + i, p->va_aligned, (void *)p->pa_aligned, p->size); } if (i != QDF_ARRAY_SIZE(g_dp_consistent_allocs)) { @@ -399,6 +465,32 @@ QDF_STATUS dp_prealloc_init(void) goto deinit; } + for (i = 0; i < QDF_ARRAY_SIZE(g_dp_consistent_unaligned_allocs); i++) { + up = &g_dp_consistent_unaligned_allocs[i]; + up->in_use = 0; + up->va_unaligned = qdf_mem_alloc_consistent(qdf_ctx, + qdf_ctx->dev, + up->size, + &up->pa_unaligned); + if (qdf_unlikely(!up->va_unaligned)) { + dp_warn("i %d: fail to prealloc unaligned %d bytes!", + i, up->size); + break; + } + dp_info("i %d: va unalign %pK pa unalign %pK size %d", + i, up->va_unaligned, + (void *)up->pa_unaligned, up->size); + } + + if (i != QDF_ARRAY_SIZE(g_dp_consistent_unaligned_allocs)) { + dp_info("unable to allocate unaligned memory!"); + /* + * Only if unaligned memory prealloc fail, is deinit + * necessary for all other DP srng/multi-pages memory? + */ + goto deinit; + } + return QDF_STATUS_SUCCESS; deinit: dp_prealloc_deinit(); @@ -516,11 +608,55 @@ void dp_prealloc_put_multi_pages(uint32_t desc_type, } } - if (!mp_found) + if (qdf_unlikely(!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); } + +void *dp_prealloc_get_consistent_mem_unaligned(size_t size, + qdf_dma_addr_t *base_addr, + uint32_t ring_type) +{ + int i; + struct dp_consistent_prealloc_unaligned *up; + + for (i = 0; i < QDF_ARRAY_SIZE(g_dp_consistent_unaligned_allocs); i++) { + up = &g_dp_consistent_unaligned_allocs[i]; + + if (ring_type == up->ring_type && size == up->size && + up->va_unaligned && !up->in_use) { + up->in_use = true; + *base_addr = up->pa_unaligned; + dp_info("i %d: va unalign %pK pa unalign %pK size %d", + i, up->va_unaligned, + (void *)up->pa_unaligned, up->size); + return up->va_unaligned; + } + } + + return NULL; +} + +void dp_prealloc_put_consistent_mem_unaligned(void *va_unaligned) +{ + int i; + struct dp_consistent_prealloc_unaligned *up; + + for (i = 0; i < QDF_ARRAY_SIZE(g_dp_consistent_unaligned_allocs); i++) { + up = &g_dp_consistent_unaligned_allocs[i]; + + if (va_unaligned == up->va_unaligned) { + dp_info("index %d, returned", i); + up->in_use = false; + qdf_mem_zero(up->va_unaligned, up->size); + break; + } + } + + if (i == QDF_ARRAY_SIZE(g_dp_consistent_unaligned_allocs)) + dp_err("unable to find vaddr %pK", va_unaligned); +} #endif diff --git a/core/dp/txrx3.0/dp_txrx.h b/core/dp/txrx3.0/dp_txrx.h index ace61ee5ffa9..ed9c1df38df5 100644 --- a/core/dp/txrx3.0/dp_txrx.h +++ b/core/dp/txrx3.0/dp_txrx.h @@ -527,6 +527,28 @@ void dp_prealloc_get_multi_pages(uint32_t src_type, void dp_prealloc_put_multi_pages(uint32_t src_type, struct qdf_mem_multi_page_t *pages); +/** + * dp_prealloc_get_consistent_mem_unaligned() - gets pre-alloc unaligned + consistent memory + * @size: total memory size + * @base_addr: pointer to dma address + * @ring_type: HAL ring type that requires memory + * + * Return: memory virtual address pointer, NULL if fail + */ +void *dp_prealloc_get_consistent_mem_unaligned(size_t size, + qdf_dma_addr_t *base_addr, + uint32_t ring_type); + +/** + * dp_prealloc_put_consistent_mem_unaligned() - puts back pre-alloc unaligned + consistent memory + * @va_unaligned: memory virtual address pointer + * + * Return: None + */ +void dp_prealloc_put_consistent_mem_unaligned(void *va_unaligned); + #else static inline QDF_STATUS dp_prealloc_init(void) { return QDF_STATUS_SUCCESS; } diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 66164b000023..c5e786132e66 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -95,6 +95,55 @@ static int hdd_get_bandwidth_level(void *data) return ret; } +#ifdef DP_MEM_PRE_ALLOC + +/** + * hdd_get_consistent_mem_unaligned() - API to get consistent unaligned mem + * @size: Size of memory required + * @paddr: Pointer to paddr to be filled in by API + * @ring_type: Pointer to ring type for which consistent memory is needed + * + * Return: Virtual address of consistent memory on success, else null + */ +static +void *hdd_get_consistent_mem_unaligned(size_t size, + qdf_dma_addr_t *paddr, + uint32_t ring_type) +{ + return dp_prealloc_get_consistent_mem_unaligned(size, paddr, + ring_type); +} + +/** + * hdd_put_consistent_mem_unaligned() - API to put consistent unaligned mem + * @vaddr: Virtual address of memory + * + * Return: None + */ +static +void hdd_put_consistent_mem_unaligned(void *vaddr) +{ + dp_prealloc_put_consistent_mem_unaligned(vaddr); +} + +#else +static +void *hdd_get_consistent_mem_unaligned(size_t size, + qdf_dma_addr_t *paddr, + uint32_t ring_type) +{ + hdd_err_rl("prealloc not support!"); + + return NULL; +} + +static +void hdd_put_consistent_mem_unaligned(void *vaddr) +{ + hdd_err_rl("prealloc not support!"); +} +#endif + /** * hdd_set_recovery_in_progress() - API to set recovery in progress * @data: Context @@ -172,6 +221,10 @@ static void hdd_hif_init_driver_state_callbacks(void *data, cbk->is_driver_unloading = hdd_is_driver_unloading; cbk->is_target_ready = hdd_is_target_ready; cbk->get_bandwidth_level = hdd_get_bandwidth_level; + cbk->prealloc_get_consistent_mem_unaligned = + hdd_get_consistent_mem_unaligned; + cbk->prealloc_put_consistent_mem_unaligned = + hdd_put_consistent_mem_unaligned; } #ifdef FORCE_WAKE