diff --git a/dp/wifi3.0/be/dp_be.c b/dp/wifi3.0/be/dp_be.c index b318198c25..69f2635fb0 100644 --- a/dp/wifi3.0/be/dp_be.c +++ b/dp/wifi3.0/be/dp_be.c @@ -2693,6 +2693,8 @@ void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops) dp_tx_comp_get_params_from_hal_desc_be; arch_ops->dp_tx_process_htt_completion = dp_tx_process_htt_completion_be; + arch_ops->dp_tx_desc_pool_alloc = dp_tx_desc_pool_alloc_be; + arch_ops->dp_tx_desc_pool_free = dp_tx_desc_pool_free_be; arch_ops->dp_tx_desc_pool_init = dp_tx_desc_pool_init_be; arch_ops->dp_tx_desc_pool_deinit = dp_tx_desc_pool_deinit_be; arch_ops->dp_rx_desc_pool_init = dp_rx_desc_pool_init_be; diff --git a/dp/wifi3.0/be/dp_be_tx.c b/dp/wifi3.0/be/dp_be_tx.c index 4cba21c1b4..78ff5a147a 100644 --- a/dp/wifi3.0/be/dp_be_tx.c +++ b/dp/wifi3.0/be/dp_be_tx.c @@ -1844,3 +1844,13 @@ release_desc: return nbuf; } #endif + +QDF_STATUS dp_tx_desc_pool_alloc_be(struct dp_soc *soc, uint32_t num_elem, + uint8_t pool_id) +{ + return QDF_STATUS_SUCCESS; +} + +void dp_tx_desc_pool_free_be(struct dp_soc *soc, uint8_t pool_id) +{ +} diff --git a/dp/wifi3.0/be/dp_be_tx.h b/dp/wifi3.0/be/dp_be_tx.h index 6ac9d3e01c..dcc2159bdd 100644 --- a/dp/wifi3.0/be/dp_be_tx.h +++ b/dp/wifi3.0/be/dp_be_tx.h @@ -336,4 +336,24 @@ QDF_STATUS dp_tx_compute_tx_delay_be(struct dp_soc *soc, struct dp_vdev *vdev, struct hal_tx_completion_status *ts, uint32_t *delay_us); + +/** + * dp_tx_desc_pool_alloc_be() - Allocate TX descriptor pool + * @soc: Handle to DP Soc structure + * @num_elem: Number of elements to allocate + * @pool_id: TCL descriptor pool ID + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_tx_desc_pool_alloc_be(struct dp_soc *soc, uint32_t num_elem, + uint8_t pool_id); + +/** + * dp_tx_desc_pool_free_be() - Free TX descriptor pool + * @soc: Handle to DP Soc structure + * @pool_id: TCL descriptor pool ID + * + * Return: none + */ +void dp_tx_desc_pool_free_be(struct dp_soc *soc, uint8_t pool_id); #endif diff --git a/dp/wifi3.0/dp_tx_desc.c b/dp/wifi3.0/dp_tx_desc.c index ca348c8ef0..d3755c49f0 100644 --- a/dp/wifi3.0/dp_tx_desc.c +++ b/dp/wifi3.0/dp_tx_desc.c @@ -120,6 +120,7 @@ QDF_STATUS dp_tx_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, { uint32_t desc_size; struct dp_tx_desc_pool_s *tx_desc_pool; + QDF_STATUS status; desc_size = DP_TX_DESC_SIZE(sizeof(struct dp_tx_desc_s)); tx_desc_pool = &((soc)->tx_desc[(pool_id)]); @@ -133,6 +134,14 @@ QDF_STATUS dp_tx_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, dp_err("Multi page alloc fail, tx desc"); return QDF_STATUS_E_NOMEM; } + + /* Arch specific TX descriptor allocation */ + status = soc->arch_ops.dp_tx_desc_pool_alloc(soc, num_elem, pool_id); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("failed to allocate arch specific descriptors"); + return QDF_STATUS_E_NOMEM; + } + return QDF_STATUS_SUCCESS; } @@ -146,6 +155,9 @@ void dp_tx_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) dp_desc_multi_pages_mem_free(soc, DP_TX_DESC_TYPE, &tx_desc_pool->desc_pages, 0, true); + + /* Free arch specific TX descriptor */ + soc->arch_ops.dp_tx_desc_pool_free(soc, pool_id); } QDF_STATUS dp_tx_desc_pool_init(struct dp_soc *soc, uint8_t pool_id, diff --git a/dp/wifi3.0/dp_tx_desc.h b/dp/wifi3.0/dp_tx_desc.h index 7fd4a49536..028285ea9d 100644 --- a/dp/wifi3.0/dp_tx_desc.h +++ b/dp/wifi3.0/dp_tx_desc.h @@ -31,12 +31,23 @@ * 5 bits offset id 0 ~ 31 (Desc size = 128, Num descs per page = 4096/128 = 32) */ /* ???Ring ID needed??? */ + +/* TODO: Need to revisit this change for Rhine */ +#ifdef WLAN_SOFTUMAC_SUPPORT +#define DP_TX_DESC_ID_POOL_MASK 0x018000 +#define DP_TX_DESC_ID_POOL_OS 15 +#define DP_TX_DESC_ID_PAGE_MASK 0x007FF0 +#define DP_TX_DESC_ID_PAGE_OS 4 +#define DP_TX_DESC_ID_OFFSET_MASK 0x00000F +#define DP_TX_DESC_ID_OFFSET_OS 0 +#else #define DP_TX_DESC_ID_POOL_MASK 0x018000 #define DP_TX_DESC_ID_POOL_OS 15 #define DP_TX_DESC_ID_PAGE_MASK 0x007FE0 #define DP_TX_DESC_ID_PAGE_OS 5 #define DP_TX_DESC_ID_OFFSET_MASK 0x00001F #define DP_TX_DESC_ID_OFFSET_OS 0 +#endif /* WLAN_SOFTUMAC_SUPPORT */ /* * Compilation assert on tx desc size diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 738cf1c082..6e598150a6 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -518,6 +518,7 @@ enum dp_ctxt_type { * @DP_RX_DESC_STATUS_TYPE: DP RX SW descriptor for monitor status * @DP_HW_LINK_DESC_TYPE: DP HW link descriptor * @DP_HW_CC_SPT_PAGE_TYPE: DP pages for HW CC secondary page table + * @DP_TX_TCL_DESC_TYPE: DP TCL descriptor */ enum dp_desc_type { DP_TX_DESC_TYPE, @@ -530,6 +531,7 @@ enum dp_desc_type { DP_RX_DESC_STATUS_TYPE, DP_HW_LINK_DESC_TYPE, DP_HW_CC_SPT_PAGE_TYPE, + DP_TX_TCL_DESC_TYPE, }; /** @@ -638,6 +640,8 @@ struct dp_tx_ext_desc_pool_s { * @msdu_ext_desc: MSDU extension descriptor * @timestamp: * @comp: + * @tcl_cmd_vaddr: VADDR of the TCL descriptor, valid for soft-umac arch + * @tcl_cmd_paddr: PADDR of the TCL descriptor, valid for soft-umac arch */ struct dp_tx_desc_s { struct dp_tx_desc_s *next; @@ -664,6 +668,10 @@ struct dp_tx_desc_s { struct dp_tx_ext_desc_elem_s *msdu_ext_desc; qdf_ktime_t timestamp; struct hal_tx_desc_comp_s comp; +#ifdef WLAN_SOFTUMAC_SUPPORT + void *tcl_cmd_vaddr; + qdf_dma_addr_t tcl_cmd_paddr; +#endif }; #ifdef QCA_AC_BASED_FLOW_CONTROL @@ -2205,6 +2213,8 @@ enum dp_context_type { * @dp_free_ppeds_interrupts: * @dp_rx_wbm_err_reap_desc: Reap WBM Error Ring Descriptor * @dp_rx_null_q_desc_handle: Handle Null Queue Exception Error + * @dp_tx_desc_pool_alloc: Allocate arch specific TX descriptor pool + * @dp_tx_desc_pool_free: Free arch specific TX descriptor pool */ struct dp_arch_ops { /* INIT/DEINIT Arch Ops */ @@ -2433,6 +2443,11 @@ struct dp_arch_ops { struct dp_txrx_peer *txrx_peer, bool is_reo_exception, uint8_t link_id); + + QDF_STATUS (*dp_tx_desc_pool_alloc)(struct dp_soc *soc, + uint32_t num_elem, + uint8_t pool_id); + void (*dp_tx_desc_pool_free)(struct dp_soc *soc, uint8_t pool_id); }; /** diff --git a/dp/wifi3.0/li/dp_li.c b/dp/wifi3.0/li/dp_li.c index c91f3e19f3..37b6635d89 100644 --- a/dp/wifi3.0/li/dp_li.c +++ b/dp/wifi3.0/li/dp_li.c @@ -613,6 +613,8 @@ void dp_initialize_arch_ops_li(struct dp_arch_ops *arch_ops) dp_tx_process_htt_completion_li; arch_ops->dp_wbm_get_rx_desc_from_hal_desc = dp_wbm_get_rx_desc_from_hal_desc_li; + arch_ops->dp_tx_desc_pool_alloc = dp_tx_desc_pool_alloc_li; + arch_ops->dp_tx_desc_pool_free = dp_tx_desc_pool_free_li; arch_ops->dp_tx_desc_pool_init = dp_tx_desc_pool_init_li; arch_ops->dp_tx_desc_pool_deinit = dp_tx_desc_pool_deinit_li; arch_ops->dp_rx_desc_pool_init = dp_rx_desc_pool_init_li; diff --git a/dp/wifi3.0/li/dp_li_tx.c b/dp/wifi3.0/li/dp_li_tx.c index c32849d389..e7671135ed 100644 --- a/dp/wifi3.0/li/dp_li_tx.c +++ b/dp/wifi3.0/li/dp_li_tx.c @@ -603,3 +603,13 @@ QDF_STATUS dp_tx_compute_tx_delay_li(struct dp_soc *soc, { return dp_tx_compute_hw_delay_li(soc, vdev, ts, delay_us); } + +QDF_STATUS dp_tx_desc_pool_alloc_li(struct dp_soc *soc, uint32_t num_elem, + uint8_t pool_id) +{ + return QDF_STATUS_SUCCESS; +} + +void dp_tx_desc_pool_free_li(struct dp_soc *soc, uint8_t pool_id) +{ +} diff --git a/dp/wifi3.0/li/dp_li_tx.h b/dp/wifi3.0/li/dp_li_tx.h index 4e74e8474b..2191dcd8f1 100644 --- a/dp/wifi3.0/li/dp_li_tx.h +++ b/dp/wifi3.0/li/dp_li_tx.h @@ -106,4 +106,24 @@ QDF_STATUS dp_tx_compute_tx_delay_li(struct dp_soc *soc, struct dp_vdev *vdev, struct hal_tx_completion_status *ts, uint32_t *delay_us); + +/** + * dp_tx_desc_pool_alloc_li() - Allocate TX descriptor pool + * @soc: Handle to DP Soc structure + * @num_elem: Number of elements to allocate + * @pool_id: TCL descriptor pool ID + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_tx_desc_pool_alloc_li(struct dp_soc *soc, uint32_t num_elem, + uint8_t pool_id); + +/** + * dp_tx_desc_pool_free_li() - Free TX descriptor pool + * @soc: Handle to DP Soc structure + * @pool_id: TCL descriptor pool ID + * + * Return: none + */ +void dp_tx_desc_pool_free_li(struct dp_soc *soc, uint8_t pool_id); #endif diff --git a/dp/wifi3.0/rh/dp_rh.c b/dp/wifi3.0/rh/dp_rh.c index 1f8db41190..e8802aea50 100644 --- a/dp/wifi3.0/rh/dp_rh.c +++ b/dp/wifi3.0/rh/dp_rh.c @@ -415,6 +415,8 @@ void dp_initialize_arch_ops_rh(struct dp_arch_ops *arch_ops) dp_tx_process_htt_completion_rh; arch_ops->dp_wbm_get_rx_desc_from_hal_desc = dp_wbm_get_rx_desc_from_hal_desc_rh; + arch_ops->dp_tx_desc_pool_alloc = dp_tx_desc_pool_alloc_rh; + arch_ops->dp_tx_desc_pool_free = dp_tx_desc_pool_free_rh; arch_ops->dp_tx_desc_pool_init = dp_tx_desc_pool_init_rh; arch_ops->dp_tx_desc_pool_deinit = dp_tx_desc_pool_deinit_rh; arch_ops->dp_rx_desc_pool_init = dp_rx_desc_pool_init_rh; diff --git a/dp/wifi3.0/rh/dp_rh.h b/dp/wifi3.0/rh/dp_rh.h index abbdf4ae13..b72015f01d 100644 --- a/dp/wifi3.0/rh/dp_rh.h +++ b/dp/wifi3.0/rh/dp_rh.h @@ -23,13 +23,16 @@ #include #include #include +#include "dp_rh_tx.h" /** * struct dp_soc_rh - Extended DP soc for RH targets * @soc: dp soc structure + * @tcl_desc_pool: A pool of TCL descriptors that are allocated for RH targets */ struct dp_soc_rh { struct dp_soc soc; + struct dp_tx_tcl_desc_pool_s tcl_desc_pool[MAX_TXDESC_POOLS]; }; /** @@ -105,4 +108,14 @@ qdf_size_t dp_get_context_size_rh(enum dp_context_type context_type); qdf_size_t dp_mon_get_context_size_rh(enum dp_context_type context_type); +/** + * dp_get_rh_soc_from_dp_soc() - get dp_soc_rh from dp_soc + * @soc: dp_soc pointer + * + * Return: dp_soc_rh pointer + */ +static inline struct dp_soc_rh *dp_get_rh_soc_from_dp_soc(struct dp_soc *soc) +{ + return (struct dp_soc_rh *)soc; +} #endif diff --git a/dp/wifi3.0/rh/dp_rh_tx.c b/dp/wifi3.0/rh/dp_rh_tx.c index 98d6760294..52450d2fd9 100644 --- a/dp/wifi3.0/rh/dp_rh_tx.c +++ b/dp/wifi3.0/rh/dp_rh_tx.c @@ -54,16 +54,193 @@ dp_tx_hw_enqueue_rh(struct dp_soc *soc, struct dp_vdev *vdev, return QDF_STATUS_SUCCESS; } +/** + * dp_tx_tcl_desc_pool_alloc_rh() - Allocate the tcl descriptor pool + * based on pool_id + * @soc: Handle to DP SoC structure + * @num_elem: Number of descriptor elements per pool + * @pool_id: Pool to allocate + * + * Return: QDF_STATUS_SUCCESS + * QDF_STATUS_E_NOMEM + */ +static QDF_STATUS +dp_tx_tcl_desc_pool_alloc_rh(struct dp_soc *soc, uint32_t num_elem, + uint8_t pool_id) +{ + struct dp_soc_rh *rh_soc = dp_get_rh_soc_from_dp_soc(soc); + struct dp_tx_tcl_desc_pool_s *tcl_desc_pool; + uint16_t elem_size = DP_RH_TX_TCL_DESC_SIZE; + QDF_STATUS status = QDF_STATUS_SUCCESS; + qdf_dma_context_t memctx = 0; + + if (pool_id > MAX_TXDESC_POOLS - 1) + return QDF_STATUS_E_INVAL; + + /* Allocate tcl descriptors in coherent memory */ + tcl_desc_pool = &rh_soc->tcl_desc_pool[pool_id]; + memctx = qdf_get_dma_mem_context(tcl_desc_pool, memctx); + dp_desc_multi_pages_mem_alloc(soc, DP_TX_TCL_DESC_TYPE, + &tcl_desc_pool->desc_pages, + elem_size, num_elem, memctx, false); + + if (!tcl_desc_pool->desc_pages.num_pages) { + dp_err("failed to allocate tcl desc Pages"); + status = QDF_STATUS_E_NOMEM; + goto err_alloc_fail; + } + + return status; + +err_alloc_fail: + dp_desc_multi_pages_mem_free(soc, DP_TX_TCL_DESC_TYPE, + &tcl_desc_pool->desc_pages, + memctx, false); + return status; +} + +/** + * dp_tx_tcl_desc_pool_free_rh() - Free the tcl descriptor pool + * @soc: Handle to DP SoC structure + * @pool_id: pool to free + * + */ +static void dp_tx_tcl_desc_pool_free_rh(struct dp_soc *soc, uint8_t pool_id) +{ + struct dp_soc_rh *rh_soc = dp_get_rh_soc_from_dp_soc(soc); + struct dp_tx_tcl_desc_pool_s *tcl_desc_pool; + qdf_dma_context_t memctx = 0; + + if (pool_id > MAX_TXDESC_POOLS - 1) + return; + + tcl_desc_pool = &rh_soc->tcl_desc_pool[pool_id]; + memctx = qdf_get_dma_mem_context(tcl_desc_pool, memctx); + + dp_desc_multi_pages_mem_free(soc, DP_TX_TCL_DESC_TYPE, + &tcl_desc_pool->desc_pages, + memctx, false); +} + +/** + * dp_tx_tcl_desc_pool_init_rh() - Initialize tcl descriptor pool + * based on pool_id + * @soc: Handle to DP SoC structure + * @num_elem: Number of descriptor elements per pool + * @pool_id: pool to initialize + * + * Return: QDF_STATUS_SUCCESS + * QDF_STATUS_E_FAULT + */ +static QDF_STATUS +dp_tx_tcl_desc_pool_init_rh(struct dp_soc *soc, uint32_t num_elem, + uint8_t pool_id) +{ + struct dp_soc_rh *rh_soc = dp_get_rh_soc_from_dp_soc(soc); + struct dp_tx_tcl_desc_pool_s *tcl_desc_pool; + struct qdf_mem_dma_page_t *page_info; + QDF_STATUS status; + + tcl_desc_pool = &rh_soc->tcl_desc_pool[pool_id]; + tcl_desc_pool->elem_size = DP_RH_TX_TCL_DESC_SIZE; + tcl_desc_pool->elem_count = num_elem; + + /* Link tcl descriptors into a freelist */ + if (qdf_mem_multi_page_link(soc->osdev, &tcl_desc_pool->desc_pages, + tcl_desc_pool->elem_size, + tcl_desc_pool->elem_count, + false)) { + dp_err("failed to link tcl desc Pages"); + status = QDF_STATUS_E_FAULT; + goto err_link_fail; + } + + page_info = tcl_desc_pool->desc_pages.dma_pages; + tcl_desc_pool->freelist = (uint32_t *)page_info->page_v_addr_start; + + return QDF_STATUS_SUCCESS; + +err_link_fail: + return status; +} + +/** + * dp_tx_tcl_desc_pool_deinit_rh() - De-initialize tcl descriptor pool + * based on pool_id + * @soc: Handle to DP SoC structure + * @pool_id: pool to de-initialize + * + */ +static void dp_tx_tcl_desc_pool_deinit_rh(struct dp_soc *soc, uint8_t pool_id) +{ +} + +/** + * dp_tx_alloc_tcl_desc_rh() - Allocate a tcl descriptor from the pool + * @tcl_desc_pool: Tcl descriptor pool + * @tx_desc: SW TX descriptor + * @index: Index into the tcl descriptor pool + */ +static void dp_tx_alloc_tcl_desc_rh(struct dp_tx_tcl_desc_pool_s *tcl_desc_pool, + struct dp_tx_desc_s *tx_desc, + uint32_t index) +{ + struct qdf_mem_dma_page_t *dma_page; + uint32_t page_id; + uint32_t offset; + + tx_desc->tcl_cmd_vaddr = (void *)tcl_desc_pool->freelist; + + if (tcl_desc_pool->freelist) + tcl_desc_pool->freelist = + *((uint32_t **)tcl_desc_pool->freelist); + + page_id = index / tcl_desc_pool->desc_pages.num_element_per_page; + offset = index % tcl_desc_pool->desc_pages.num_element_per_page; + dma_page = &tcl_desc_pool->desc_pages.dma_pages[page_id]; + + tx_desc->tcl_cmd_paddr = + dma_page->page_p_addr + offset * tcl_desc_pool->elem_size; +} + QDF_STATUS dp_tx_desc_pool_init_rh(struct dp_soc *soc, uint32_t num_elem, uint8_t pool_id) { + struct dp_soc_rh *rh_soc = dp_get_rh_soc_from_dp_soc(soc); uint32_t id, count, page_id, offset, pool_id_32; struct dp_tx_desc_s *tx_desc; + struct dp_tx_tcl_desc_pool_s *tcl_desc_pool; struct dp_tx_desc_pool_s *tx_desc_pool; uint16_t num_desc_per_page; + QDF_STATUS status; + + status = dp_tx_tcl_desc_pool_init_rh(soc, num_elem, pool_id); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("failed to initialise tcl desc pool %d", pool_id); + goto err_out; + } + + status = dp_tx_ext_desc_pool_init_by_id(soc, num_elem, pool_id); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("failed to initialise tx ext desc pool %d", pool_id); + goto err_deinit_tcl_pool; + } + + status = dp_tx_tso_desc_pool_init_by_id(soc, num_elem, pool_id); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("failed to initialise tso desc pool %d", pool_id); + goto err_deinit_tx_ext_pool; + } + + status = dp_tx_tso_num_seg_pool_init_by_id(soc, num_elem, pool_id); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("failed to initialise tso num seg pool %d", pool_id); + goto err_deinit_tso_pool; + } tx_desc_pool = &soc->tx_desc[pool_id]; + tcl_desc_pool = &rh_soc->tcl_desc_pool[pool_id]; tx_desc = tx_desc_pool->freelist; count = 0; pool_id_32 = (uint32_t)pool_id; @@ -77,17 +254,33 @@ QDF_STATUS dp_tx_desc_pool_init_rh(struct dp_soc *soc, tx_desc->id = id; tx_desc->pool_id = pool_id; dp_tx_desc_set_magic(tx_desc, DP_TX_MAGIC_PATTERN_FREE); + dp_tx_alloc_tcl_desc_rh(tcl_desc_pool, tx_desc, count); tx_desc = tx_desc->next; count++; } return QDF_STATUS_SUCCESS; + +err_deinit_tso_pool: + dp_tx_tso_desc_pool_deinit_by_id(soc, pool_id); +err_deinit_tx_ext_pool: + dp_tx_ext_desc_pool_deinit_by_id(soc, pool_id); +err_deinit_tcl_pool: + dp_tx_tcl_desc_pool_deinit_rh(soc, pool_id); +err_out: + /* TODO: is assert needed ? */ + qdf_assert_always(0); + return status; } void dp_tx_desc_pool_deinit_rh(struct dp_soc *soc, struct dp_tx_desc_pool_s *tx_desc_pool, uint8_t pool_id) { + dp_tx_tso_num_seg_pool_free_by_id(soc, pool_id); + dp_tx_tso_desc_pool_deinit_by_id(soc, pool_id); + dp_tx_ext_desc_pool_deinit_by_id(soc, pool_id); + dp_tx_tcl_desc_pool_deinit_rh(soc, pool_id); } QDF_STATUS dp_tx_compute_tx_delay_rh(struct dp_soc *soc, @@ -97,3 +290,54 @@ QDF_STATUS dp_tx_compute_tx_delay_rh(struct dp_soc *soc, { return QDF_STATUS_SUCCESS; } + +QDF_STATUS dp_tx_desc_pool_alloc_rh(struct dp_soc *soc, uint32_t num_elem, + uint8_t pool_id) +{ + QDF_STATUS status; + + status = dp_tx_tcl_desc_pool_alloc_rh(soc, num_elem, pool_id); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("failed to allocate tcl desc pool %d\n", pool_id); + goto err_tcl_desc_pool; + } + + status = dp_tx_ext_desc_pool_alloc_by_id(soc, num_elem, pool_id); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("failed to allocate tx ext desc pool %d\n", pool_id); + goto err_free_tcl_pool; + } + + status = dp_tx_tso_desc_pool_alloc_by_id(soc, num_elem, pool_id); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("failed to allocate tso desc pool %d\n", pool_id); + goto err_free_tx_ext_pool; + } + + status = dp_tx_tso_num_seg_pool_alloc_by_id(soc, num_elem, pool_id); + if (QDF_IS_STATUS_ERROR(status)) { + dp_err("failed to allocate tso num seg pool %d\n", pool_id); + goto err_free_tso_pool; + } + + return status; + +err_free_tso_pool: + dp_tx_tso_desc_pool_free_by_id(soc, pool_id); +err_free_tx_ext_pool: + dp_tx_ext_desc_pool_free_by_id(soc, pool_id); +err_free_tcl_pool: + dp_tx_tcl_desc_pool_free_rh(soc, pool_id); +err_tcl_desc_pool: + /* TODO: is assert needed ? */ + qdf_assert_always(0); + return status; +} + +void dp_tx_desc_pool_free_rh(struct dp_soc *soc, uint8_t pool_id) +{ + dp_tx_tso_num_seg_pool_free_by_id(soc, pool_id); + dp_tx_tso_desc_pool_free_by_id(soc, pool_id); + dp_tx_ext_desc_pool_free_by_id(soc, pool_id); + dp_tx_tcl_desc_pool_free_rh(soc, pool_id); +} diff --git a/dp/wifi3.0/rh/dp_rh_tx.h b/dp/wifi3.0/rh/dp_rh_tx.h index 1f033374c5..bb7d49d696 100644 --- a/dp/wifi3.0/rh/dp_rh_tx.h +++ b/dp/wifi3.0/rh/dp_rh_tx.h @@ -20,6 +20,27 @@ #include +#define DP_RH_TX_TLV_HDR_SIZE sizeof(struct tlv_32_hdr) +#define DP_RH_TX_TCL_DESC_SIZE (HAL_TX_DESC_LEN_BYTES + DP_RH_TX_TLV_HDR_SIZE) + +/* + * NB: intentionally not using kernel-doc comment because the kernel-doc + * script does not handle the qdf_dma_mem_context macro + * struct dp_tx_tcl_desc_pool_s - Tx Extension Descriptor Pool + * @elem_count: Number of descriptors in the pool + * @elem_size: Size of each descriptor + * @desc_pages: multiple page allocation information for actual descriptors + * @freelist: freelist of TCL descriptors + * @memctx: + */ +struct dp_tx_tcl_desc_pool_s { + uint16_t elem_count; + int elem_size; + struct qdf_mem_multi_page_t desc_pages; + uint32_t *freelist; + qdf_dma_mem_context(memctx); +}; + /** * dp_tx_hw_enqueue_rh() - Enqueue to TCL HW for transmit * @soc: DP Soc Handle @@ -105,4 +126,24 @@ QDF_STATUS dp_tx_compute_tx_delay_rh(struct dp_soc *soc, struct dp_vdev *vdev, struct hal_tx_completion_status *ts, uint32_t *delay_us); + +/** + * dp_tx_desc_pool_alloc_rh() - Allocate coherent memory for TCL descriptors + * @soc: Handle to DP Soc structure + * @num_elem: Number of elements to allocate + * @pool_id: TCL descriptor pool ID + * + * Return: QDF_STATUS_SUCCESS - success, others - failure + */ +QDF_STATUS dp_tx_desc_pool_alloc_rh(struct dp_soc *soc, uint32_t num_elem, + uint8_t pool_id); + +/** + * dp_tx_desc_pool_free_rh() - Free TCL descriptor memory + * @soc: Handle to DP Soc structure + * @pool_id: TCL descriptor pool ID + * + * Return: none + */ +void dp_tx_desc_pool_free_rh(struct dp_soc *soc, uint8_t pool_id); #endif