diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 98f11383ca..351c86048b 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -35,6 +35,14 @@ /* Ring index for WBM2SW2 release ring */ #define HAL_IPA_TX_COMP_RING_IDX 2 +#if defined(CONFIG_SHADOW_V2) || defined(CONFIG_SHADOW_V3) +#define ignore_shadow false +#define CHECK_SHADOW_REGISTERS true +#else +#define ignore_shadow true +#define CHECK_SHADOW_REGISTERS false +#endif + /* calculate the register address offset from bar0 of shadow register x */ #if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \ defined(QCA_WIFI_KIWI) @@ -2606,9 +2614,17 @@ hal_srng_get_hp_addr(void *hal_soc, struct hal_soc *hal = (struct hal_soc *)hal_soc; if (srng->ring_dir == HAL_SRNG_SRC_RING) { - return hal->shadow_wrptr_mem_paddr + - ((unsigned long)(srng->u.src_ring.hp_addr) - - (unsigned long)(hal->shadow_wrptr_mem_vaddr)); + if (srng->flags & HAL_SRNG_LMAC_RING) + return hal->shadow_wrptr_mem_paddr + + ((unsigned long)(srng->u.src_ring.hp_addr) - + (unsigned long)(hal->shadow_wrptr_mem_vaddr)); + else if (ignore_shadow) + return (qdf_dma_addr_t)srng->u.src_ring.hp_addr; + else + return ((struct hif_softc *)hal->hif_handle)->mem_pa + + ((unsigned long)srng->u.src_ring.hp_addr - + (unsigned long)hal->dev_base_addr); + } else { return hal->shadow_rdptr_mem_paddr + ((unsigned long)(srng->u.dst_ring.hp_addr) - @@ -2634,9 +2650,16 @@ hal_srng_get_tp_addr(void *hal_soc, hal_ring_handle_t hal_ring_hdl) ((unsigned long)(srng->u.src_ring.tp_addr) - (unsigned long)(hal->shadow_rdptr_mem_vaddr)); } else { - return hal->shadow_wrptr_mem_paddr + - ((unsigned long)(srng->u.dst_ring.tp_addr) - - (unsigned long)(hal->shadow_wrptr_mem_vaddr)); + if (srng->flags & HAL_SRNG_LMAC_RING) + return hal->shadow_wrptr_mem_paddr + + ((unsigned long)(srng->u.dst_ring.tp_addr) - + (unsigned long)(hal->shadow_wrptr_mem_vaddr)); + else if (ignore_shadow) + return (qdf_dma_addr_t)srng->u.dst_ring.tp_addr; + else + return ((struct hif_softc *)hal->hif_handle)->mem_pa + + ((unsigned long)srng->u.dst_ring.tp_addr - + (unsigned long)hal->dev_base_addr); } } diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index a73e62a612..6976023376 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -1431,14 +1431,6 @@ static inline void hal_srng_hw_init(struct hal_soc *hal, hal_srng_dst_hw_init(hal, srng, idle_check); } -#if defined(CONFIG_SHADOW_V2) || defined(CONFIG_SHADOW_V3) -#define ignore_shadow false -#define CHECK_SHADOW_REGISTERS true -#else -#define ignore_shadow true -#define CHECK_SHADOW_REGISTERS false -#endif - #ifdef WLAN_FEATURE_NEAR_FULL_IRQ /** * hal_srng_is_near_full_irq_supported() - Check if near full irq is diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 2b1f19dad8..d1144c86fd 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -442,6 +442,38 @@ struct hif_target_info { struct hif_opaque_softc { }; +/** + * struct hif_ce_ring_info - CE ring information + * @ring_id: ring id + * @ring_dir: ring direction + * @num_entries: number of entries in ring + * @entry_size: ring entry size + * @ring_base_paddr: srng base physical address + * @hp_paddr: head pointer physical address + * @tp_paddr: tail pointer physical address + */ +struct hif_ce_ring_info { + uint8_t ring_id; + uint8_t ring_dir; + uint32_t num_entries; + uint32_t entry_size; + uint64_t ring_base_paddr; + uint64_t hp_paddr; + uint64_t tp_paddr; +}; + +/** + * struct hif_direct_link_ce_info - Direct Link CE information + * @ce_id: CE ide + * @pipe_dir: Pipe direction + * @ring_info: ring information + */ +struct hif_direct_link_ce_info { + uint8_t ce_id; + uint8_t pipe_dir; + struct hif_ce_ring_info ring_info; +}; + /** * enum hif_event_type - Type of DP events to be recorded * @HIF_EVENT_IRQ_TRIGGER: IRQ trigger event @@ -2450,6 +2482,30 @@ QDF_STATUS hif_unregister_umac_reset_handler(struct hif_opaque_softc *hif_scn) QDF_STATUS hif_set_irq_config_by_ceid(struct hif_opaque_softc *scn, uint8_t ce_id, uint64_t addr, uint32_t data); + +/** + * hif_get_direct_link_ce_dest_srng_buffers() - Get Direct Link ce dest srng + * buffer information + * @hif_ctx: hif opaque handle + * @dma_addr: pointer to array of dma addresses + * + * Return: Number of buffers attached to the dest srng. + */ +uint16_t hif_get_direct_link_ce_dest_srng_buffers(struct hif_opaque_softc *scn, + uint64_t **dma_addr); + +/** + * hif_get_direct_link_ce_srng_info() - Get Direct Link CE srng information + * @hif_ctx: hif opaque handle + * @info: Direct Link CEs information + * @max_ce_info_len: max array size of ce info + * + * Return: QDF status + */ +QDF_STATUS +hif_get_direct_link_ce_srng_info(struct hif_opaque_softc *scn, + struct hif_direct_link_ce_info *info, + uint8_t max_ce_info_len); #else static inline QDF_STATUS hif_set_irq_config_by_ceid(struct hif_opaque_softc *scn, uint8_t ce_id, @@ -2457,5 +2513,19 @@ hif_set_irq_config_by_ceid(struct hif_opaque_softc *scn, uint8_t ce_id, { return QDF_STATUS_SUCCESS; } + +static inline +uint16_t hif_get_direct_link_ce_dest_srng_buffers(struct hif_opaque_softc *scn) +{ + return 0; +} + +static inline QDF_STATUS +hif_get_direct_link_ce_srng_info(struct hif_opaque_softc *scn, + struct hif_direct_link_ce_info *info, + uint8_t max_ce_info_len) +{ + return QDF_STATUS_SUCCESS; +} #endif #endif /* _HIF_H_ */ diff --git a/hif/src/ce/ce_api.h b/hif/src/ce/ce_api.h index a85f88080b..0cb0f95cce 100644 --- a/hif/src/ce/ce_api.h +++ b/hif/src/ce/ce_api.h @@ -601,6 +601,11 @@ struct ce_ops { QDF_STATUS (*ce_set_irq_config_by_ceid)(struct hif_softc *scn, uint8_t ce_id, uint64_t addr, uint32_t data); + uint16_t (*ce_get_direct_link_dest_buffers)(struct hif_softc *scn, + uint64_t **dma_addr); + QDF_STATUS (*ce_get_direct_link_ring_info)(struct hif_softc *scn, + struct hif_direct_link_ce_info *info, + uint8_t max_ce_info_len); #endif }; diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index 4f3dff1ac4..9ee2ce9a8d 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -5322,5 +5322,36 @@ hif_set_irq_config_by_ceid(struct hif_opaque_softc *scn, uint8_t ce_id, return QDF_STATUS_E_NOSUPPORT; } + +uint16_t hif_get_direct_link_ce_dest_srng_buffers(struct hif_opaque_softc *scn, + uint64_t **dma_addr) +{ + struct hif_softc *hif_ctx = HIF_GET_SOFTC(scn); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct ce_ops *ce_services = hif_state->ce_services; + + if (ce_services->ce_get_direct_link_dest_buffers) + return ce_services->ce_get_direct_link_dest_buffers(hif_ctx, + dma_addr); + + return 0; +} + +QDF_STATUS +hif_get_direct_link_ce_srng_info(struct hif_opaque_softc *scn, + struct hif_direct_link_ce_info *info, + uint8_t max_ce_info_len) +{ + struct hif_softc *hif_ctx = HIF_GET_SOFTC(scn); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct ce_ops *ce_services = hif_state->ce_services; + + if (ce_services->ce_get_direct_link_ring_info) + return ce_services->ce_get_direct_link_ring_info(hif_ctx, + info, + max_ce_info_len); + + return QDF_STATUS_E_NOSUPPORT; +} #endif #endif diff --git a/hif/src/ce/ce_service_srng.c b/hif/src/ce/ce_service_srng.c index 514712f432..012b1729a1 100644 --- a/hif/src/ce/ce_service_srng.c +++ b/hif/src/ce/ce_service_srng.c @@ -1153,6 +1153,136 @@ ce_set_srng_msi_irq_config_by_ceid(struct hif_softc *scn, uint8_t ce_id, return QDF_STATUS_SUCCESS; } + +static +uint16_t ce_get_direct_link_dest_srng_buffers(struct hif_softc *scn, + uint64_t **dma_addr) +{ + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct CE_state *ce_state; + struct service_to_pipe *tgt_svc_cfg; + qdf_nbuf_t nbuf; + uint64_t *nbuf_dmaaddr = NULL; + uint32_t i; + uint32_t j = 0; + + tgt_svc_cfg = hif_state->tgt_svc_map; + + for (i = 0; i < hif_state->sz_tgt_svc_map; i++) { + if (tgt_svc_cfg[i].service_id != LPASS_DATA_MSG_SVC || + tgt_svc_cfg[i].pipedir != PIPEDIR_IN) + continue; + + ce_state = scn->ce_id_to_state[tgt_svc_cfg[i].pipenum]; + if (!ce_state || !ce_state->dest_ring) { + hif_err("Direct Link CE pipe %d not initialized", + tgt_svc_cfg[i].pipenum); + return QDF_STATUS_E_FAILURE; + } + + nbuf_dmaaddr = qdf_mem_malloc(sizeof(*nbuf_dmaaddr) * + ce_state->dest_ring->nentries); + if (!nbuf_dmaaddr) + return 0; + + for (j = 0; j < ce_state->dest_ring->nentries; j++) { + nbuf = ce_state->dest_ring->per_transfer_context[j]; + if (!nbuf) + break; + + nbuf_dmaaddr[j] = QDF_NBUF_CB_PADDR(nbuf); + } + + break; + } + + *dma_addr = nbuf_dmaaddr; + + return j; +} + +/** + * ce_save_srng_info() - Get and save srng information + * @hif_ctx: hif context + * @srng_info: Direct Link CE srng information + * @srng_ctx: Direct Link CE srng context + * + * Return: QDF status + */ +static void +ce_save_srng_info(struct hif_softc *hif_ctx, struct hif_ce_ring_info *srng_info, + void *srng_ctx) +{ + struct hal_srng_params params; + + hal_get_srng_params(hif_ctx->hal_soc, srng_ctx, ¶ms); + + srng_info->ring_id = params.ring_id; + srng_info->ring_dir = params.ring_dir; + srng_info->num_entries = params.num_entries; + srng_info->entry_size = params.entry_size; + srng_info->ring_base_paddr = params.ring_base_paddr; + srng_info->hp_paddr = + hal_srng_get_hp_addr(hif_ctx->hal_soc, srng_ctx); + srng_info->tp_paddr = + hal_srng_get_tp_addr(hif_ctx->hal_soc, srng_ctx); +} + +static +QDF_STATUS ce_get_direct_link_srng_info(struct hif_softc *scn, + struct hif_direct_link_ce_info *info, + uint8_t max_ce_info_len) +{ + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct CE_state *ce_state; + struct service_to_pipe *tgt_svc_cfg; + uint8_t ce_info_idx = 0; + uint32_t i; + + tgt_svc_cfg = hif_state->tgt_svc_map; + + for (i = 0; i < hif_state->sz_tgt_svc_map; i++) { + if (tgt_svc_cfg[i].service_id != LPASS_DATA_MSG_SVC) + continue; + + ce_state = scn->ce_id_to_state[tgt_svc_cfg[i].pipenum]; + if (!ce_state) { + hif_err("Direct Link CE pipe %d not initialized", + tgt_svc_cfg[i].pipenum); + return QDF_STATUS_E_FAILURE; + } + + if (ce_info_idx > max_ce_info_len) + return QDF_STATUS_E_FAILURE; + + info[ce_info_idx].ce_id = ce_state->id; + info[ce_info_idx].pipe_dir = tgt_svc_cfg[i].pipedir; + + if (ce_state->src_ring) + ce_save_srng_info(scn, &info[ce_info_idx].ring_info, + ce_state->src_ring->srng_ctx); + else + ce_save_srng_info(scn, &info[ce_info_idx].ring_info, + ce_state->dest_ring->srng_ctx); + + ce_info_idx++; + + if (!ce_state->status_ring) + continue; + + if (ce_info_idx > max_ce_info_len) + return QDF_STATUS_E_FAILURE; + + info[ce_info_idx].ce_id = ce_state->id; + info[ce_info_idx].pipe_dir = tgt_svc_cfg[i].pipedir; + + ce_save_srng_info(scn, &info[ce_info_idx].ring_info, + ce_state->status_ring->srng_ctx); + ce_info_idx++; + } + + return QDF_STATUS_SUCCESS; +} #endif static struct ce_ops ce_service_srng = { @@ -1182,6 +1312,8 @@ static struct ce_ops ce_service_srng = { #endif #ifdef FEATURE_DIRECT_LINK .ce_set_irq_config_by_ceid = ce_set_srng_msi_irq_config_by_ceid, + .ce_get_direct_link_dest_buffers = ce_get_direct_link_dest_srng_buffers, + .ce_get_direct_link_ring_info = ce_get_direct_link_srng_info, #endif };