diff --git a/target_if/direct_buf_rx/inc/target_if_direct_buf_rx_api.h b/target_if/direct_buf_rx/inc/target_if_direct_buf_rx_api.h index 54669c5974be..a3065a041c74 100644 --- a/target_if/direct_buf_rx/inc/target_if_direct_buf_rx_api.h +++ b/target_if/direct_buf_rx/inc/target_if_direct_buf_rx_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -60,12 +60,16 @@ struct wlan_lmac_if_tx_ops; * struct direct_buf_rx_data - direct buffer rx data * @dbr_len: Length of the buffer DMAed * @vaddr: Virtual address of the buffer that has DMAed data + * @cookie: Cookie for the buffer rxed from target + * @paddr: physical address of buffer corresponding to vaddr * @meta_data_valid: Indicates that metadata is valid * @meta_data: Meta data */ struct direct_buf_rx_data { size_t dbr_len; void *vaddr; + uint32_t cookie; + qdf_dma_addr_t paddr; bool meta_data_valid; struct direct_buf_rx_metadata meta_data; }; @@ -105,4 +109,31 @@ QDF_STATUS direct_buf_rx_target_attach(struct wlan_objmgr_psoc *psoc, void target_if_direct_buf_rx_register_tx_ops( struct wlan_lmac_if_tx_ops *tx_ops); +/** + * target_if_dbr_cookie_lookup() - Function to retrieve cookie from + * buffer address(paddr) + * @pdev: pointer to pdev object + * @mod_id: module id indicating the module using direct buffer rx framework + * @paddr: Physical address of buffer for which cookie info is required + * @cookie: cookie will be returned in this param + * + * Return: QDF status of operation + */ +QDF_STATUS target_if_dbr_cookie_lookup(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, qdf_dma_addr_t paddr, + uint32_t *cookie); + +/** + * target_if_dbr_buf_release() - Notify direct buf that a previously provided + * buffer can be released. + * @pdev: pointer to pdev object + * @mod_id: module id indicating the module using direct buffer rx framework + * @paddr: Physical address of buffer for which cookie info is required + * @cookie: cookie value corresponding to the paddr + * + * Return: QDF status of operation + */ +QDF_STATUS target_if_dbr_buf_release(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, qdf_dma_addr_t paddr, + uint32_t cookie); #endif /* _TARGET_IF_DIRECT_BUF_RX_API_H_ */ diff --git a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c b/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c index 3d2ddb9b90c2..123b159d48e7 100644 --- a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c +++ b/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c @@ -670,8 +670,9 @@ dbr_srng_init_failed: QDF_STATUS target_if_direct_buf_rx_module_register( struct wlan_objmgr_pdev *pdev, uint8_t mod_id, - int (*dbr_rsp_handler)(struct wlan_objmgr_pdev *pdev, - struct direct_buf_rx_data *dbr_data)) + bool (*dbr_rsp_handler) + (struct wlan_objmgr_pdev *pdev, + struct direct_buf_rx_data *dbr_data)) { QDF_STATUS status; struct direct_buf_rx_pdev_obj *dbr_pdev_obj; @@ -779,6 +780,79 @@ static void *target_if_dbr_vaddr_lookup( return NULL; } +QDF_STATUS target_if_dbr_cookie_lookup(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, qdf_dma_addr_t paddr, + uint32_t *cookie) +{ + struct direct_buf_rx_buf_info *dbr_buf_pool; + struct direct_buf_rx_ring_cfg *dbr_ring_cfg; + struct direct_buf_rx_pdev_obj *dbr_pdev_obj; + struct direct_buf_rx_module_param *mod_param; + enum wlan_umac_comp_id dbr_comp_id = WLAN_TARGET_IF_COMP_DIRECT_BUF_RX; + uint32_t idx; + + dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, dbr_comp_id); + if (!dbr_pdev_obj) { + direct_buf_rx_err("dir buf rx object is null"); + return QDF_STATUS_E_FAILURE; + } + + mod_param = &dbr_pdev_obj->dbr_mod_param[mod_id]; + if (!mod_param) { + direct_buf_rx_err("dir buf rx module param is null"); + return QDF_STATUS_E_FAILURE; + } + + dbr_ring_cfg = mod_param->dbr_ring_cfg; + dbr_buf_pool = mod_param->dbr_buf_pool; + + for (idx = 0; idx < dbr_ring_cfg->num_ptr - 1; idx++) { + if (dbr_buf_pool[idx].paddr && + dbr_buf_pool[idx].paddr == paddr) { + *cookie = idx; + return QDF_STATUS_SUCCESS; + } + } + + return QDF_STATUS_E_FAILURE; +} + +QDF_STATUS target_if_dbr_buf_release(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, qdf_dma_addr_t paddr, + uint32_t cookie) +{ + struct direct_buf_rx_module_param *mod_param; + struct direct_buf_rx_pdev_obj *dbr_pdev_obj; + enum wlan_umac_comp_id dbr_comp_id = WLAN_TARGET_IF_COMP_DIRECT_BUF_RX; + void *vaddr; + QDF_STATUS status; + + dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev, dbr_comp_id); + if (!dbr_pdev_obj) { + direct_buf_rx_err("dir buf rx object is null"); + return QDF_STATUS_E_FAILURE; + } + + mod_param = &dbr_pdev_obj->dbr_mod_param[mod_id]; + if (!mod_param) { + direct_buf_rx_err("dir buf rx module param is null"); + return QDF_STATUS_E_FAILURE; + } + + vaddr = target_if_dbr_vaddr_lookup(mod_param, paddr, cookie); + if (!vaddr) + return QDF_STATUS_E_FAILURE; + + status = target_if_dbr_replenish_ring(pdev, mod_param, + vaddr, cookie); + if (QDF_IS_STATUS_ERROR(status)) { + direct_buf_rx_err("Ring replenish failed"); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + static QDF_STATUS target_if_get_dbr_data(struct wlan_objmgr_pdev *pdev, struct direct_buf_rx_module_param *mod_param, struct direct_buf_rx_rsp *dbr_rsp, @@ -814,6 +888,8 @@ static QDF_STATUS target_if_get_dbr_data(struct wlan_objmgr_pdev *pdev, dbr_rsp->dbr_entries[idx].paddr_hi); direct_buf_rx_info("Cookie = %d", *cookie); dbr_data->vaddr = target_if_dbr_vaddr_lookup(mod_param, paddr, *cookie); + dbr_data->cookie = *cookie; + dbr_data->paddr = paddr; direct_buf_rx_info("Vaddr look up = %x", dbr_data->vaddr); dbr_data->dbr_len = dbr_rsp->dbr_entries[idx].len; qdf_mem_unmap_nbytes_single(dbr_psoc_obj->osdev, (qdf_dma_addr_t)paddr, @@ -839,6 +915,7 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, struct direct_buf_rx_pdev_obj *dbr_pdev_obj; struct direct_buf_rx_module_param *mod_param; struct common_wmi_handle *wmi_handle; + wlan_objmgr_ref_dbgid dbr_mod_id = WLAN_DIRECT_BUF_RX_ID; direct_buf_rx_enter(); @@ -863,11 +940,9 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, direct_buf_rx_info("Num buf release entry = %d", dbr_rsp.num_buf_release_entry); - pdev = wlan_objmgr_get_pdev_by_id(psoc, dbr_rsp.pdev_id, - WLAN_DIRECT_BUF_RX_ID); + pdev = wlan_objmgr_get_pdev_by_id(psoc, dbr_rsp.pdev_id, dbr_mod_id); if (!pdev) { direct_buf_rx_err("pdev is null"); - wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); return QDF_STATUS_E_INVAL; } @@ -876,7 +951,7 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, if (dbr_pdev_obj == NULL) { direct_buf_rx_err("dir buf rx object is null"); - wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); + wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id); return QDF_STATUS_E_FAILURE; } @@ -884,7 +959,7 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, if (!mod_param) { direct_buf_rx_err("dir buf rx module param is null"); - wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); + wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id); return QDF_STATUS_E_FAILURE; } @@ -894,8 +969,7 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, if (dbr_rsp.num_meta_data_entry > dbr_rsp.num_buf_release_entry) { direct_buf_rx_err("More than expected number of metadata"); - wlan_objmgr_pdev_release_ref(pdev, - WLAN_DIRECT_BUF_RX_ID); + wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id); return QDF_STATUS_E_FAILURE; } @@ -906,8 +980,7 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, direct_buf_rx_err("Unable to extract DBR buf entry %d", i+1); qdf_mem_free(dbr_rsp.dbr_entries); - wlan_objmgr_pdev_release_ref(pdev, - WLAN_DIRECT_BUF_RX_ID); + wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id); return QDF_STATUS_E_FAILURE; } status = target_if_get_dbr_data(pdev, mod_param, &dbr_rsp, @@ -916,8 +989,7 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, if (QDF_IS_STATUS_ERROR(status)) { direct_buf_rx_err("DBR data get failed"); qdf_mem_free(dbr_rsp.dbr_entries); - wlan_objmgr_pdev_release_ref(pdev, - WLAN_DIRECT_BUF_RX_ID); + wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id); return QDF_STATUS_E_FAILURE; } @@ -928,20 +1000,21 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, &dbr_data.meta_data) == QDF_STATUS_SUCCESS) dbr_data.meta_data_valid = true; } - ret = mod_param->dbr_rsp_handler(pdev, &dbr_data); - status = target_if_dbr_replenish_ring(pdev, mod_param, - dbr_data.vaddr, cookie); - if (QDF_IS_STATUS_ERROR(status)) { - direct_buf_rx_err("dir buf rx ring replenish failed"); - qdf_mem_free(dbr_rsp.dbr_entries); - wlan_objmgr_pdev_release_ref(pdev, - WLAN_DIRECT_BUF_RX_ID); - return QDF_STATUS_E_FAILURE; + if (mod_param->dbr_rsp_handler(pdev, &dbr_data)) { + status = target_if_dbr_replenish_ring(pdev, mod_param, + dbr_data.vaddr, + cookie); + if (QDF_IS_STATUS_ERROR(status)) { + direct_buf_rx_err("Ring replenish failed"); + qdf_mem_free(dbr_rsp.dbr_entries); + wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id); + return QDF_STATUS_E_FAILURE; + } } } qdf_mem_free(dbr_rsp.dbr_entries); - wlan_objmgr_pdev_release_ref(pdev, WLAN_DIRECT_BUF_RX_ID); + wlan_objmgr_pdev_release_ref(pdev, dbr_mod_id); return ret; } diff --git a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h b/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h index d38108ce1960..13aad5e6901f 100644 --- a/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h +++ b/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h @@ -106,8 +106,8 @@ struct direct_buf_rx_module_param { struct direct_buf_rx_ring_cap *dbr_ring_cap; struct direct_buf_rx_ring_cfg *dbr_ring_cfg; struct direct_buf_rx_buf_info *dbr_buf_pool; - int (*dbr_rsp_handler)(struct wlan_objmgr_pdev *pdev, - struct direct_buf_rx_data *dbr_data); + bool (*dbr_rsp_handler)(struct wlan_objmgr_pdev *pdev, + struct direct_buf_rx_data *dbr_data); }; /** @@ -241,8 +241,9 @@ QDF_STATUS target_if_deinit_dbr_ring(struct wlan_objmgr_pdev *pdev, */ QDF_STATUS target_if_direct_buf_rx_module_register( struct wlan_objmgr_pdev *pdev, uint8_t mod_id, - int (*dbr_rsp_handler)(struct wlan_objmgr_pdev *pdev, - struct direct_buf_rx_data *dbr_data)); + bool (*dbr_rsp_handler) + (struct wlan_objmgr_pdev *pdev, + struct direct_buf_rx_data *dbr_data)); /** * target_if_direct_buf_rx_module_unregister() - Function to unregister to