|
@@ -21,6 +21,7 @@
|
|
|
#include "dp_be.h"
|
|
|
#include "dp_be_tx.h"
|
|
|
#include "dp_be_rx.h"
|
|
|
+#include <hal_be_api.h>
|
|
|
|
|
|
qdf_size_t dp_get_context_size_be(enum dp_context_type context_type)
|
|
|
{
|
|
@@ -38,6 +39,263 @@ qdf_size_t dp_get_context_size_be(enum dp_context_type context_type)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static QDF_STATUS dp_hw_cookie_conversion_attach(struct dp_soc_be *be_soc)
|
|
|
+{
|
|
|
+ struct dp_soc *soc = &be_soc->soc;
|
|
|
+ struct dp_hw_cookie_conversion_t *cc_ctx = &be_soc->hw_cc_ctx;
|
|
|
+ uint32_t max_tx_rx_desc_num, num_spt_pages, i = 0;
|
|
|
+ struct dp_spt_page_desc *page_desc_elem;
|
|
|
+ struct qdf_mem_dma_page_t *dma_page;
|
|
|
+
|
|
|
+ /* get CMEM for cookie conversion */
|
|
|
+ if (soc->cmem_size < DP_CC_PPT_MEM_SIZE) {
|
|
|
+ dp_err("cmem_size %llu bytes < 4K", soc->cmem_size);
|
|
|
+ return QDF_STATUS_E_RESOURCES;
|
|
|
+ }
|
|
|
+ cc_ctx->cmem_base = (uint32_t)(soc->cmem_base +
|
|
|
+ DP_CC_MEM_OFFSET_IN_CMEM);
|
|
|
+
|
|
|
+ /* estimate how many SPT DDR pages needed */
|
|
|
+ max_tx_rx_desc_num = WLAN_CFG_NUM_TX_DESC_MAX * MAX_TXDESC_POOLS +
|
|
|
+ WLAN_CFG_RX_SW_DESC_NUM_SIZE_MAX * MAX_RXDESC_POOLS;
|
|
|
+ num_spt_pages = max_tx_rx_desc_num / DP_CC_SPT_PAGE_MAX_ENTRIES;
|
|
|
+ num_spt_pages = num_spt_pages <= DP_CC_PPT_MAX_ENTRIES ?
|
|
|
+ num_spt_pages : DP_CC_PPT_MAX_ENTRIES;
|
|
|
+ dp_info("num_spt_pages needed %d", num_spt_pages);
|
|
|
+
|
|
|
+ dp_desc_multi_pages_mem_alloc(soc, DP_HW_CC_SPT_PAGE_TYPE,
|
|
|
+ &cc_ctx->page_pool, qdf_page_size,
|
|
|
+ num_spt_pages, 0, false);
|
|
|
+ if (!cc_ctx->page_pool.dma_pages) {
|
|
|
+ dp_err("spt ddr pages allocation failed");
|
|
|
+ return QDF_STATUS_E_RESOURCES;
|
|
|
+ }
|
|
|
+ cc_ctx->page_desc_base = qdf_mem_malloc(
|
|
|
+ num_spt_pages * sizeof(struct dp_spt_page_desc));
|
|
|
+ if (!cc_ctx->page_desc_base) {
|
|
|
+ dp_err("spt page descs allocation failed");
|
|
|
+ goto fail_0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* initial page desc */
|
|
|
+ page_desc_elem = cc_ctx->page_desc_base;
|
|
|
+ dma_page = cc_ctx->page_pool.dma_pages;
|
|
|
+ while (i < num_spt_pages) {
|
|
|
+ /* check if page address 4K aligned */
|
|
|
+ if (qdf_unlikely(dma_page[i].page_p_addr & 0xFFF)) {
|
|
|
+ dp_err("non-4k aligned pages addr %pK",
|
|
|
+ (void *)dma_page[i].page_p_addr);
|
|
|
+ goto fail_1;
|
|
|
+ }
|
|
|
+
|
|
|
+ page_desc_elem[i].page_v_addr =
|
|
|
+ dma_page[i].page_v_addr_start;
|
|
|
+ page_desc_elem[i].page_p_addr =
|
|
|
+ dma_page[i].page_p_addr;
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+
|
|
|
+ cc_ctx->total_page_num = num_spt_pages;
|
|
|
+ qdf_spinlock_create(&cc_ctx->cc_lock);
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+fail_1:
|
|
|
+ qdf_mem_free(cc_ctx->page_desc_base);
|
|
|
+fail_0:
|
|
|
+ dp_desc_multi_pages_mem_free(soc, DP_HW_CC_SPT_PAGE_TYPE,
|
|
|
+ &cc_ctx->page_pool, 0, false);
|
|
|
+
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+}
|
|
|
+
|
|
|
+static QDF_STATUS dp_hw_cookie_conversion_detach(struct dp_soc_be *be_soc)
|
|
|
+{
|
|
|
+ struct dp_soc *soc = &be_soc->soc;
|
|
|
+ struct dp_hw_cookie_conversion_t *cc_ctx = &be_soc->hw_cc_ctx;
|
|
|
+
|
|
|
+ qdf_mem_free(cc_ctx->page_desc_base);
|
|
|
+ dp_desc_multi_pages_mem_free(soc, DP_HW_CC_SPT_PAGE_TYPE,
|
|
|
+ &cc_ctx->page_pool, 0, false);
|
|
|
+ qdf_spinlock_destroy(&cc_ctx->cc_lock);
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef DP_FEATURE_HW_COOKIE_CONVERSION
|
|
|
+/**
|
|
|
+ * dp_cc_reg_cfg_init() - initialize and configure HW cookie
|
|
|
+ conversion register
|
|
|
+ * @soc: SOC handle
|
|
|
+ * @cc_ctx: cookie conversion context pointer
|
|
|
+ * @is_4k_align: page address 4k alignd
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static void dp_cc_reg_cfg_init(struct dp_soc *soc,
|
|
|
+ struct dp_hw_cookie_conversion_t *cc_ctx,
|
|
|
+ bool is_4k_align)
|
|
|
+{
|
|
|
+ struct hal_hw_cc_config cc_cfg = { 0 };
|
|
|
+
|
|
|
+ cc_cfg.lut_base_addr_31_0 = cc_ctx->cmem_base;
|
|
|
+ cc_cfg.cc_global_en = soc->wlan_cfg_ctx->hw_cc_enabled;
|
|
|
+ cc_cfg.page_4k_align = is_4k_align;
|
|
|
+ cc_cfg.cookie_offset_msb = DP_CC_DESC_ID_SPT_VA_OS_MSB;
|
|
|
+ cc_cfg.cookie_page_msb = is_4k_align ?
|
|
|
+ DP_CC_DESC_ID_PPT_PAGE_OS_4K_ALIGNED_MSB :
|
|
|
+ DP_CC_DESC_ID_PPT_PAGE_OS_4K_UNALIGNED_MSB;
|
|
|
+ /* 36th bit should be 1 then HW know this is CMEM address */
|
|
|
+ cc_cfg.lut_base_addr_39_32 = 0x10;
|
|
|
+
|
|
|
+ cc_cfg.wbm2sw6_cc_en = 1;
|
|
|
+ cc_cfg.wbm2sw5_cc_en = 1;
|
|
|
+ cc_cfg.wbm2sw4_cc_en = 1;
|
|
|
+ cc_cfg.wbm2sw3_cc_en = 1;
|
|
|
+ cc_cfg.wbm2sw2_cc_en = 1;
|
|
|
+ cc_cfg.wbm2sw1_cc_en = 1;
|
|
|
+ cc_cfg.wbm2sw0_cc_en = 1;
|
|
|
+ cc_cfg.wbm2fw_cc_en = 0;
|
|
|
+
|
|
|
+ hal_cookie_conversion_reg_cfg_be(soc->hal_soc, &cc_cfg);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_hw_cc_cmem_write() - DP wrapper function for CMEM buffer writing
|
|
|
+ * @hal_soc_hdl: HAL SOC handle
|
|
|
+ * @offset: CMEM address
|
|
|
+ * @value: value to write
|
|
|
+ *
|
|
|
+ * Return: None.
|
|
|
+ */
|
|
|
+static inline void dp_hw_cc_cmem_write(hal_soc_handle_t hal_soc_hdl,
|
|
|
+ uint32_t offset,
|
|
|
+ uint32_t value)
|
|
|
+{
|
|
|
+ hal_cmem_write(hal_soc_hdl, offset, value);
|
|
|
+}
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+static inline void dp_cc_reg_cfg_init(struct dp_soc *soc,
|
|
|
+ struct dp_hw_cookie_conversion_t *cc_ctx,
|
|
|
+ bool is_4k_align) {}
|
|
|
+
|
|
|
+static inline void dp_hw_cc_cmem_write(hal_soc_handle_t hal_soc_hdl,
|
|
|
+ uint32_t offset,
|
|
|
+ uint32_t value)
|
|
|
+{ }
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+static QDF_STATUS dp_hw_cookie_conversion_init(struct dp_soc_be *be_soc)
|
|
|
+{
|
|
|
+ struct dp_soc *soc = &be_soc->soc;
|
|
|
+ struct dp_hw_cookie_conversion_t *cc_ctx = &be_soc->hw_cc_ctx;
|
|
|
+ uint32_t i = 0;
|
|
|
+ struct dp_spt_page_desc *page_desc_elem;
|
|
|
+
|
|
|
+ if (!cc_ctx->total_page_num) {
|
|
|
+ dp_err("total page num is 0");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ page_desc_elem = cc_ctx->page_desc_base;
|
|
|
+ while (i < cc_ctx->total_page_num) {
|
|
|
+ /* write page PA to CMEM */
|
|
|
+ dp_hw_cc_cmem_write(soc->hal_soc,
|
|
|
+ (cc_ctx->cmem_base +
|
|
|
+ i * DP_CC_PPT_ENTRY_SIZE_4K_ALIGNED),
|
|
|
+ (page_desc_elem[i].page_p_addr >>
|
|
|
+ DP_CC_PPT_ENTRY_HW_APEND_BITS_4K_ALIGNED));
|
|
|
+
|
|
|
+ page_desc_elem[i].ppt_index = i;
|
|
|
+ page_desc_elem[i].avail_entry_index = 0;
|
|
|
+ /* link page desc */
|
|
|
+ if ((i + 1) != cc_ctx->total_page_num)
|
|
|
+ page_desc_elem[i].next = &page_desc_elem[i + 1];
|
|
|
+ else
|
|
|
+ page_desc_elem[i].next = NULL;
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+
|
|
|
+ cc_ctx->page_desc_freelist = cc_ctx->page_desc_base;
|
|
|
+ cc_ctx->free_page_num = cc_ctx->total_page_num;
|
|
|
+
|
|
|
+ /* write WBM/REO cookie conversion CFG register */
|
|
|
+ dp_cc_reg_cfg_init(soc, cc_ctx, true);
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static QDF_STATUS dp_hw_cookie_conversion_deinit(struct dp_soc_be *be_soc)
|
|
|
+{
|
|
|
+ struct dp_hw_cookie_conversion_t *cc_ctx = &be_soc->hw_cc_ctx;
|
|
|
+
|
|
|
+ cc_ctx->page_desc_freelist = NULL;
|
|
|
+ cc_ctx->free_page_num = 0;
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+uint16_t dp_cc_spt_page_desc_alloc(struct dp_soc_be *be_soc,
|
|
|
+ struct dp_spt_page_desc **list_head,
|
|
|
+ struct dp_spt_page_desc **list_tail,
|
|
|
+ uint16_t desc_num)
|
|
|
+{
|
|
|
+ uint16_t num_pages, count;
|
|
|
+ struct dp_hw_cookie_conversion_t *cc_ctx = &be_soc->hw_cc_ctx;
|
|
|
+
|
|
|
+ num_pages = (desc_num / DP_CC_SPT_PAGE_MAX_ENTRIES) +
|
|
|
+ (desc_num % DP_CC_SPT_PAGE_MAX_ENTRIES ? 1 : 0);
|
|
|
+
|
|
|
+ if (num_pages > cc_ctx->free_page_num) {
|
|
|
+ dp_err("fail: num_pages required %d > free_page_num %d",
|
|
|
+ num_pages,
|
|
|
+ cc_ctx->free_page_num);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ qdf_spin_lock_bh(&cc_ctx->cc_lock);
|
|
|
+
|
|
|
+ *list_head = *list_tail = cc_ctx->page_desc_freelist;
|
|
|
+ for (count = 0; count < num_pages; count++) {
|
|
|
+ if (qdf_unlikely(!cc_ctx->page_desc_freelist)) {
|
|
|
+ cc_ctx->page_desc_freelist = *list_head;
|
|
|
+ *list_head = *list_tail = NULL;
|
|
|
+ qdf_spin_unlock_bh(&cc_ctx->cc_lock);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ *list_tail = cc_ctx->page_desc_freelist;
|
|
|
+ cc_ctx->page_desc_freelist = cc_ctx->page_desc_freelist->next;
|
|
|
+ }
|
|
|
+ (*list_tail)->next = NULL;
|
|
|
+ cc_ctx->free_page_num -= count;
|
|
|
+
|
|
|
+ qdf_spin_unlock_bh(&cc_ctx->cc_lock);
|
|
|
+
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+void dp_cc_spt_page_desc_free(struct dp_soc_be *be_soc,
|
|
|
+ struct dp_spt_page_desc **list_head,
|
|
|
+ struct dp_spt_page_desc **list_tail,
|
|
|
+ uint16_t page_nums)
|
|
|
+{
|
|
|
+ struct dp_hw_cookie_conversion_t *cc_ctx = &be_soc->hw_cc_ctx;
|
|
|
+ struct dp_spt_page_desc *temp_list = NULL;
|
|
|
+
|
|
|
+ qdf_spin_lock_bh(&cc_ctx->cc_lock);
|
|
|
+
|
|
|
+ temp_list = cc_ctx->page_desc_freelist;
|
|
|
+ cc_ctx->page_desc_freelist = *list_head;
|
|
|
+ (*list_tail)->next = temp_list;
|
|
|
+ cc_ctx->free_page_num += page_nums;
|
|
|
+ *list_tail = NULL;
|
|
|
+ *list_head = NULL;
|
|
|
+
|
|
|
+ qdf_spin_unlock_bh(&cc_ctx->cc_lock);
|
|
|
+}
|
|
|
+
|
|
|
static QDF_STATUS dp_soc_attach_be(struct dp_soc *soc)
|
|
|
{
|
|
|
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
|
|
@@ -46,6 +304,9 @@ static QDF_STATUS dp_soc_attach_be(struct dp_soc *soc)
|
|
|
soc->wbm_sw0_bm_id = hal_tx_get_wbm_sw0_bm_id();
|
|
|
qdf_status = dp_tx_init_bank_profiles(be_soc);
|
|
|
|
|
|
+ /* cookie conversion */
|
|
|
+ qdf_status = dp_hw_cookie_conversion_attach(be_soc);
|
|
|
+
|
|
|
return qdf_status;
|
|
|
}
|
|
|
|
|
@@ -55,6 +316,27 @@ static QDF_STATUS dp_soc_detach_be(struct dp_soc *soc)
|
|
|
|
|
|
dp_tx_deinit_bank_profiles(be_soc);
|
|
|
|
|
|
+ dp_hw_cookie_conversion_detach(be_soc);
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static QDF_STATUS dp_soc_init_be(struct dp_soc *soc)
|
|
|
+{
|
|
|
+ struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
|
|
|
+ QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ qdf_status = dp_hw_cookie_conversion_init(be_soc);
|
|
|
+
|
|
|
+ return qdf_status;
|
|
|
+}
|
|
|
+
|
|
|
+static QDF_STATUS dp_soc_deinit_be(struct dp_soc *soc)
|
|
|
+{
|
|
|
+ struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
|
|
|
+
|
|
|
+ dp_hw_cookie_conversion_deinit(be_soc);
|
|
|
+
|
|
|
return QDF_STATUS_SUCCESS;
|
|
|
}
|
|
|
|
|
@@ -217,10 +499,21 @@ void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops)
|
|
|
arch_ops->dp_rx_process = dp_rx_process_be;
|
|
|
arch_ops->tx_comp_get_params_from_hal_desc =
|
|
|
dp_tx_comp_get_params_from_hal_desc_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;
|
|
|
+ arch_ops->dp_rx_desc_pool_deinit = dp_rx_desc_pool_deinit_be;
|
|
|
+ arch_ops->dp_wbm_get_rx_desc_from_hal_desc =
|
|
|
+ dp_wbm_get_rx_desc_from_hal_desc_be;
|
|
|
#endif
|
|
|
arch_ops->txrx_get_context_size = dp_get_context_size_be;
|
|
|
+ arch_ops->dp_rx_desc_cookie_2_va =
|
|
|
+ dp_rx_desc_cookie_2_va_be;
|
|
|
+
|
|
|
arch_ops->txrx_soc_attach = dp_soc_attach_be;
|
|
|
arch_ops->txrx_soc_detach = dp_soc_detach_be;
|
|
|
+ arch_ops->txrx_soc_init = dp_soc_init_be;
|
|
|
+ arch_ops->txrx_soc_deinit = dp_soc_deinit_be;
|
|
|
arch_ops->txrx_pdev_attach = dp_pdev_attach_be;
|
|
|
arch_ops->txrx_pdev_detach = dp_pdev_detach_be;
|
|
|
arch_ops->txrx_vdev_attach = dp_vdev_attach_be;
|