diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index fc48a2c81028..58c3549b34c7 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -157,6 +157,9 @@ enum hal_ring_type { RXDMA_MONITOR_STATUS, RXDMA_MONITOR_DST, RXDMA_MONITOR_DESC, +#ifdef WLAN_FEATURE_CIF_CFR + WIFI_POS_SRC, +#endif MAX_RING_TYPES }; diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 120bed6db9ae..3df6f3e3746f 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -147,7 +147,10 @@ enum hal_srng_ring_id { HAL_SRNG_WMAC1_RXDMA2SW0 = 133, HAL_SRNG_WMAC1_RXDMA2SW1 = 134, HAL_SRNG_WMAC1_SW2RXDMA1_DESC = 135, - /* 136-142 unused */ +#ifdef WLAN_FEATURE_CIF_CFR + HAL_SRNG_WIFI_POS_SRC_DMA_RING = 136, +#endif + /* 137-142 unused */ HAL_SRNG_LMAC1_ID_END = 143 }; diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 866971fc1506..f02e343d73ac 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -497,6 +497,20 @@ static struct hal_hw_srng_config hw_srng_table[] = { .reg_start = {}, .reg_size = {}, }, +#ifdef WLAN_FEATURE_CIF_CFR + { /* WIFI_POS_SRC */ + .start_ring_id = HAL_SRNG_WIFI_POS_SRC_DMA_RING, + .max_rings = 1, + .entry_size = sizeof(wmi_oem_dma_buf_release_entry) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + }, +#endif }; /** diff --git a/pmo/core/src/wlan_pmo_suspend_resume.c b/pmo/core/src/wlan_pmo_suspend_resume.c index b6e09e131e28..550a8cb465a3 100644 --- a/pmo/core/src/wlan_pmo_suspend_resume.c +++ b/pmo/core/src/wlan_pmo_suspend_resume.c @@ -757,6 +757,9 @@ QDF_STATUS pmo_core_psoc_bus_runtime_suspend(struct wlan_objmgr_psoc *psoc, goto dec_psoc_ref; } + wow_params.interface_pause = PMO_WOW_INTERFACE_PAUSE_ENABLE; + wow_params.resume_trigger = PMO_WOW_RESUME_TRIGGER_GPIO; + if (hif_pre_runtime_suspend(hif_ctx)) goto runtime_failure; diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index 811e5d546b7b..727f96f58632 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -605,8 +605,8 @@ static inline size_t __qdf_nbuf_len(struct sk_buff *skb) * @dst: Buffer to piggyback into * @src: Buffer to put * - * Link tow nbufs the new buf is piggybacked into the older one. The older - * (src) skb is released. + * Concat two nbufs, the new buf(src) is piggybacked into the older one. + * It is callers responsibility to free the src skb. * * Return: QDF_STATUS (status of the call) if failed the src skb * is released @@ -628,11 +628,9 @@ __qdf_nbuf_cat(struct sk_buff *dst, struct sk_buff *src) if (error) return __qdf_to_status(error); } + memcpy(skb_tail_pointer(dst), src->data, src->len); - skb_put(dst, src->len); - dev_kfree_skb_any(src); - return __qdf_to_status(error); } diff --git a/target_if/wifi_pos/inc/target_if_wifi_pos.h b/target_if/wifi_pos/inc/target_if_wifi_pos.h index 4cd5448e477d..b1a6b3fd856d 100644 --- a/target_if/wifi_pos/inc/target_if_wifi_pos.h +++ b/target_if/wifi_pos/inc/target_if_wifi_pos.h @@ -124,6 +124,13 @@ static inline void target_if_wifi_pos_register_rx_ops( QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc, void *hal_soc, uint8_t num_mac, void *buf); +/** + * target_if_wifi_pos_deinit_dma_rings: frees up DMA rings + * @psoc: pointer to psoc + * + * Return: status of operation + */ +QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc); #else static inline QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings( struct wlan_objmgr_psoc *psoc, void *hal_soc, @@ -131,6 +138,12 @@ static inline QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings( { return QDF_STATUS_SUCCESS; } + +static inline QDF_STATUS target_if_wifi_pos_deinit_dma_rings( + struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} #endif #endif /* _WIFI_POS_TGT_IF_H_ */ diff --git a/target_if/wifi_pos/src/target_if_wifi_pos.c b/target_if/wifi_pos/src/target_if_wifi_pos.c index 133665a4a321..0ba62fbdb634 100644 --- a/target_if/wifi_pos/src/target_if_wifi_pos.c +++ b/target_if/wifi_pos/src/target_if_wifi_pos.c @@ -38,56 +38,185 @@ #include "target_if.h" #ifdef WLAN_FEATURE_CIF_CFR #include "hal_api.h" + +#define RING_BASE_ALIGN 8 + +static void *target_if_wifi_pos_vaddr_lookup( + struct wifi_pos_psoc_priv_obj *priv, + void *paddr, uint8_t ring_num, uint32_t cookie) +{ + if (priv->dma_buf_pool[ring_num][cookie].paddr == paddr) { + return priv->dma_buf_pool[ring_num][cookie].vaddr + + priv->dma_buf_pool[ring_num][cookie].offset; + } else { + target_if_err("incorrect paddr found on cookie slot"); + return NULL; + } +} + +static QDF_STATUS target_if_wifi_pos_replenish_ring( + struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx, + void *alinged_vaddr, uint32_t cookie) +{ + uint64_t *ring_entry; + uint32_t dw_lo, dw_hi = 0, map_status; + void *hal_soc = priv->hal_soc; + void *srng = priv->dma_cfg[ring_idx].srng; + void *paddr; + + if (!alinged_vaddr) { + target_if_debug("NULL alinged_vaddr provided"); + return QDF_STATUS_SUCCESS; + } + + map_status = qdf_mem_map_nbytes_single(NULL, alinged_vaddr, + QDF_DMA_FROM_DEVICE, + priv->dma_cap[ring_idx].min_buf_size, + (qdf_dma_addr_t *)&paddr); + if (map_status) { + target_if_err("mem map failed status: %d", map_status); + return QDF_STATUS_E_FAILURE; + } + QDF_ASSERT(!((uint64_t)paddr % priv->dma_cap[ring_idx].min_buf_align)); + priv->dma_buf_pool[ring_idx][cookie].paddr = paddr; + + hal_srng_access_start(hal_soc, srng); + ring_entry = hal_srng_src_get_next(hal_soc, srng); + dw_lo = (uint64_t)paddr & 0xFFFFFFFF; + WMI_OEM_DMA_DATA_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32); + WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie); + *ring_entry = (uint64_t)dw_hi << 32 | dw_lo; + hal_srng_access_end(hal_soc, srng); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_wifi_pos_get_indirect_data( + struct wifi_pos_psoc_priv_obj *priv_obj, + wmi_oem_indirect_data *indirect, + struct oem_data_rsp *rsp, uint32_t *cookie) +{ + void *paddr = NULL; + uint32_t addr_hi; + uint8_t ring_idx = 0, num_rings; + + if (!indirect) { + target_if_debug("no indirect data. regular event received"); + return QDF_STATUS_SUCCESS; + } + + ring_idx = indirect->pdev_id - 1; + num_rings = priv_obj->num_rings; + if (ring_idx >= num_rings) { + target_if_err("incorrect pdev_id: %d", indirect->pdev_id); + return QDF_STATUS_E_INVAL; + } + addr_hi = (uint64_t)WMI_OEM_DMA_DATA_ADDR_HI_GET( + indirect->addr_hi); + paddr = (void *)((uint64_t)addr_hi << 32 | indirect->addr_lo); + *cookie = WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_GET( + indirect->addr_hi); + rsp->vaddr = target_if_wifi_pos_vaddr_lookup(priv_obj, + paddr, ring_idx, *cookie); + rsp->dma_len = indirect->len; + qdf_mem_unmap_nbytes_single(NULL, (qdf_dma_addr_t)paddr, + QDF_DMA_FROM_DEVICE, + priv_obj->dma_cap[ring_idx].min_buf_size); + + return QDF_STATUS_SUCCESS; +} + +#else +static QDF_STATUS target_if_wifi_pos_replenish_ring( + struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx, + void *vaddr, uint32_t cookie) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_wifi_pos_get_indirect_data( + struct wifi_pos_psoc_priv_obj *priv_obj, + wmi_oem_indirect_data *indirect, + struct oem_data_rsp *rsp, uint32_t *cookie) +{ + return QDF_STATUS_SUCCESS; +} #endif /** - * wifi_pos_oem_rsp_ev_handler: handler registered with WMI_OEM_RESPONSE_EVENTID + * target_if_wifi_pos_oem_rsp_ev_handler: handler registered with + * WMI_OEM_RESPONSE_EVENTID * @scn: scn handle * @data_buf: event buffer * @data_len: event buffer length * * Return: status of operation */ -static int wifi_pos_oem_rsp_ev_handler(ol_scn_t scn, +static int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn, uint8_t *data_buf, uint32_t data_len) { int ret; + uint8_t ring_idx = 0; + QDF_STATUS status; + uint32_t cookie = 0; + wmi_oem_indirect_data *indirect; struct oem_data_rsp oem_rsp = {0}; - struct wifi_pos_psoc_priv_obj *wifi_pos_psoc; + struct wifi_pos_psoc_priv_obj *priv_obj; struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc(); struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops = NULL; WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *)data_buf; if (!psoc) { - wifi_pos_err("psoc is null"); + target_if_err("psoc is null"); return QDF_STATUS_NOT_INITIALIZED; } - wifi_pos_psoc = wifi_pos_get_psoc_priv_obj(psoc); - if (!wifi_pos_psoc) { - wifi_pos_err("wifi_pos_psoc is null"); - return QDF_STATUS_NOT_INITIALIZED; - } - qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_ID); - wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc); - /* this will be implemented later */ - if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) { - wifi_pos_err("lmac callbacks not registered"); - ret = QDF_STATUS_NOT_INITIALIZED; - goto release_psoc_ref; + priv_obj = wifi_pos_get_psoc_priv_obj(psoc); + if (!priv_obj) { + target_if_err("priv_obj is null"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID); + return QDF_STATUS_NOT_INITIALIZED; } - oem_rsp.rsp_len = param_buf->num_data; - oem_rsp.data = param_buf->data; + wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc); + if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) { + wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID); + target_if_err("lmac callbacks not registered"); + return QDF_STATUS_NOT_INITIALIZED; + } + + oem_rsp.rsp_len_1 = param_buf->num_data; + oem_rsp.data_1 = param_buf->data; + + if (param_buf->num_data2) { + oem_rsp.rsp_len_2 = param_buf->num_data2; + oem_rsp.data_2 = param_buf->data2; + } + + indirect = (wmi_oem_indirect_data *)param_buf->indirect_data; + status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect, + &oem_rsp, &cookie); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_err("get indirect data failed status: %d", status); + wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID); + return QDF_STATUS_E_INVAL; + } ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp); + if (indirect) + ring_idx = indirect->pdev_id - 1; + status = target_if_wifi_pos_replenish_ring(priv_obj, ring_idx, + oem_rsp.vaddr, cookie); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_err("replenish failed status: %d", status); + ret = QDF_STATUS_E_FAILURE; + } -release_psoc_ref: wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID); - qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); return ret; } @@ -151,15 +280,15 @@ static QDF_STATUS wifi_pos_oem_data_req(struct wlan_objmgr_psoc *psoc, QDF_STATUS status; void *wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); - wifi_pos_debug("Send oem data req to target"); + target_if_debug("Send oem data req to target"); if (!req || !req->data) { - wifi_pos_err("oem_data_req is null"); + target_if_err("oem_data_req is null"); return QDF_STATUS_E_INVAL; } if (!wmi_hdl) { - wifi_pos_err(FL("WMA closed, can't send oem data req cmd")); + target_if_err("WMA closed, can't send oem data req cmd"); return QDF_STATUS_E_INVAL; } @@ -167,7 +296,7 @@ static QDF_STATUS wifi_pos_oem_data_req(struct wlan_objmgr_psoc *psoc, req->data); if (!QDF_IS_STATUS_SUCCESS(status)) - wifi_pos_err("wmi cmd send failed"); + target_if_err("wmi cmd send failed"); return status; } @@ -190,7 +319,7 @@ inline struct wlan_lmac_if_wifi_pos_tx_ops *target_if_wifi_pos_get_txops( struct wlan_objmgr_psoc *psoc) { if (!psoc) { - wifi_pos_err("passed psoc is NULL"); + target_if_err("passed psoc is NULL"); return NULL; } @@ -201,7 +330,7 @@ inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops( struct wlan_objmgr_psoc *psoc) { if (!psoc) { - wifi_pos_err("passed psoc is NULL"); + target_if_err("passed psoc is NULL"); return NULL; } @@ -213,43 +342,43 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc) int ret; if (!psoc || !psoc->tgt_if_handle) { - wifi_pos_err("psoc or psoc->tgt_if_handle is null"); + target_if_err("psoc or psoc->tgt_if_handle is null"); return QDF_STATUS_E_INVAL; } ret = wmi_unified_register_event_handler(psoc->tgt_if_handle, WMI_OEM_RESPONSE_EVENTID, - wifi_pos_oem_rsp_ev_handler, - WMI_RX_UMAC_CTX); + target_if_wifi_pos_oem_rsp_ev_handler, + WMI_RX_WORK_CTX); if (ret) { - wifi_pos_err("register_event_handler failed: err %d", ret); + target_if_err("register_event_handler failed: err %d", ret); return QDF_STATUS_E_INVAL; } ret = wmi_unified_register_event_handler(psoc->tgt_if_handle, wmi_oem_cap_event_id, wifi_pos_oem_cap_ev_handler, - WMI_RX_UMAC_CTX); + WMI_RX_WORK_CTX); if (ret) { - wifi_pos_err("register_event_handler failed: err %d", ret); + target_if_err("register_event_handler failed: err %d", ret); return QDF_STATUS_E_INVAL; } ret = wmi_unified_register_event_handler(psoc->tgt_if_handle, wmi_oem_meas_report_event_id, wifi_pos_oem_meas_rpt_ev_handler, - WMI_RX_UMAC_CTX); + WMI_RX_WORK_CTX); if (ret) { - wifi_pos_err("register_event_handler failed: err %d", ret); + target_if_err("register_event_handler failed: err %d", ret); return QDF_STATUS_E_INVAL; } ret = wmi_unified_register_event_handler(psoc->tgt_if_handle, wmi_oem_report_event_id, wifi_pos_oem_err_rpt_ev_handler, - WMI_RX_UMAC_CTX); + WMI_RX_WORK_CTX); if (ret) { - wifi_pos_err("register_event_handler failed: err %d", ret); + target_if_err("register_event_handler failed: err %d", ret); return QDF_STATUS_E_INVAL; } @@ -259,7 +388,7 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc) QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc) { if (!psoc || !psoc->tgt_if_handle) { - wifi_pos_err("psoc or psoc->tgt_if_handle is null"); + target_if_err("psoc or psoc->tgt_if_handle is null"); return QDF_STATUS_E_INVAL; } @@ -276,15 +405,216 @@ QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc) } #ifdef WLAN_FEATURE_CIF_CFR -static QDF_STATUS target_if_wifi_pos_init_srngs(struct wlan_objmgr_psoc *psoc, - void *hal_soc, struct wifi_pos_psoc_priv_obj *priv_obj) +static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx, + struct hal_srng *srng, + struct wifi_pos_psoc_priv_obj *priv) { + uint32_t i; + void *buf, *buf_aligned; + + for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { + buf = qdf_mem_malloc(priv->dma_cap[ring_idx].min_buf_size + + priv->dma_cap[ring_idx].min_buf_align - 1); + if (!buf) { + target_if_err("malloc failed"); + return QDF_STATUS_E_NOMEM; + } + priv->dma_buf_pool[ring_idx][i].vaddr = buf; + buf_aligned = (void *)qdf_roundup((uint64_t)buf, + priv->dma_cap[ring_idx].min_buf_align); + priv->dma_buf_pool[ring_idx][i].offset = buf_aligned - buf; + priv->dma_buf_pool[ring_idx][i].cookie = i; + target_if_wifi_pos_replenish_ring(priv, ring_idx, + buf_aligned, i); + } + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_wifi_pos_empty_ring(uint8_t ring_idx, + struct wifi_pos_psoc_priv_obj *priv) +{ + uint32_t i; + + for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) { + qdf_mem_unmap_nbytes_single(NULL, + (qdf_dma_addr_t)priv->dma_buf_pool[ring_idx][i].vaddr, + QDF_DMA_FROM_DEVICE, + priv->dma_cap[ring_idx].min_buf_size); + qdf_mem_free(priv->dma_buf_pool[ring_idx][i].vaddr); + } + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_wifi_pos_init_ring(uint8_t ring_idx, + struct wifi_pos_psoc_priv_obj *priv) +{ + void *srng; + uint32_t num_entries; + qdf_dma_addr_t paddr; + uint32_t ring_alloc_size; + void *hal_soc = priv->hal_soc; + struct hal_srng_params ring_params = {0}; + uint32_t max_entries = hal_srng_max_entries(hal_soc, WIFI_POS_SRC); + uint32_t entry_size = hal_srng_get_entrysize(hal_soc, WIFI_POS_SRC); + + num_entries = priv->dma_cap[ring_idx].min_num_ptr > max_entries ? + max_entries : priv->dma_cap[ring_idx].min_num_ptr; + priv->dma_cfg[ring_idx].num_ptr = num_entries; + priv->dma_buf_pool[ring_idx] = qdf_mem_malloc(num_entries * + sizeof(struct wifi_pos_dma_buf_info)); + if (!priv->dma_buf_pool[ring_idx]) { + target_if_err("malloc failed"); + return QDF_STATUS_E_NOMEM; + } + + ring_alloc_size = (num_entries * entry_size) + RING_BASE_ALIGN - 1; + priv->dma_cfg[ring_idx].ring_alloc_size = ring_alloc_size; + priv->dma_cfg[ring_idx].base_vaddr_unaligned = + qdf_mem_alloc_consistent(NULL, NULL, ring_alloc_size, &paddr); + priv->dma_cfg[ring_idx].base_paddr_unaligned = (void *)paddr; + if (!priv->dma_cfg[ring_idx].base_vaddr_unaligned) { + target_if_err("malloc failed"); + return QDF_STATUS_E_NOMEM; + } + + priv->dma_cfg[ring_idx].base_vaddr_aligned = (void *)qdf_roundup( + (uint64_t)priv->dma_cfg[ring_idx].base_vaddr_unaligned, + RING_BASE_ALIGN); + ring_params.ring_base_vaddr = + priv->dma_cfg[ring_idx].base_vaddr_aligned; + priv->dma_cfg[ring_idx].base_paddr_aligned = (void *)qdf_roundup( + (uint64_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, + RING_BASE_ALIGN); + ring_params.ring_base_paddr = + (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_aligned; + ring_params.num_entries = num_entries; + srng = hal_srng_setup(hal_soc, WIFI_POS_SRC, 0, + priv->dma_cap[ring_idx].pdev_id, &ring_params); + if (!srng) { + target_if_err("srng setup failed"); + return QDF_STATUS_E_FAILURE; + } + priv->dma_cfg[ring_idx].srng = srng; + priv->dma_cfg[ring_idx].tail_idx_addr = + (void *)hal_srng_get_tp_addr(hal_soc, srng); + priv->dma_cfg[ring_idx].head_idx_addr = + (void *)hal_srng_get_tp_addr(hal_soc, srng); + + return target_if_wifi_pos_fill_ring(ring_idx, srng, priv); +} + +static QDF_STATUS target_if_wifi_pos_deinit_ring(uint8_t ring_idx, + struct wifi_pos_psoc_priv_obj *priv) +{ + target_if_wifi_pos_empty_ring(ring_idx, priv); + priv->dma_buf_pool[ring_idx] = NULL; + hal_srng_cleanup(priv->hal_soc, priv->dma_cfg[ring_idx].srng); + qdf_mem_free_consistent(NULL, NULL, + priv->dma_cfg[ring_idx].ring_alloc_size, + priv->dma_cfg[ring_idx].base_vaddr_unaligned, + (qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_unaligned, + 0); + qdf_mem_free(priv->dma_buf_pool[ring_idx]); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_wifi_pos_init_srngs( + struct wifi_pos_psoc_priv_obj *priv) +{ + uint8_t i; + QDF_STATUS status; + + /* allocate memory for num_rings pointers */ + priv->dma_cfg = qdf_mem_malloc(priv->num_rings * + sizeof(struct wifi_pos_dma_rings_cap)); + if (!priv->dma_cfg) { + target_if_err("malloc failed"); + return QDF_STATUS_E_NOMEM; + } + + priv->dma_buf_pool = qdf_mem_malloc(priv->num_rings * + sizeof(struct wifi_pos_dma_buf_info *)); + if (!priv->dma_buf_pool) { + target_if_err("malloc failed"); + return QDF_STATUS_E_NOMEM; + } + + for (i = 0; i < priv->num_rings; i++) { + status = target_if_wifi_pos_init_ring(i, priv); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_err("init for ring[%d] failed", i); + return status; + } + } + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_wifi_pos_deinit_srngs( + struct wifi_pos_psoc_priv_obj *priv) +{ + uint8_t i; + + for (i = 0; i < priv->num_rings; i++) + target_if_wifi_pos_deinit_ring(i, priv); + + qdf_mem_free(priv->dma_buf_pool); + priv->dma_buf_pool = NULL; + return QDF_STATUS_SUCCESS; } static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc, - struct wifi_pos_psoc_priv_obj *priv_obj) + struct wifi_pos_psoc_priv_obj *priv) { + uint8_t i; + QDF_STATUS status; + void *wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); + wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0}; + + if (!wmi_hdl) { + target_if_err("WMA closed, can't send oem data req cmd"); + return QDF_STATUS_E_INVAL; + } + + target_if_debug("Sending oem dma ring cfg to target"); + + for (i = 0; i < priv->num_rings; i++) { + cfg.pdev_id = priv->dma_cfg[i].pdev_id; + cfg.base_addr_lo = (uint64_t)priv->dma_cfg[i].base_paddr_aligned + & 0xFFFFFFFF; + cfg.base_addr_hi = (uint64_t)priv->dma_cfg[i].base_paddr_aligned + & 0xFFFFFFFF00000000; + cfg.head_idx_addr_lo = (uint64_t)priv->dma_cfg[i].head_idx_addr + & 0xFFFFFFFF; + cfg.head_idx_addr_hi = (uint64_t)priv->dma_cfg[i].head_idx_addr + & 0xFFFFFFFF00000000; + cfg.tail_idx_addr_lo = (uint64_t)priv->dma_cfg[i].tail_idx_addr + & 0xFFFFFFFF; + cfg.tail_idx_addr_hi = (uint64_t)priv->dma_cfg[i].tail_idx_addr + & 0xFFFFFFFF00000000; + cfg.num_ptr = priv->dma_cfg[i].num_ptr; + status = wmi_unified_oem_dma_ring_cfg(wmi_hdl, &cfg); + if (!QDF_IS_STATUS_SUCCESS(status)) { + target_if_err("wmi cmd send failed"); + return status; + } + } + + return status; +} + +QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc) +{ + struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); + + target_if_wifi_pos_deinit_srngs(priv); + qdf_mem_free(priv->dma_cap); + priv->dma_cap = NULL; + return QDF_STATUS_SUCCESS; } @@ -293,37 +623,50 @@ QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc, void *buf) { uint8_t i; - struct wifi_pos_psoc_priv_obj *priv_obj = - wifi_pos_get_psoc_priv_obj(psoc); + QDF_STATUS status = QDF_STATUS_SUCCESS; WMI_OEM_DMA_RING_CAPABILITIES *dma_cap = buf; + struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); - if (!priv_obj) { + if (!priv) { target_if_err("unable to get wifi_pos psoc obj"); return QDF_STATUS_E_NULL_VALUE; } - priv_obj->hal_soc = hal_soc; - priv_obj->num_rings = num_mac; - priv_obj->dma_cap = qdf_mem_malloc(priv_obj->num_rings * + priv->hal_soc = hal_soc; + priv->num_rings = num_mac; + priv->dma_cap = qdf_mem_malloc(priv->num_rings * sizeof(struct wifi_pos_dma_rings_cap)); - if (!priv_obj->dma_cap) { + if (!priv->dma_cap) { target_if_err("unable to get wifi_pos psoc obj"); return QDF_STATUS_E_NOMEM; } for (i = 0; i < num_mac; i++) { - priv_obj->dma_cap[i].pdev_id = dma_cap[i].pdev_id; - priv_obj->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr; - priv_obj->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size; - priv_obj->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align; + priv->dma_cap[i].pdev_id = dma_cap[i].pdev_id; + priv->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr; + priv->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size; + priv->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align; } /* initialize DMA rings now */ - target_if_wifi_pos_init_srngs(psoc, hal_soc, priv_obj); + status = target_if_wifi_pos_init_srngs(priv); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_err("dma init failed: %d", status); + goto dma_init_failed; + } /* send cfg req cmd to firmware */ - target_if_wifi_pos_cfg_fw(psoc, priv_obj); + status = target_if_wifi_pos_cfg_fw(psoc, priv); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_err("configure to FW failed: %d", status); + goto dma_init_failed; + } return QDF_STATUS_SUCCESS; + +dma_init_failed: + target_if_wifi_pos_deinit_dma_rings(psoc); + return status; } + #endif diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h index fc33a07c6e52..4e10ad00563b 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h +++ b/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h @@ -200,15 +200,12 @@ enum block_ack_actioncode { /** * enum pub_actioncode - public action frames * @PUB_ACTION_2040_BSS_COEXISTENCE: public 20-40 bss coex action frame - * @PUB_ACTION_P2P_SUBTYPE_PRESENCE_RSP: public p2p subtype presence - * response action frame * @PUB_ACTION_EXT_CHANNEL_SWITCH_ID: public ext channel switch id action frame * @PUB_ACTION_VENDOR_SPECIFIC: vendor specific public action frame * @PUB_ACTION_TDLS_DISCRESP: tdls discovery response public action frame */ enum pub_actioncode { PUB_ACTION_2040_BSS_COEXISTENCE = 0, - PUB_ACTION_P2P_SUBTYPE_PRESENCE_RSP = 2, PUB_ACTION_EXT_CHANNEL_SWITCH_ID = 4, PUB_ACTION_VENDOR_SPECIFIC = 9, PUB_ACTION_TDLS_DISCRESP = 14, @@ -434,7 +431,7 @@ struct action_frm_hdr { * @MGMT_ACTION_BA_ADDBA_RESPONSE: ADDBA response action frame * @MGMT_ACTION_BA_DELBA: DELBA action frame * @MGMT_ACTION_2040_BSS_COEXISTENCE: 20-40 bss coex action frame - * @MGMT_ACTION_P2P_SUBTYPE_PRESENCE_RSP: p2p subtype presence rsp action frame + * @MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC: category vendor spcific action frame * @MGMT_ACTION_EXT_CHANNEL_SWITCH_ID: ext channel switch id action frame * @MGMT_ACTION_VENDOR_SPECIFIC: vendor specific action frame * @MGMT_ACTION_TDLS_DISCRESP: TDLS discovery response frame @@ -529,7 +526,7 @@ enum mgmt_frame_type { MGMT_ACTION_BA_ADDBA_RESPONSE, MGMT_ACTION_BA_DELBA, MGMT_ACTION_2040_BSS_COEXISTENCE, - MGMT_ACTION_P2P_SUBTYPE_PRESENCE_RSP, + MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC, MGMT_ACTION_EXT_CHANNEL_SWITCH_ID, MGMT_ACTION_VENDOR_SPECIFIC, MGMT_ACTION_TDLS_DISCRESP, diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c index 8e1c8aa285d4..747ccd48bb7e 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c +++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c @@ -187,9 +187,6 @@ mgmt_get_public_action_subtype(uint8_t action_code) case PUB_ACTION_2040_BSS_COEXISTENCE: frm_type = MGMT_ACTION_2040_BSS_COEXISTENCE; break; - case PUB_ACTION_P2P_SUBTYPE_PRESENCE_RSP: - frm_type = MGMT_ACTION_P2P_SUBTYPE_PRESENCE_RSP; - break; case PUB_ACTION_EXT_CHANNEL_SWITCH_ID: frm_type = MGMT_ACTION_EXT_CHANNEL_SWITCH_ID; break; @@ -681,6 +678,9 @@ mgmt_txrx_get_action_frm_subtype(uint8_t *mpdu_data_ptr) case ACTION_CATEGORY_VHT: frm_type = mgmt_get_vht_action_subtype(action_hdr->action_code); break; + case ACTION_CATEGORY_VENDOR_SPECIFIC: + frm_type = MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC; + break; default: frm_type = MGMT_FRM_UNSPECIFIED; break; diff --git a/umac/p2p/core/src/wlan_p2p_off_chan_tx.c b/umac/p2p/core/src/wlan_p2p_off_chan_tx.c index 2fe4b6ba6ae8..3831efb029ab 100644 --- a/umac/p2p/core/src/wlan_p2p_off_chan_tx.c +++ b/umac/p2p/core/src/wlan_p2p_off_chan_tx.c @@ -535,6 +535,8 @@ static char *p2p_get_frame_type_str(struct p2p_frame_info *frame_info) return "Invalid P2P command"; } + if (frame_info->action_type == P2P_ACTION_PRESENCE_REQ) + return "P2P action presence request"; if (frame_info->action_type == P2P_ACTION_PRESENCE_RSP) return "P2P action presence response"; @@ -651,6 +653,9 @@ static QDF_STATUS p2p_get_frame_info(uint8_t *data_buf, uint32_t length, buf = data_buf + P2P_ACTION_FRAME_TYPE_OFFSET; action_type = buf[0]; + if (action_type == P2P_ACTION_PRESENCE_REQ) + frame_info->action_type = + P2P_ACTION_PRESENCE_REQ; if (action_type == P2P_ACTION_PRESENCE_RSP) frame_info->action_type = P2P_ACTION_PRESENCE_RSP; @@ -1631,6 +1636,10 @@ QDF_STATUS p2p_process_rx_mgmt( } } + if (rx_mgmt->frm_type == MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC) + p2p_get_frame_info(rx_mgmt->buf, rx_mgmt->frame_len, + &frame_info); + start_param = p2p_soc_obj->start_param; if (start_param->rx_cb) start_param->rx_cb(start_param->rx_cb_data, rx_mgmt); diff --git a/umac/p2p/core/src/wlan_p2p_off_chan_tx.h b/umac/p2p/core/src/wlan_p2p_off_chan_tx.h index eb63fc881d46..8b255e71f699 100644 --- a/umac/p2p/core/src/wlan_p2p_off_chan_tx.h +++ b/umac/p2p/core/src/wlan_p2p_off_chan_tx.h @@ -121,10 +121,12 @@ enum p2p_public_action_type { /** * enum p2p_action_type - p2p action frame type + * @P2P_ACTION_PRESENCE_REQ: presence request frame * @P2P_ACTION_PRESENCE_RSP: presence response frame * @P2P_ACTION_NOT_SUPPORT: not support action frame type */ enum p2p_action_type { + P2P_ACTION_PRESENCE_REQ = 1, P2P_ACTION_PRESENCE_RSP = 2, P2P_ACTION_NOT_SUPPORT, }; diff --git a/umac/p2p/core/src/wlan_p2p_roc.c b/umac/p2p/core/src/wlan_p2p_roc.c index cff85f4e2a38..e83914d1c300 100644 --- a/umac/p2p/core/src/wlan_p2p_roc.c +++ b/umac/p2p/core/src/wlan_p2p_roc.c @@ -545,20 +545,22 @@ static QDF_STATUS p2p_process_scan_complete_evt( QDF_STATUS p2p_mgmt_rx_action_ops(struct wlan_objmgr_psoc *psoc, bool isregister) { - struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info; + struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info[2]; QDF_STATUS status; p2p_debug("psoc:%p, is register rx:%d", psoc, isregister); - frm_cb_info.frm_type = MGMT_ACTION_VENDOR_SPECIFIC; - frm_cb_info.mgmt_rx_cb = tgt_p2p_mgmt_frame_rx_cb; + frm_cb_info[0].frm_type = MGMT_ACTION_VENDOR_SPECIFIC; + frm_cb_info[0].mgmt_rx_cb = tgt_p2p_mgmt_frame_rx_cb; + frm_cb_info[1].frm_type = MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC; + frm_cb_info[1].mgmt_rx_cb = tgt_p2p_mgmt_frame_rx_cb; if (isregister) status = wlan_mgmt_txrx_register_rx_cb(psoc, - WLAN_UMAC_COMP_P2P, &frm_cb_info, 1); + WLAN_UMAC_COMP_P2P, frm_cb_info, 2); else status = wlan_mgmt_txrx_deregister_rx_cb(psoc, - WLAN_UMAC_COMP_P2P, &frm_cb_info, 1); + WLAN_UMAC_COMP_P2P, frm_cb_info, 2); return status; } diff --git a/umac/wifi_pos/src/wifi_pos_main.c b/umac/wifi_pos/src/wifi_pos_main.c index 1c15452a4fcb..3feef52a099d 100644 --- a/umac/wifi_pos/src/wifi_pos_main.c +++ b/umac/wifi_pos/src/wifi_pos_main.c @@ -447,6 +447,8 @@ QDF_STATUS wifi_pos_psoc_obj_destroyed_notification( return QDF_STATUS_E_FAULT; } + target_if_wifi_pos_deinit_dma_rings(psoc); + status = wlan_objmgr_psoc_component_obj_detach(psoc, WLAN_UMAC_COMP_WIFI_POS, wifi_pos_obj); @@ -463,20 +465,52 @@ QDF_STATUS wifi_pos_psoc_obj_destroyed_notification( int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc, struct oem_data_rsp *oem_rsp) { - struct wifi_pos_psoc_priv_obj *wifi_pos_obj = + uint32_t len; + uint8_t *data; + uint32_t app_pid; + struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); - /* handle oem event here */ - if (oem_rsp->rsp_len > OEM_DATA_RSP_SIZE) { + void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *); + + if (!priv) { + wifi_pos_err("private object is NULL"); + return -EINVAL; + } + + qdf_spin_lock_bh(&priv->wifi_pos_lock); + app_pid = priv->app_pid; + wifi_pos_send_rsp = priv->wifi_pos_send_rsp; + qdf_spin_unlock_bh(&priv->wifi_pos_lock); + + len = oem_rsp->rsp_len_1 + oem_rsp->rsp_len_2 + oem_rsp->dma_len; + if (oem_rsp->rsp_len_1 > OEM_DATA_RSP_SIZE || + oem_rsp->rsp_len_2 > OEM_DATA_RSP_SIZE) { wifi_pos_err("invalid length of Oem Data response"); return -EINVAL; } - wifi_pos_debug("sending oem data rsp, len: %d to pid: %d", - oem_rsp->rsp_len, wifi_pos_obj->app_pid); - wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, - ANI_MSG_OEM_DATA_RSP, - oem_rsp->rsp_len, - oem_rsp->data); + wifi_pos_debug("oem data rsp, len: %d to pid: %d", len, app_pid); + + if (oem_rsp->rsp_len_2 + oem_rsp->dma_len) { + /* stitch togther the msg data_1 + CIR/CFR + data_2 */ + data = qdf_mem_malloc(len); + if (!data) { + wifi_pos_err("malloc failed"); + return -ENOMEM; + } + qdf_mem_copy(data, oem_rsp->data_1, oem_rsp->rsp_len_1); + qdf_mem_copy(&data[oem_rsp->rsp_len_1], + oem_rsp->vaddr, oem_rsp->dma_len); + qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len], + oem_rsp->data_2, oem_rsp->rsp_len_2); + + wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, len, data); + qdf_mem_free(data); + } else { + wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, + oem_rsp->rsp_len_1, oem_rsp->data_1); + } + return 0; } diff --git a/umac/wifi_pos/src/wifi_pos_utils_i.h b/umac/wifi_pos/src/wifi_pos_utils_i.h index fed26984dc8c..4ee74adb90ee 100644 --- a/umac/wifi_pos/src/wifi_pos_utils_i.h +++ b/umac/wifi_pos/src/wifi_pos_utils_i.h @@ -106,13 +106,21 @@ struct oem_data_req { /** * struct oem_data_rsp - response from firmware to data request sent earlier - * @data_len: len of data - * @data: buffer containing data + * @rsp_len_1: len of data_1 + * @data_1: first part of payload + * @rsp_len_2: len of data_2 + * @data_2: second part of payload + * @dma_len: len of DMAed data + * @vaddr: virtual address of DMA data start * */ struct oem_data_rsp { - uint32_t rsp_len; - uint8_t *data; + uint32_t rsp_len_1; + uint8_t *data_1; + uint32_t rsp_len_2; + uint8_t *data_2; + uint32_t dma_len; + void *vaddr; }; /** @@ -196,26 +204,44 @@ struct wifi_pos_dma_rings_cap { uint32_t min_buf_align; }; +/** + * struct wifi_pos_dma_buf_info - buffer info struct containing phy to virtual + * mapping. + * @cookie: this identifies location of DMA buffer in pool array + * @paddr: aligned physical address as exchanged with firmware + * @vaddr: virtual address - unaligned. this helps in freeing later + * @offset: offset of aligned address from unaligned + */ +struct wifi_pos_dma_buf_info { + uint32_t cookie; + void *paddr; + void *vaddr; + uint8_t offset; +}; + /** * struct wifi_pos_dma_rings_cfg - DMA ring parameters to be programmed to FW. * @pdev_id: pdev_id of ring - * @base_addr_lo: Base address of ring, bits 31:0 - * @base_addr_hi: Base address of ring, bits 63:32 - * @head_idx_addr_lo: Address of head index register, bits 31:0 - * @head_idx_addr_hi: Address of head index register, bits 63:32 - * @tail_idx_addr_lo: Address of tail index register, bits 31:0 - * @tail_idx_addr_hi: Address of tail index register, bits 63:32 - * @num_ptr: Number of pointers in the ring + * @num_ptr: depth of ring + * @base_paddr_unaligned: base physical addr unaligned + * @base_vaddr_unaligned: base virtual addr unaligned + * @base_paddr_aligned: base physical addr aligned + * @base_vaddr_aligned: base virtual addr unaligned + * @head_idx_addr: head index addr + * @tail_idx_addr: tail index addr + * @srng: hal srng */ struct wifi_pos_dma_rings_cfg { uint32_t pdev_id; - uint32_t base_addr_lo; - uint32_t base_addr_hi; - uint32_t head_idx_addr_lo; - uint32_t head_idx_addr_hi; - uint32_t tail_idx_addr_lo; - uint32_t tail_idx_addr_hi; uint32_t num_ptr; + uint32_t ring_alloc_size; + void *base_paddr_unaligned; + void *base_vaddr_unaligned; + void *base_paddr_aligned; + void *base_vaddr_aligned; + void *head_idx_addr; + void *tail_idx_addr; + void *srng; }; /** @@ -234,9 +260,11 @@ struct wifi_pos_dma_rings_cfg { * @allowed_dwell_time_max: allowed dwell time max, populated from HDD * @current_dwell_time_min: current dwell time min, populated from HDD * @current_dwell_time_max: current dwell time max, populated from HDD + * @hal_soc: hal_soc * @num_rings: DMA ring cap requested by firmware * @dma_cap: dma cap as read from service ready ext event * @dma_cfg: DMA ring cfg to be programmed to firmware + * @dma_buf_pool: DMA buffer pools maintained at host: this will be 2-D array * where with num_rows = number of rings num_elements in each row = ring depth * @wifi_pos_lock: lock to access wifi pos priv object * @wifi_pos_req_handler: function pointer to handle TLV or non-TLV @@ -269,9 +297,11 @@ struct wifi_pos_psoc_priv_obj { uint16_t current_dwell_time_min; uint16_t current_dwell_time_max; + void *hal_soc; uint8_t num_rings; struct wifi_pos_dma_rings_cap *dma_cap; struct wifi_pos_dma_rings_cfg *dma_cfg; + struct wifi_pos_dma_buf_info **dma_buf_pool; qdf_spinlock_t wifi_pos_lock; QDF_STATUS (*wifi_pos_req_handler)(struct wlan_objmgr_psoc *psoc, diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 504ecc03cf79..66d3de25c77b 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -719,6 +719,19 @@ QDF_STATUS wmi_unified_nat_keepalive_en_cmd(void *wmi_hdl, uint8_t vdev_id); QDF_STATUS wmi_unified_csa_offload_enable(void *wmi_hdl, uint8_t vdev_id); +#ifdef WLAN_FEATURE_CIF_CFR +/** + * wmi_unified_oem_dma_ring_cfg() - configure OEM DMA rings + * @wmi_handle: wmi handle + * @data_len: len of dma cfg req + * @data: dma cfg req + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_oem_dma_ring_cfg(void *wmi_hdl, + wmi_oem_dma_ring_cfg_req_fixed_param *cfg); +#endif + QDF_STATUS wmi_unified_start_oem_data_cmd(void *wmi_hdl, uint32_t data_len, uint8_t *data); diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index a1547d2a566c..56c52a2395c5 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -593,6 +593,11 @@ QDF_STATUS (*send_fw_profiling_cmd)(wmi_unified_t wmi_handle, QDF_STATUS (*send_nat_keepalive_en_cmd)(wmi_unified_t wmi_handle, uint8_t vdev_id); +#ifdef WLAN_FEATURE_CIF_CFR +QDF_STATUS (*send_oem_dma_cfg_cmd)(wmi_unified_t wmi_handle, + wmi_oem_dma_ring_cfg_req_fixed_param *cfg); +#endif + QDF_STATUS (*send_start_oem_data_cmd)(wmi_unified_t wmi_handle, uint32_t data_len, uint8_t *data); diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 3de36cc1be72..bf405cf4390b 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -2258,6 +2258,20 @@ QDF_STATUS wmi_unified_csa_offload_enable(void *wmi_hdl, uint8_t vdev_id) return QDF_STATUS_E_FAILURE; } + +#ifdef WLAN_FEATURE_CIF_CFR +QDF_STATUS wmi_unified_oem_dma_ring_cfg(void *wmi_hdl, + wmi_oem_dma_ring_cfg_req_fixed_param *cfg) +{ + wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl; + + if (wmi_handle->ops->send_start_oem_data_cmd) + return wmi_handle->ops->send_oem_dma_cfg_cmd(wmi_handle, cfg); + + return QDF_STATUS_E_FAILURE; +} +#endif + /** * wmi_unified_start_oem_data_cmd() - start OEM data request to target * @wmi_handle: wmi handle diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index c7b007d2e631..7b62eef2cfef 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -7915,6 +7915,47 @@ static QDF_STATUS send_csa_offload_enable_cmd_tlv(wmi_unified_t wmi_handle, return 0; } +#ifdef WLAN_FEATURE_CIF_CFR +/** + * send_oem_dma_cfg_cmd_tlv() - configure OEM DMA rings + * @wmi_handle: wmi handle + * @data_len: len of dma cfg req + * @data: dma cfg req + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +static QDF_STATUS send_oem_dma_cfg_cmd_tlv(wmi_unified_t wmi_handle, + wmi_oem_dma_ring_cfg_req_fixed_param *cfg) +{ + wmi_buf_t buf; + uint8_t *cmd; + QDF_STATUS ret; + + WMITLV_SET_HDR(cfg, + WMITLV_TAG_STRUC_wmi_oem_dma_ring_cfg_req_fixed_param, + (sizeof(*cfg) - WMI_TLV_HDR_SIZE)); + + buf = wmi_buf_alloc(wmi_handle, sizeof(*cfg)); + if (!buf) { + WMI_LOGE(FL("wmi_buf_alloc failed")); + return QDF_STATUS_E_FAILURE; + } + + cmd = (uint8_t *) wmi_buf_data(buf); + qdf_mem_copy(cmd, cfg, sizeof(*cfg)); + WMI_LOGI(FL("Sending OEM Data Request to target, data len %lu"), + sizeof(*cfg)); + ret = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cfg), + WMI_OEM_DMA_RING_CFG_REQ_CMDID); + if (QDF_IS_STATUS_ERROR(ret)) { + WMI_LOGE(FL(":wmi cmd send failed")); + wmi_buf_free(buf); + } + + return ret; +} +#endif + /** * send_start_oem_data_cmd_tlv() - start OEM data request to target * @wmi_handle: wmi handle @@ -17739,6 +17780,9 @@ struct wmi_ops tlv_ops = { .send_csa_offload_enable_cmd = send_csa_offload_enable_cmd_tlv, .send_nat_keepalive_en_cmd = send_nat_keepalive_en_cmd_tlv, .send_start_oem_data_cmd = send_start_oem_data_cmd_tlv, +#ifdef WLAN_FEATURE_CIF_CFR + .send_oem_dma_cfg_cmd = send_oem_dma_cfg_cmd_tlv, +#endif .send_dfs_phyerr_filter_offload_en_cmd = send_dfs_phyerr_filter_offload_en_cmd_tlv, .send_wow_delete_pattern_cmd = send_wow_delete_pattern_cmd_tlv,