diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 6aee83e941..0554c57780 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -118,6 +118,9 @@ static void dp_ppdu_ring_cfg(struct dp_pdev *pdev); bool is_dp_verbose_debug_enabled; #endif +static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc, + enum hal_ring_type ring_type, + int ring_num); #define DP_INTR_POLL_TIMER_MS 10 /* Generic AST entry aging timer value */ #define DP_AST_AGING_TIMER_DEFAULT_MS 1000 @@ -1102,13 +1105,23 @@ static void dp_print_peer_table(struct dp_vdev *vdev) * QDF_STATUS_E_NOMEM on failure */ static QDF_STATUS -dp_srng_mem_alloc(struct dp_soc *soc, struct dp_srng *srng, uint32_t align) +dp_srng_mem_alloc(struct dp_soc *soc, struct dp_srng *srng, uint32_t align, + bool cached) { - srng->base_vaddr_unaligned = - qdf_mem_alloc_consistent(soc->osdev, - soc->osdev->dev, - srng->alloc_size, - &srng->base_paddr_unaligned); + uint32_t align_alloc_size; + + if (!cached) { + srng->base_vaddr_unaligned = + qdf_mem_alloc_consistent(soc->osdev, + soc->osdev->dev, + srng->alloc_size, + &srng->base_paddr_unaligned); + } else { + srng->base_vaddr_unaligned = qdf_mem_malloc(srng->alloc_size); + srng->base_paddr_unaligned = + qdf_mem_virt_to_phys(srng->base_vaddr_unaligned); + } + if (!srng->base_vaddr_unaligned) { return QDF_STATUS_E_NOMEM; } @@ -1127,21 +1140,36 @@ dp_srng_mem_alloc(struct dp_soc *soc, struct dp_srng *srng, uint32_t align) */ if ((unsigned long)(srng->base_paddr_unaligned) & (align - 1)) { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - srng->alloc_size, - srng->base_vaddr_unaligned, - srng->base_paddr_unaligned, 0); - srng->alloc_size = srng->alloc_size + align - 1; - srng->base_vaddr_unaligned = - qdf_mem_alloc_consistent(soc->osdev, - soc->osdev->dev, - srng->alloc_size, - &srng->base_paddr_unaligned); + align_alloc_size = srng->alloc_size + align - 1; + + if (!cached) { + qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, + srng->alloc_size, + srng->base_vaddr_unaligned, + srng->base_paddr_unaligned, 0); + + srng->base_vaddr_unaligned = + qdf_mem_alloc_consistent(soc->osdev, + soc->osdev->dev, + align_alloc_size, + &srng->base_paddr_unaligned); + + } else { + qdf_mem_free(srng->base_vaddr_unaligned); + srng->base_vaddr_unaligned = + qdf_mem_malloc(align_alloc_size); + + srng->base_paddr_unaligned = + qdf_mem_virt_to_phys(srng->base_vaddr_unaligned); + } + + srng->alloc_size = align_alloc_size; if (!srng->base_vaddr_unaligned) { return QDF_STATUS_E_NOMEM; } } + return QDF_STATUS_SUCCESS; } @@ -1150,7 +1178,8 @@ dp_srng_mem_alloc(struct dp_soc *soc, struct dp_srng *srng, uint32_t align) * dp_setup_srng - Internal function to setup SRNG rings used by data path */ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng, - int ring_type, int ring_num, int mac_id, uint32_t num_entries) + int ring_type, int ring_num, int mac_id, + uint32_t num_entries, bool cached) { void *hal_soc = soc->hal_soc; uint32_t entry_size = hal_srng_get_entrysize(hal_soc, ring_type); @@ -1170,12 +1199,13 @@ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng, srng->num_entries = num_entries; if (!dp_is_soc_reinit(soc)) { - if (dp_srng_mem_alloc(soc, srng, ring_base_align) != + if (dp_srng_mem_alloc(soc, srng, ring_base_align, cached) != QDF_STATUS_SUCCESS) { dp_err("alloc failed - ring_type: %d, ring_num %d", ring_type, ring_num); return QDF_STATUS_E_NOMEM; } + } ring_params.ring_base_paddr = @@ -1245,14 +1275,23 @@ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng, ring_params.intr_batch_cntr_thres_entries = 0; } + if (cached) { + ring_params.flags |= HAL_SRNG_CACHED_DESC; + srng->cached = 1; + } + srng->hal_srng = hal_srng_setup(hal_soc, ring_type, ring_num, mac_id, &ring_params); if (!srng->hal_srng) { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - srng->alloc_size, - srng->base_vaddr_unaligned, - srng->base_paddr_unaligned, 0); + if (cached) { + qdf_mem_free(srng->base_vaddr_unaligned); + } else { + qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, + srng->alloc_size, + srng->base_vaddr_unaligned, + srng->base_paddr_unaligned, 0); + } } return 0; @@ -1304,12 +1343,17 @@ static void dp_srng_cleanup(struct dp_soc *soc, struct dp_srng *srng, } if (srng->alloc_size) { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - srng->alloc_size, - srng->base_vaddr_unaligned, - srng->base_paddr_unaligned, 0); + if (!srng->cached) { + qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, + srng->alloc_size, + srng->base_vaddr_unaligned, + srng->base_paddr_unaligned, 0); + } else { + qdf_mem_free(srng->base_vaddr_unaligned); + } srng->alloc_size = 0; } + srng->hal_srng = NULL; } /* TODO: Need this interface from HIF */ @@ -2000,7 +2044,7 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc) void *desc; if (dp_srng_setup(soc, &soc->wbm_idle_link_ring, - WBM_IDLE_LINK, 0, 0, total_link_descs)) { + WBM_IDLE_LINK, 0, 0, total_link_descs, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("Link desc idle ring setup failed")); goto fail; @@ -2695,8 +2739,10 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) /* Setup SRNG rings */ /* Common rings */ + entries = wlan_cfg_get_dp_soc_wbm_release_ring_size(soc_cfg_ctx); + if (dp_srng_setup(soc, &soc->wbm_desc_rel_ring, SW2WBM_RELEASE, 0, 0, - wlan_cfg_get_dp_soc_wbm_release_ring_size(soc_cfg_ctx))) { + entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for wbm_desc_rel_ring")); goto fail1; @@ -2717,7 +2763,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) wlan_cfg_tx_ring_size(soc_cfg_ctx); for (i = 0; i < soc->num_tcl_data_rings; i++) { if (dp_srng_setup(soc, &soc->tcl_data_ring[i], - TCL_DATA, i, 0, tx_ring_size)) { + TCL_DATA, i, 0, tx_ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tcl_data_ring[%d]"), i); @@ -2728,7 +2774,9 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) * count */ if (dp_srng_setup(soc, &soc->tx_comp_ring[i], - WBM2SW_RELEASE, i, 0, tx_comp_ring_size)) { + WBM2SW_RELEASE, i, 0, + tx_comp_ring_size, + WLAN_CFG_DST_RING_CACHED_DESC)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tx_comp_ring[%d]"), i); @@ -2749,7 +2797,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) entries = wlan_cfg_get_dp_soc_tcl_cmd_ring_size(soc_cfg_ctx); /* TCL command and status rings */ if (dp_srng_setup(soc, &soc->tcl_cmd_ring, TCL_CMD, 0, 0, - entries)) { + entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tcl_cmd_ring")); goto fail1; @@ -2757,7 +2805,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) entries = wlan_cfg_get_dp_soc_tcl_status_ring_size(soc_cfg_ctx); if (dp_srng_setup(soc, &soc->tcl_status_ring, TCL_STATUS, 0, 0, - entries)) { + entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tcl_status_ring")); goto fail1; @@ -2778,7 +2826,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) FL("num_reo_dest_rings %d"), soc->num_reo_dest_rings); for (i = 0; i < soc->num_reo_dest_rings; i++) { if (dp_srng_setup(soc, &soc->reo_dest_ring[i], REO_DST, - i, 0, reo_dst_ring_size)) { + i, 0, reo_dst_ring_size, + WLAN_CFG_DST_RING_CACHED_DESC)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "reo_dest_ring [%d]"), i); @@ -2798,8 +2847,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) for (i = 0; i < MAX_RX_MAC_RINGS; i++) { if (dp_srng_setup(soc, &pdev->rxdma_err_dst_ring[i], - RXDMA_DST, 0, i, - entries)) { + RXDMA_DST, 0, i, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "rxdma_err_dst_ring")); @@ -2812,7 +2860,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) /* REO reinjection ring */ entries = wlan_cfg_get_dp_soc_reo_reinject_ring_size(soc_cfg_ctx); if (dp_srng_setup(soc, &soc->reo_reinject_ring, REO_REINJECT, 0, 0, - entries)) { + entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_reinject_ring")); goto fail1; @@ -2821,7 +2869,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) /* Rx release ring */ if (dp_srng_setup(soc, &soc->rx_rel_ring, WBM2SW_RELEASE, 3, 0, - wlan_cfg_get_dp_soc_rx_release_ring_size(soc_cfg_ctx))) { + wlan_cfg_get_dp_soc_rx_release_ring_size(soc_cfg_ctx), + 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for rx_rel_ring")); goto fail1; @@ -2831,7 +2880,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) /* Rx exception ring */ entries = wlan_cfg_get_dp_soc_reo_exception_ring_size(soc_cfg_ctx); if (dp_srng_setup(soc, &soc->reo_exception_ring, - REO_EXCEPTION, 0, MAX_REO_DEST_RINGS, entries)) { + REO_EXCEPTION, 0, MAX_REO_DEST_RINGS, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_exception_ring")); goto fail1; @@ -2840,7 +2889,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) /* REO command and status rings */ if (dp_srng_setup(soc, &soc->reo_cmd_ring, REO_CMD, 0, 0, - wlan_cfg_get_dp_soc_reo_cmd_ring_size(soc_cfg_ctx))) { + wlan_cfg_get_dp_soc_reo_cmd_ring_size(soc_cfg_ctx), + 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_cmd_ring")); goto fail1; @@ -2851,7 +2901,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) qdf_spinlock_create(&soc->rx.reo_cmd_lock); if (dp_srng_setup(soc, &soc->reo_status_ring, REO_STATUS, 0, 0, - wlan_cfg_get_dp_soc_reo_status_ring_size(soc_cfg_ctx))) { + wlan_cfg_get_dp_soc_reo_status_ring_size(soc_cfg_ctx), + 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_status_ring")); goto fail1; @@ -2991,15 +3042,16 @@ static int dp_rxdma_ring_setup(struct dp_soc *soc, struct wlan_cfg_dp_pdev_ctxt *pdev_cfg_ctx; int max_mac_rings; int i; + int ring_size; pdev_cfg_ctx = pdev->wlan_cfg_ctx; max_mac_rings = wlan_cfg_get_num_mac_rings(pdev_cfg_ctx); + ring_size = wlan_cfg_get_rx_dma_buf_ring_size(pdev_cfg_ctx); for (i = 0; i < max_mac_rings; i++) { dp_verbose_debug("pdev_id %d mac_id %d", pdev->pdev_id, i); if (dp_srng_setup(soc, &pdev->rx_mac_buf_ring[i], - RXDMA_BUF, 1, i, - wlan_cfg_get_rx_dma_buf_ring_size(pdev_cfg_ctx))) { + RXDMA_BUF, 1, i, ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("failed rx mac ring setup")); @@ -3083,9 +3135,8 @@ static int dp_setup_ipa_rx_refill_buf_ring(struct dp_soc *soc, /* Setup second Rx refill buffer ring */ if (dp_srng_setup(soc, &pdev->rx_refill_buf_ring2, RXDMA_BUF, - IPA_RX_REFILL_BUF_RING_IDX, - pdev->pdev_id, - entries)) { + IPA_RX_REFILL_BUF_RING_IDX, pdev->pdev_id, entries, 0) + ) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed second rx refill ring")); return QDF_STATUS_E_FAILURE; @@ -3147,7 +3198,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) if (dp_srng_setup(soc, &pdev->rxdma_mon_buf_ring[mac_id], RXDMA_MONITOR_BUF, 0, mac_for_pdev, - entries)) { + entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "rxdma_mon_buf_ring ")); @@ -3159,7 +3210,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) if (dp_srng_setup(soc, &pdev->rxdma_mon_dst_ring[mac_id], RXDMA_MONITOR_DST, 0, mac_for_pdev, - entries)) { + entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "rxdma_mon_dst_ring")); @@ -3171,7 +3222,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) if (dp_srng_setup(soc, &pdev->rxdma_mon_status_ring[mac_id], RXDMA_MONITOR_STATUS, 0, mac_for_pdev, - entries)) { + entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "rxdma_mon_status_ring")); @@ -3183,7 +3234,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) if (dp_srng_setup(soc, &pdev->rxdma_mon_desc_ring[mac_id], RXDMA_MONITOR_DESC, 0, mac_for_pdev, - entries)) { + entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "rxdma_mon_desc_ring")); @@ -3195,7 +3246,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) if (dp_srng_setup(soc, &pdev->rxdma_mon_status_ring[mac_id], RXDMA_MONITOR_STATUS, 0, mac_for_pdev, - entries)) { + entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "rxdma_mon_status_ring")); @@ -3274,9 +3325,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, struct cdp_ctrl_objmgr_pdev *ctrl_pdev, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, uint8_t pdev_id) { - int tx_ring_size; - int tx_comp_ring_size; - int reo_dst_ring_size; + int ring_size; int entries; struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx; int nss_cfg; @@ -3356,19 +3405,22 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, /* Setup per PDEV TCL rings if configured */ if (wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) { - tx_ring_size = + ring_size = wlan_cfg_tx_ring_size(soc_cfg_ctx); - tx_comp_ring_size = - wlan_cfg_tx_comp_ring_size(soc_cfg_ctx); if (dp_srng_setup(soc, &soc->tcl_data_ring[pdev_id], TCL_DATA, - pdev_id, pdev_id, tx_ring_size)) { + pdev_id, pdev_id, ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tcl_data_ring")); goto fail1; } + + ring_size = + wlan_cfg_tx_comp_ring_size(soc_cfg_ctx); + if (dp_srng_setup(soc, &soc->tx_comp_ring[pdev_id], - WBM2SW_RELEASE, pdev_id, pdev_id, tx_comp_ring_size)) { + WBM2SW_RELEASE, pdev_id, pdev_id, + ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tx_comp_ring")); goto fail1; @@ -3383,11 +3435,11 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, goto fail1; } - reo_dst_ring_size = wlan_cfg_get_reo_dst_ring_size(soc->wlan_cfg_ctx); + ring_size = wlan_cfg_get_reo_dst_ring_size(soc->wlan_cfg_ctx); /* Setup per PDEV REO rings if configured */ if (wlan_cfg_per_pdev_rx_ring(soc_cfg_ctx)) { if (dp_srng_setup(soc, &soc->reo_dest_ring[pdev_id], REO_DST, - pdev_id, pdev_id, reo_dst_ring_size)) { + pdev_id, pdev_id, ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_dest_ringn")); goto fail1; @@ -3395,8 +3447,12 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, soc->num_reo_dest_rings++; } + + ring_size = + wlan_cfg_get_dp_soc_rxdma_refill_ring_size(soc->wlan_cfg_ctx); + if (dp_srng_setup(soc, &pdev->rx_refill_buf_ring, RXDMA_BUF, 0, pdev_id, - wlan_cfg_get_dp_soc_rxdma_refill_ring_size(soc_cfg_ctx))) { + ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed rx refill ring")); goto fail1; @@ -3417,8 +3473,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, entries = wlan_cfg_get_dp_soc_rxdma_err_dst_ring_size(soc_cfg_ctx); if (wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) { if (dp_srng_setup(soc, &pdev->rxdma_err_dst_ring[0], RXDMA_DST, - 0, pdev_id, - entries)) { + 0, pdev_id, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "rxdma_err_dst_ring")); goto fail1; diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 05f7edcadb..4ecc2b7fc4 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -3361,9 +3361,6 @@ more_data: pool_id = (tx_desc_id & DP_TX_DESC_ID_POOL_MASK) >> DP_TX_DESC_ID_POOL_OS; - if (!dp_tx_is_desc_id_valid(soc, tx_desc_id)) - continue; - /* Find Tx descriptor */ tx_desc = dp_tx_desc_find(soc, pool_id, (tx_desc_id & DP_TX_DESC_ID_PAGE_MASK) >> diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index cf076abeba..b1cdfa33d6 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -478,6 +478,7 @@ struct dp_srng { void *base_vaddr_unaligned; qdf_dma_addr_t base_paddr_unaligned; uint32_t alloc_size; + uint8_t cached; int irq; uint32_t num_entries; }; diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 6f5cc08463..fca9271521 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -312,6 +312,7 @@ enum hal_ring_type { #define HAL_SRNG_DATA_TLV_SWAP 0x00000020 #define HAL_SRNG_LOW_THRES_INTR_ENABLE 0x00010000 #define HAL_SRNG_MSI_INTR 0x00020000 +#define HAL_SRNG_CACHED_DESC 0x00040000 #define PN_SIZE_24 0 #define PN_SIZE_48 1 @@ -520,6 +521,26 @@ static inline bool hal_srng_initialized(void *hal_ring) return !!srng->initialized; } +/** + * hal_srng_dst_peek - Check if there are any entries in the ring (peek) + * @hal_soc: Opaque HAL SOC handle + * @hal_ring: Destination ring pointer + * + * Caller takes responsibility for any locking needs. + * + * Return: Opaque pointer for next ring entry; NULL on failire + */ +static inline +void *hal_srng_dst_peek(void *hal_soc, void *hal_ring) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring; + + if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp) + return (void *)(&srng->ring_base_vaddr[srng->u.dst_ring.tp]); + + return NULL; +} + /** * hal_srng_access_start_unlocked - Start ring access (unlocked). Should use * hal_srng_access_start if locked access is required @@ -532,14 +553,30 @@ static inline bool hal_srng_initialized(void *hal_ring) static inline int hal_srng_access_start_unlocked(void *hal_soc, void *hal_ring) { struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_soc *soc = (struct hal_soc *)hal_soc; + uint32_t *desc; if (srng->ring_dir == HAL_SRNG_SRC_RING) srng->u.src_ring.cached_tp = *(volatile uint32_t *)(srng->u.src_ring.tp_addr); - else + else { srng->u.dst_ring.cached_hp = *(volatile uint32_t *)(srng->u.dst_ring.hp_addr); + if (srng->flags & HAL_SRNG_CACHED_DESC) { + desc = hal_srng_dst_peek(hal_soc, hal_ring); + if (qdf_likely(desc)) { + qdf_mem_dma_cache_sync(soc->qdf_dev, + qdf_mem_virt_to_phys + (desc), + QDF_DMA_FROM_DEVICE, + (srng->entry_size * + sizeof(uint32_t))); + qdf_prefetch(desc); + } + } + } + return 0; } @@ -577,7 +614,10 @@ static inline int hal_srng_access_start(void *hal_soc, void *hal_ring) static inline void *hal_srng_dst_get_next(void *hal_soc, void *hal_ring) { struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_soc *soc = (struct hal_soc *)hal_soc; uint32_t *desc; + uint32_t *desc_next; + uint32_t tp; if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp) { desc = &(srng->ring_base_vaddr[srng->u.dst_ring.tp]); @@ -590,6 +630,17 @@ static inline void *hal_srng_dst_get_next(void *hal_soc, void *hal_ring) srng->u.dst_ring.tp = (srng->u.dst_ring.tp + srng->entry_size) % srng->ring_size; + if (srng->flags & HAL_SRNG_CACHED_DESC) { + tp = srng->u.dst_ring.tp; + desc_next = &srng->ring_base_vaddr[tp]; + qdf_mem_dma_cache_sync(soc->qdf_dev, + qdf_mem_virt_to_phys(desc_next), + QDF_DMA_FROM_DEVICE, + (srng->entry_size * + sizeof(uint32_t))); + qdf_prefetch(desc_next); + } + return (void *)desc; } @@ -627,26 +678,6 @@ static inline void *hal_srng_dst_get_next_hp(void *hal_soc, void *hal_ring) return NULL; } -/** - * hal_srng_dst_peek - Check if there are any entries in the ring (peek) - * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Destination ring pointer - * - * Caller takes responsibility for any locking needs. - * - * Return: Opaque pointer for next ring entry; NULL on failire - */ -static inline -void *hal_srng_dst_peek(void *hal_soc, void *hal_ring) -{ - struct hal_srng *srng = (struct hal_srng *)hal_ring; - - if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp) - return (void *)(&srng->ring_base_vaddr[srng->u.dst_ring.tp]); - - return NULL; -} - /** * hal_srng_dst_peek_sync - Check if there are any entries in the ring (peek) * @hal_soc: Opaque HAL SOC handle diff --git a/hal/wifi3.0/hal_rx.h b/hal/wifi3.0/hal_rx.h index 12c70a3e4f..04c144bd85 100644 --- a/hal/wifi3.0/hal_rx.h +++ b/hal/wifi3.0/hal_rx.h @@ -466,13 +466,11 @@ static inline void hal_rx_mpdu_desc_info_get(void *desc_addr, struct hal_rx_mpdu_desc_info *mpdu_desc_info) { struct reo_destination_ring *reo_dst_ring; - uint32_t mpdu_info[NUM_OF_DWORDS_RX_MPDU_DESC_INFO]; + uint32_t *mpdu_info; reo_dst_ring = (struct reo_destination_ring *) desc_addr; - qdf_mem_copy(&mpdu_info, - (const void *)&reo_dst_ring->rx_mpdu_desc_info_details, - sizeof(struct rx_mpdu_desc_info)); + mpdu_info = (uint32_t *)&reo_dst_ring->rx_mpdu_desc_info_details; mpdu_desc_info->msdu_count = HAL_RX_MPDU_MSDU_COUNT_GET(mpdu_info); mpdu_desc_info->mpdu_seq = HAL_RX_MPDU_SEQUENCE_NUMBER_GET(mpdu_info); @@ -498,14 +496,11 @@ static inline void hal_rx_msdu_desc_info_get(void *desc_addr, struct hal_rx_msdu_desc_info *msdu_desc_info) { struct reo_destination_ring *reo_dst_ring; - uint32_t msdu_info[NUM_OF_DWORDS_RX_MSDU_DESC_INFO]; + uint32_t *msdu_info; reo_dst_ring = (struct reo_destination_ring *) desc_addr; - qdf_mem_copy(&msdu_info, - (const void *)&reo_dst_ring->rx_msdu_desc_info_details, - sizeof(struct rx_msdu_desc_info)); - + msdu_info = (uint32_t *)&reo_dst_ring->rx_msdu_desc_info_details; msdu_desc_info->msdu_flags = HAL_RX_MSDU_FLAGS_GET(msdu_info); msdu_desc_info->msdu_len = HAL_RX_MSDU_PKT_LENGTH_GET(msdu_info); } diff --git a/qdf/inc/qdf_mem.h b/qdf/inc/qdf_mem.h index ea85aef3db..86155245b1 100644 --- a/qdf/inc/qdf_mem.h +++ b/qdf/inc/qdf_mem.h @@ -310,6 +310,7 @@ void *qdf_aligned_mem_alloc_consistent_fl( void **vaddr_unaligned, qdf_dma_addr_t *paddr_unaligned, qdf_dma_addr_t *paddr_aligned, uint32_t ring_base_align, const char *func, uint32_t line); +#define qdf_mem_virt_to_phys(vaddr) virt_to_phys(vaddr) void qdf_mem_set_io(void *ptr, uint32_t num_bytes, uint32_t value); @@ -414,6 +415,14 @@ static inline uint32_t qdf_mem_map_nbytes_single(qdf_device_t osdev, void *buf, #endif } +static inline void qdf_mem_dma_cache_sync(qdf_device_t osdev, + qdf_dma_addr_t buf, + qdf_dma_dir_t dir, + int nbytes) +{ + __qdf_mem_dma_cache_sync(osdev, buf, dir, nbytes); +} + /** * qdf_mem_unmap_nbytes_single() - un_map memory for DMA * @osdev: pomter OS device context diff --git a/qdf/inc/qdf_util.h b/qdf/inc/qdf_util.h index aa9130b506..ec990c505c 100644 --- a/qdf/inc/qdf_util.h +++ b/qdf/inc/qdf_util.h @@ -551,6 +551,13 @@ static inline uint8_t *qdf_get_u32(uint8_t *ptr, uint32_t *value) */ #define qdf_ffz(mask) __qdf_ffz(mask) +/** + * qdf_prefetch - prefetches the cacheline for read + * + * @x: address to be prefetched + */ +#define qdf_prefetch(x) __qdf_prefetch(x) + /** * qdf_get_pwr2() - get next power of 2 integer from input value * @value: input value to find next power of 2 integer diff --git a/qdf/linux/src/i_qdf_mem.h b/qdf/linux/src/i_qdf_mem.h index fa195ad4d3..acf9bbe93a 100644 --- a/qdf/linux/src/i_qdf_mem.h +++ b/qdf/linux/src/i_qdf_mem.h @@ -149,6 +149,25 @@ static inline uint32_t __qdf_mem_map_nbytes_single(qdf_device_t osdev, QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static inline void __qdf_mem_dma_cache_sync(qdf_device_t osdev, + qdf_dma_addr_t buf, + qdf_dma_dir_t dir, + int nbytes) +{ + dma_cache_sync(osdev->dev, buf, nbytes, __qdf_dma_dir_to_os(dir)); +} +#else +static inline void __qdf_mem_dma_cache_sync(qdf_device_t osdev, + qdf_dma_addr_t buf, + qdf_dma_dir_t dir, + int nbytes) +{ + dma_sync_single_for_cpu(osdev->dev, buf, nbytes, + __qdf_dma_dir_to_os(dir)); +} +#endif + /** * __qdf_mem_unmap_nbytes_single() - un_map memory for DMA * diff --git a/qdf/linux/src/i_qdf_util.h b/qdf/linux/src/i_qdf_util.h index e36bdb8a6d..764152bdd8 100644 --- a/qdf/linux/src/i_qdf_util.h +++ b/qdf/linux/src/i_qdf_util.h @@ -279,6 +279,8 @@ static inline bool __qdf_is_macaddr_equal(struct qdf_mac_addr *mac_addr1, ewma_rx_rssi_read(rx_rssi) #endif +#define __qdf_prefetch(x) prefetch(x) + #ifdef QCA_CONFIG_SMP /** * __qdf_get_cpu() - get cpu_index diff --git a/wlan_cfg/wlan_cfg.h b/wlan_cfg/wlan_cfg.h index fae40b684c..870ed5580c 100644 --- a/wlan_cfg/wlan_cfg.h +++ b/wlan_cfg/wlan_cfg.h @@ -24,6 +24,7 @@ * or platform configuration */ #if defined(CONFIG_MCL) +#define WLAN_CFG_DST_RING_CACHED_DESC 0 #define MAX_PDEV_CNT 1 #define WLAN_CFG_INT_NUM_CONTEXTS 7 #define WLAN_CFG_RXDMA1_ENABLE 1 @@ -38,6 +39,7 @@ #define NUM_RXDMA_RINGS_PER_PDEV 2 #else +#define WLAN_CFG_DST_RING_CACHED_DESC 1 #define MAX_PDEV_CNT 3 #define WLAN_CFG_INT_NUM_CONTEXTS 11 #define WLAN_CFG_RXDMA1_ENABLE 1