diff --git a/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h b/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h index 7c5aa130224a..6186a5c7b152 100644 --- a/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h +++ b/components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -25,6 +25,7 @@ #include #include "include/wlan_vdev_mlme.h" #include "wlan_mlme_main.h" +#include "wma_if.h" /** * mlme_register_mlme_ext_ops() - Register mlme ext ops @@ -287,4 +288,38 @@ QDF_STATUS mlme_vdev_create_send(struct wlan_objmgr_vdev *vdev); * to firmware or QDF_STATUS_E_** when there is a failure. */ QDF_STATUS mlme_vdev_self_peer_create(struct wlan_objmgr_vdev *vdev); + +/** + * mlme_vdev_self_peer_delete() - function to delete vdev self peer + * @self_peer_del_msg: scheduler message containing the del_vdev_params + * + * Return: QDF_STATUS_SUCCESS when the self peer is successfully deleted + * to firmware or QDF_STATUS_E_** when there is a failure. + */ +QDF_STATUS mlme_vdev_self_peer_delete(struct scheduler_msg *self_peer_del_msg); + +/** + * mlme_vdev_uses_self_peer() - send vdev del resp to Upper layer + * @vdev_type: params of del vdev response + * + * Return: boolean + */ +bool mlme_vdev_uses_self_peer(uint32_t vdev_type, uint32_t vdev_subtype); + +/** + * mlme_vdev_self_peer_delete_resp() - send vdev self peer delete resp to Upper + * layer + * @param: params of del vdev response + * + * Return: none + */ +void mlme_vdev_self_peer_delete_resp(struct del_vdev_params *param); + +/** + * mlme_vdev_del_resp() - send vdev delete resp to Upper layer + * @vdev_id: vdev id for which del vdev response is received + * + * Return: none + */ +void mlme_vdev_del_resp(uint8_t vdev_id); #endif diff --git a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c index bd9636e2fcb6..1812ef15bff2 100644 --- a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c +++ b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c @@ -22,6 +22,7 @@ #include "wlan_mlme_vdev_mgr_interface.h" #include "lim_utils.h" #include "wma_api.h" +#include "wma.h" #include "lim_types.h" #include #include <../../core/src/vdev_mgr_ops.h> @@ -924,11 +925,23 @@ QDF_STATUS vdevmgr_mlme_ext_hdl_create(struct vdev_mlme_obj *vdev_mlme) static QDF_STATUS vdevmgr_mlme_ext_hdl_destroy(struct vdev_mlme_obj *vdev_mlme) { - mlme_legacy_debug("vdev id = %d ", - vdev_mlme->vdev->vdev_objmgr.vdev_id); + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct vdev_delete_response rsp; + uint8_t vdev_id; + + vdev_id = vdev_mlme->vdev->vdev_objmgr.vdev_id; + mlme_legacy_debug("Sending vdev delete to firmware for vdev id = %d ", + vdev_id); if (!vdev_mlme->ext_vdev_ptr) - return QDF_STATUS_E_FAILURE; + return status; + + status = vdev_mgr_delete_send(vdev_mlme); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("Failed to send vdev delete to firmware"); + rsp.vdev_id = vdev_id; + wma_vdev_detach_callback(&rsp); + } mlme_free_self_disconnect_ies(vdev_mlme->vdev); mlme_free_peer_disconnect_ies(vdev_mlme->vdev); @@ -1280,6 +1293,73 @@ QDF_STATUS vdevmgr_mlme_ext_post_hdl_create(struct vdev_mlme_obj *vdev_mlme) return status; } +bool mlme_vdev_uses_self_peer(uint32_t vdev_type, uint32_t vdev_subtype) +{ + switch (vdev_type) { + case WMI_VDEV_TYPE_AP: + return vdev_subtype == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE; + + case WMI_VDEV_TYPE_MONITOR: + case WMI_VDEV_TYPE_OCB: + return true; + + default: + return false; + } +} + +void mlme_vdev_del_resp(uint8_t vdev_id) +{ + sme_vdev_del_resp(vdev_id); +} + +static +QDF_STATUS mlme_vdev_self_peer_delete_resp_flush_cb(struct scheduler_msg *msg) +{ + /* + * sme should be the last component to hold the reference invoke the + * same to release the reference gracefully + */ + sme_vdev_self_peer_delete_resp(msg->bodyptr); + return QDF_STATUS_SUCCESS; +} + +void mlme_vdev_self_peer_delete_resp(struct del_vdev_params *param) +{ + struct scheduler_msg peer_del_rsp = {0}; + QDF_STATUS status; + + peer_del_rsp.type = eWNI_SME_VDEV_DELETE_RSP; + peer_del_rsp.bodyptr = param; + peer_del_rsp.flush_callback = mlme_vdev_self_peer_delete_resp_flush_cb; + + status = scheduler_post_message(QDF_MODULE_ID_MLME, + QDF_MODULE_ID_SME, + QDF_MODULE_ID_SME, &peer_del_rsp); + if (!QDF_IS_STATUS_SUCCESS(status)) { + /* In the error cases release the final sme referene */ + wlan_objmgr_vdev_release_ref(param->vdev, WLAN_LEGACY_SME_ID); + qdf_mem_free(param); + } +} + +QDF_STATUS mlme_vdev_self_peer_delete(struct scheduler_msg *self_peer_del_msg) +{ + QDF_STATUS status; + struct del_vdev_params *del_vdev = self_peer_del_msg->bodyptr; + + if (!del_vdev) { + mlme_err("Invalid del self peer params"); + return QDF_STATUS_E_INVAL; + } + + status = wma_vdev_detach(del_vdev); + if (QDF_IS_STATUS_ERROR(status)) + mlme_err("Failed to detach vdev"); + + return status; +} + /** * struct sta_mlme_ops - VDEV MLME operation callbacks strucutre for sta * @mlme_vdev_start_send: callback to initiate actions of VDEV diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index acdaea82bf09..b9b425a7ae24 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4758,6 +4758,9 @@ QDF_STATUS hdd_sme_close_session_callback(uint8_t vdev_id) } clear_bit(SME_SESSION_OPENED, &adapter->event_flags); + qdf_spin_lock_bh(&adapter->vdev_lock); + adapter->vdev_id = WLAN_UMAC_VDEV_ID_MAX; + qdf_spin_unlock_bh(&adapter->vdev_lock); /* * We can be blocked while waiting for scheduled work to be @@ -4806,7 +4809,6 @@ int hdd_vdev_ready(struct hdd_adapter *adapter) int hdd_vdev_destroy(struct hdd_adapter *adapter) { QDF_STATUS status; - int errno; struct hdd_context *hdd_ctx; uint8_t vdev_id; struct wlan_objmgr_vdev *vdev; @@ -4847,12 +4849,19 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter) /* Disable serialization for vdev before sending vdev delete */ wlan_ser_vdev_queue_disable(adapter->vdev); + qdf_spin_lock_bh(&adapter->vdev_lock); + adapter->vdev = NULL; + qdf_spin_unlock_bh(&adapter->vdev_lock); + + /* Release the hdd reference */ + wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR); + /* close sme session (destroy vdev in firmware via legacy API) */ INIT_COMPLETION(adapter->vdev_destroy_event); status = sme_vdev_delete(hdd_ctx->mac_handle, vdev); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("failed to delete vdev; status:%d", status); - goto release_vdev; + goto send_status; } /* block on a completion variable until sme session is closed */ @@ -4868,18 +4877,10 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter) } } -release_vdev: - - /* do vdev logical destroy via objmgr */ - errno = hdd_objmgr_release_and_destroy_vdev(adapter); - if (errno) { - hdd_err("failed to destroy objmgr vdev; errno:%d", errno); - return errno; - } - hdd_nofl_debug("vdev %d destroyed successfully", vdev_id); - return 0; +send_status: + return qdf_status_to_os_return(status); } void @@ -4940,7 +4941,7 @@ hdd_init_vdev_os_priv(struct hdd_adapter *adapter) int hdd_vdev_create(struct hdd_adapter *adapter) { QDF_STATUS status; - int errno; + int errno = 0; bool bval; struct hdd_context *hdd_ctx; struct wlan_objmgr_vdev *vdev; @@ -4981,16 +4982,22 @@ int hdd_vdev_create(struct hdd_adapter *adapter) QDF_STATUS_SUCCESS) { errno = QDF_STATUS_E_INVAL; sme_vdev_delete(hdd_ctx->mac_handle, vdev); - wlan_objmgr_vdev_obj_delete(vdev); return -EINVAL; } - set_bit(SME_SESSION_OPENED, &adapter->event_flags); qdf_spin_lock_bh(&adapter->vdev_lock); adapter->vdev_id = wlan_vdev_get_id(vdev); adapter->vdev = vdev; qdf_spin_unlock_bh(&adapter->vdev_lock); + set_bit(SME_SESSION_OPENED, &adapter->event_flags); + status = sme_vdev_post_vdev_create_setup(hdd_ctx->mac_handle, vdev); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to setup the vdev"); + errno = qdf_status_to_os_return(status); + goto hdd_vdev_destroy_procedure; + } + /* firmware ready for component communication, raise vdev_ready event */ errno = hdd_vdev_ready(adapter); if (errno) { @@ -5035,7 +5042,7 @@ int hdd_vdev_create(struct hdd_adapter *adapter) hdd_nofl_debug("vdev %d created successfully", adapter->vdev_id); - return 0; + return errno; hdd_vdev_destroy_procedure: QDF_BUG(!hdd_vdev_destroy(adapter)); @@ -6658,7 +6665,7 @@ QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx) adapter->device_mode != QDF_P2P_GO_MODE && adapter->device_mode != QDF_FTM_MODE) hdd_set_disconnect_status(adapter, false); - + hdd_debug("Flush any mgmt references held by peer"); hdd_stop_adapter(hdd_ctx, adapter); } diff --git a/core/hdd/src/wlan_hdd_object_manager.c b/core/hdd/src/wlan_hdd_object_manager.c index 9563c3aa6f3e..be626202026e 100644 --- a/core/hdd/src/wlan_hdd_object_manager.c +++ b/core/hdd/src/wlan_hdd_object_manager.c @@ -214,28 +214,6 @@ int hdd_objmgr_release_and_destroy_pdev(struct hdd_context *hdd_ctx) return qdf_status_to_os_return(status); } - -int hdd_objmgr_release_and_destroy_vdev(struct hdd_adapter *adapter) -{ - QDF_STATUS status; - struct wlan_objmgr_vdev *vdev; - - qdf_spin_lock_bh(&adapter->vdev_lock); - vdev = adapter->vdev; - adapter->vdev = NULL; - adapter->vdev_id = WLAN_UMAC_VDEV_ID_MAX; - qdf_spin_unlock_bh(&adapter->vdev_lock); - - QDF_BUG(vdev); - if (!vdev) - return -EINVAL; - - status = wlan_objmgr_vdev_obj_delete(vdev); - wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR); - - return qdf_status_to_os_return(status); -} - struct wlan_objmgr_vdev *__hdd_objmgr_get_vdev(struct hdd_adapter *adapter, const char *func) { diff --git a/core/hdd/src/wlan_hdd_object_manager.h b/core/hdd/src/wlan_hdd_object_manager.h index cf877677b77a..9ac1c6adb64c 100644 --- a/core/hdd/src/wlan_hdd_object_manager.h +++ b/core/hdd/src/wlan_hdd_object_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -109,16 +109,6 @@ int hdd_objmgr_create_and_store_pdev(struct hdd_context *hdd_ctx); */ int hdd_objmgr_release_and_destroy_pdev(struct hdd_context *hdd_ctx); -/** - * hdd_objmgr_release_and_destroy_vdev() - Delete vdev and remove from adapter - * @adapter: hdd adapter - * - * This API deletes vdev object and release its reference from hdd adapter - * - * Return: 0 for success, negative error code for failure - */ -int hdd_objmgr_release_and_destroy_vdev(struct hdd_adapter *adapter); - /** * hdd_objmgr_get_vdev() - Get reference of vdev from adapter * @adapter: hdd adapter diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index bea0c77eefd5..67bfa9d16a43 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -239,13 +239,12 @@ enum eWniMsgTypes { WNI_SME_REGISTER_BCN_REPORT_SEND_CB = SIR_SME_MSG_TYPES_BEGIN + 154, eWNI_SME_ANTENNA_ISOLATION_RSP = SIR_SME_MSG_TYPES_BEGIN + 155, eWNI_SME_MON_DEINIT_SESSION = SIR_SME_MSG_TYPES_BEGIN + 156, - eWNI_SME_VDEV_DELETE_REQ = SIR_SME_MSG_TYPES_BEGIN + 157, - eWNI_SME_VDEV_DELETE_RSP = SIR_SME_MSG_TYPES_BEGIN + 158, - eWNI_SME_ROAM_INIT_PARAM = SIR_SME_MSG_TYPES_BEGIN + 159, - eWNI_SME_ROAM_SEND_PER_REQ = SIR_SME_MSG_TYPES_BEGIN + 160, + eWNI_SME_VDEV_DELETE_RSP = SIR_SME_MSG_TYPES_BEGIN + 157, + eWNI_SME_ROAM_INIT_PARAM = SIR_SME_MSG_TYPES_BEGIN + 158, + eWNI_SME_ROAM_SEND_PER_REQ = SIR_SME_MSG_TYPES_BEGIN + 159, eWNI_SME_GET_ROAM_SCAN_CH_LIST_EVENT = - SIR_SME_MSG_TYPES_BEGIN + 161, - eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 162 + SIR_SME_MSG_TYPES_BEGIN + 160, + eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 161 }; typedef struct sAniCfgTxRateCtrs { diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index ba57f775045f..663b69820cb1 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1577,20 +1577,6 @@ static void lim_process_sme_obss_scan_ind(struct mac_context *mac_ctx, return; } -static void -lim_process_vdev_delete(struct mac_context *mac_ctx, - struct del_vdev_params *vdev_param) -{ - tp_wma_handle wma_handle; - - wma_handle = cds_get_context(QDF_MODULE_ID_WMA); - if (!wma_handle) { - WMA_LOGE("%s: WMA context is invalid", __func__); - return; - } - wma_vdev_detach(wma_handle, vdev_param); -} - /** * lim_process_messages() - Process messages from upper layers. * @@ -2118,11 +2104,6 @@ static void lim_process_messages(struct mac_context *mac_ctx, qdf_mem_free((void *)msg->bodyptr); msg->bodyptr = NULL; break; - case eWNI_SME_VDEV_DELETE_REQ: - lim_process_vdev_delete(mac_ctx, msg->bodyptr); - /* Do not free msg->bodyptr, same memory used to send resp */ - msg->bodyptr = NULL; - break; default: qdf_mem_free((void *)msg->bodyptr); msg->bodyptr = NULL; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index feb392fe5465..8eef63ff5f26 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -37,6 +37,7 @@ #include "wma_tgt_cfg.h" #include "wma_fips_public_structs.h" #include "wma_sar_public_structs.h" +#include "wma_if.h" #include "wlan_mlme_public_struct.h" #include "sme_rrm_internal.h" #include "sir_types.h" @@ -369,7 +370,6 @@ sme_nss_chains_update(mac_handle_t mac_handle, * by below modules: * 1) WLAN_OBJMGR_ID * 2) WLAN_LEGACY_SME_ID - * 3) WLAN_LEGACY_WMA_ID * * Return: Newly created Vdev object or NULL incase in any error */ @@ -377,6 +377,21 @@ struct wlan_objmgr_vdev *sme_vdev_create(mac_handle_t mac_handle, struct wlan_vdev_create_params *vdev_params); +/** + * sme_vdev_post_vdev_create_setup() - setup the lower layers for the new vdev + * @mac_handle: The handle returned by mac_open + * @vdev: Object manger vdev + * + * This api will setup the csr/mlme/wma layer for the newly created vdev. + * + * If the post vdev setup is successfull, we will have following vdev refs + * 1) WLAN_OBJMGR_ID for self peer + * 2) WLAN_LEGACY_WMA_ID for vdev + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_vdev_post_vdev_create_setup(mac_handle_t mac_handle, + struct wlan_objmgr_vdev *vdev); /** * sme_vdev_delete() - Delete vdev for given id * @mac_handle: The handle returned by mac_open. @@ -4141,4 +4156,25 @@ static inline void sme_reset_oem_data_event_handler_cb(mac_handle_t mac_handle) QDF_STATUS sme_get_prev_connected_bss_ies(mac_handle_t mac_handle, uint8_t vdev_id, uint8_t **ies, uint32_t *ie_len); +/* + * sme_vdev_self_peer_delete_resp() - Response for self peer delete + * @del_vdev_params: parameters for which vdev self peer has been deleted + * + * This function is called by the lower level function as a response to + * vdev self peer delete request. + * + * Return: QDF_STATUS. + */ +QDF_STATUS sme_vdev_self_peer_delete_resp(struct del_vdev_params *param); + +/** + * sme_vdev_del_resp() - Vdev delete response function + * @vdev_id: vdevid which has been deleted + * + * This function is called by the lower level function as a response to + * vdev delete request + * + * Return: None + */ +void sme_vdev_del_resp(uint8_t vdev_id); #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h index 767c4745e9df..9ad44fb06603 100644 --- a/core/sme/inc/sme_inside.h +++ b/core/sme/inc/sme_inside.h @@ -152,9 +152,6 @@ QDF_STATUS csr_is_valid_channel(struct mac_context *mac, uint32_t freq); QDF_STATUS sme_acquire_global_lock(struct sme_context *sme); QDF_STATUS sme_release_global_lock(struct sme_context *sme); -QDF_STATUS -csr_process_vdev_del_rsp(struct mac_context *mac, uint8_t *pmsg); - /** * csr_flush_cfg_bg_scan_roam_channel_list() - Flush the channel list * @channel_info: Channel list to be flushed diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 0ad09f7613b7..efaccb165a0b 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -2148,12 +2148,10 @@ QDF_STATUS sme_process_msg(struct mac_context *mac, struct scheduler_msg *pMsg) } break; case eWNI_SME_VDEV_DELETE_RSP: - if (pMsg->bodyptr) { - status = csr_process_vdev_del_rsp(mac, pMsg->bodyptr); - qdf_mem_free(pMsg->bodyptr); - } else { + if (pMsg->bodyptr) + sme_vdev_self_peer_delete_resp(pMsg->bodyptr); + else sme_err("Empty message for: %d", pMsg->type); - } break; case eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE: if (pMsg->bodyptr) { @@ -4508,14 +4506,55 @@ release_ref: return status; } -struct wlan_objmgr_vdev *sme_vdev_create(mac_handle_t mac_handle, - struct wlan_vdev_create_params *vdev_params) +QDF_STATUS sme_vdev_post_vdev_create_setup(mac_handle_t mac_handle, + struct wlan_objmgr_vdev *vdev) { + struct vdev_mlme_obj *vdev_mlme; QDF_STATUS status = QDF_STATUS_E_INVAL; struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle); uint8_t vdev_id; + + vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); + if (!vdev_mlme) { + sme_err("Failed to get vdev mlme obj!"); + QDF_BUG(0); + return status; + } + + vdev_id = wlan_vdev_get_id(vdev); + status = wma_post_vdev_create_setup(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + sme_err("Failed to setup wma for vdev: %d", vdev_id); + return status; + } + + status = csr_setup_vdev_session(vdev_mlme); + if (QDF_IS_STATUS_ERROR(status)) { + sme_err("Failed to setup CSR layer for vdev: %d", vdev_id); + goto cleanup_wma; + } + + status = mlme_vdev_self_peer_create(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + sme_err("Failed to create vdev selfpeer for vdev:%d", vdev_id); + goto csr_cleanup_vdev_session; + } + + return status; + +csr_cleanup_vdev_session: + csr_cleanup_vdev_session(mac_ctx, vdev_id); +cleanup_wma: + wma_cleanup_vdev(vdev); + return status; +} + +struct wlan_objmgr_vdev +*sme_vdev_create(mac_handle_t mac_handle, + struct wlan_vdev_create_params *vdev_params) +{ + struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle); struct wlan_objmgr_vdev *vdev; - struct vdev_mlme_obj *vdev_mlme; sme_debug("addr:%pM opmode:%d", vdev_params->macaddr, vdev_params->opmode); @@ -4532,45 +4571,47 @@ struct wlan_objmgr_vdev *sme_vdev_create(mac_handle_t mac_handle, return NULL; } - vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); - if (!vdev_mlme) { - sme_err("Failed to get vdev mlme obj!"); - QDF_BUG(0); - goto vdev_obj_del; - } - - vdev_id = wlan_vdev_get_id(vdev); - status = wma_post_vdev_create_setup(vdev); - if (QDF_IS_STATUS_ERROR(status)) { - sme_err("Failed to setup wma for vdev: %d", vdev_id); - goto vdev_obj_del; - } - - status = csr_setup_vdev_session(vdev_mlme); - if (QDF_IS_STATUS_ERROR(status)) { - sme_err("Failed to setup CSR layer for vdev: %d", vdev_id); - goto cleanup_wma; - } - - status = mlme_vdev_self_peer_create(vdev); - if (QDF_IS_STATUS_ERROR(status)) { - sme_err("Failed to create vdev selfpeer for vdev:%d", vdev_id); - goto csr_cleanup_vdev_session; - } MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_OPEN_SESSION, - vdev_id, 0)); + wlan_vdev_get_id(vdev), 0)); return vdev; +} + +void sme_vdev_del_resp(uint8_t vdev_id) +{ + mac_handle_t mac_handle; + struct mac_context *mac; + + mac_handle = cds_get_context(QDF_MODULE_ID_SME); + if (!mac_handle) { + QDF_ASSERT(0); + return; + } + + mac = MAC_CONTEXT(mac_handle); + csr_cleanup_vdev_session(mac, vdev_id); + + if (mac->session_close_cb) + mac->session_close_cb(vdev_id); +} + +QDF_STATUS sme_vdev_self_peer_delete_resp(struct del_vdev_params *del_vdev_req) +{ + struct wlan_objmgr_vdev *vdev; + QDF_STATUS status; + + vdev = del_vdev_req->vdev; + if (!vdev) { + qdf_mem_free(del_vdev_req); + return QDF_STATUS_E_INVAL; + } -csr_cleanup_vdev_session: - csr_cleanup_vdev_session(mac_ctx, vdev_id); -cleanup_wma: - wma_cleanup_vdev(vdev); -vdev_obj_del: - wlan_objmgr_vdev_obj_delete(vdev); wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); - return NULL; + + status = del_vdev_req->status; + qdf_mem_free(del_vdev_req); + return status; } QDF_STATUS sme_vdev_delete(mac_handle_t mac_handle, @@ -4579,17 +4620,61 @@ QDF_STATUS sme_vdev_delete(mac_handle_t mac_handle, QDF_STATUS status; struct mac_context *mac = MAC_CONTEXT(mac_handle); uint8_t vdev_id = wlan_vdev_get_id(vdev); + struct scheduler_msg self_peer_delete_msg = {0}; + struct del_vdev_params *del_self_peer; MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_CLOSE_SESSION, vdev_id, 0)); + status = sme_acquire_global_lock(&mac->sme); if (QDF_IS_STATUS_SUCCESS(status)) { - status = csr_roam_vdev_delete(mac, vdev_id, false); + status = csr_prepare_vdev_delete(mac, vdev_id, false); sme_release_global_lock(&mac->sme); } - /* Release the reference acquired during vdev create */ - wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); + /* + * While this vdev delete is invoked we will still have following + * references held: + * WLAN_LEGACY_WMA_ID -- 1 + * WLAN_LEGACY_SME_ID -- 1 + * WLAN_OBJMGR_ID -- 2 + * Following message will release the self and delete the self peer + * and release the wma references so the objmgr and wma_legacy will be + * released because of this. + * + * In the message callback the legacy_sme reference will be released + * resulting in the last reference of vdev object and sending the + * vdev_delete to firmware. + */ + status = wlan_objmgr_vdev_obj_delete(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + sme_nofl_err("Failed to mark vdev as logical delete %d", + status); + return status; + } + + del_self_peer = qdf_mem_malloc(sizeof(*del_self_peer)); + if (!del_self_peer) + return QDF_STATUS_E_NOMEM; + + del_self_peer->vdev = vdev; + del_self_peer->vdev_id = wlan_vdev_get_id(vdev); + qdf_mem_copy(del_self_peer->self_mac_addr, + wlan_vdev_mlme_get_macaddr(vdev), sizeof(tSirMacAddr)); + + self_peer_delete_msg.bodyptr = del_self_peer; + self_peer_delete_msg.callback = mlme_vdev_self_peer_delete; + status = scheduler_post_message(QDF_MODULE_ID_SME, + QDF_MODULE_ID_MLME, + QDF_MODULE_ID_TARGET_IF, + &self_peer_delete_msg); + + if (QDF_IS_STATUS_ERROR(status)) { + sme_err("Failed to post vdev selfpeer for vdev:%d", vdev_id); + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); + qdf_mem_free(del_self_peer); + } + return status; } diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 6d32923f851b..aed94ceaabff 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -1665,7 +1665,7 @@ QDF_STATUS csr_stop(struct mac_context *mac) */ csr_purge_pdev_all_ser_cmd_list(mac); for (sessionId = 0; sessionId < WLAN_MAX_VDEVS; sessionId++) - csr_roam_vdev_delete(mac, sessionId, true); + csr_prepare_vdev_delete(mac, sessionId, true); for (sessionId = 0; sessionId < WLAN_MAX_VDEVS; sessionId++) csr_neighbor_roam_close(mac, sessionId); @@ -1822,7 +1822,7 @@ static QDF_STATUS csr_roam_close(struct mac_context *mac) */ csr_purge_pdev_all_ser_cmd_list(mac); for (sessionId = 0; sessionId < WLAN_MAX_VDEVS; sessionId++) - csr_roam_vdev_delete(mac, sessionId, true); + csr_prepare_vdev_delete(mac, sessionId, true); qdf_mc_timer_stop(&mac->roam.hTimerWaitForKey); qdf_mc_timer_destroy(&mac->roam.hTimerWaitForKey); @@ -17070,84 +17070,6 @@ QDF_STATUS csr_setup_vdev_session(struct vdev_mlme_obj *vdev_mlme) return status; } -QDF_STATUS csr_process_vdev_del_rsp(struct mac_context *mac_ctx, - uint8_t *pmsg) -{ - QDF_STATUS status = QDF_STATUS_E_FAILURE; - struct del_vdev_params *rsp; - uint8_t vdev_id; - - if (!pmsg) { - sme_err("msg ptr is NULL"); - return status; - } - - rsp = (struct del_vdev_params *)pmsg; - vdev_id = rsp->vdev_id; - sme_debug("vdev delete rsp status = %d", rsp->status); - - /* - * This session is done. This will also flush all the pending command - * for this vdev, as vdev is deleted and no command should be sent - * for this vdev. Active cmnd is e_sme_command_del_vdev and will - * be removed anyway next. - */ - csr_cleanup_vdev_session(mac_ctx, vdev_id); - - if (rsp->sme_callback) { - status = sme_release_global_lock(&mac_ctx->sme); - if (!QDF_IS_STATUS_SUCCESS(status)) - sme_debug("Failed to Release Lock"); - else { - rsp->sme_callback(rsp->vdev_id); - status = sme_acquire_global_lock(&mac_ctx->sme); - if (!QDF_IS_STATUS_SUCCESS(status)) - return status; - } - } - - return QDF_STATUS_SUCCESS; -} - -static QDF_STATUS -csr_issue_vdev_del_req(struct mac_context *mac_ctx, uint8_t vdev_id, - tSirMacAddr session_mac_addr, - csr_session_close_cb callback, - void *context) -{ - QDF_STATUS status = QDF_STATUS_SUCCESS; - struct del_vdev_params *del_vdev_req; - struct scheduler_msg msg = {0}; - - del_vdev_req = qdf_mem_malloc(sizeof(struct del_vdev_params)); - if (!del_vdev_req) - return QDF_STATUS_E_NOMEM; - - qdf_mem_copy(del_vdev_req->self_mac_addr, - session_mac_addr, sizeof(tSirMacAddr)); - - del_vdev_req->vdev_id = vdev_id; - del_vdev_req->sme_callback = callback; - del_vdev_req->sme_ctx = context; - msg.type = eWNI_SME_VDEV_DELETE_REQ; - msg.reserved = 0; - msg.bodyptr = del_vdev_req; - msg.bodyval = 0; - - sme_debug("sending eWNI_SME_VDEV_DELETE_REQ"); - status = scheduler_post_message( - QDF_MODULE_ID_SME, - QDF_MODULE_ID_PE, - QDF_MODULE_ID_PE, &msg); - if (status != QDF_STATUS_SUCCESS) { - sme_err("wma_post_ctrl_msg failed"); - qdf_mem_free(del_vdev_req); - return QDF_STATUS_E_FAILURE; - } - return QDF_STATUS_SUCCESS; - return status; -} - void csr_cleanup_vdev_session(struct mac_context *mac, uint8_t vdev_id) { if (CSR_IS_SESSION_VALID(mac, vdev_id)) { @@ -17168,13 +17090,12 @@ void csr_cleanup_vdev_session(struct mac_context *mac, uint8_t vdev_id) &pSession->prev_assoc_ap_info); qdf_mc_timer_destroy(&pSession->hTimerRoaming); qdf_mc_timer_destroy(&pSession->roaming_offload_timer); - csr_purge_vdev_pending_ser_cmd_list(mac, vdev_id); csr_init_session(mac, vdev_id); } } -QDF_STATUS csr_roam_vdev_delete(struct mac_context *mac_ctx, - uint8_t vdev_id, bool cleanup) +QDF_STATUS csr_prepare_vdev_delete(struct mac_context *mac_ctx, + uint8_t vdev_id, bool cleanup) { QDF_STATUS status = QDF_STATUS_SUCCESS; struct csr_roam_session *session; @@ -17202,13 +17123,13 @@ QDF_STATUS csr_roam_vdev_delete(struct mac_context *mac_ctx, * as expected by firmware and should not be flushed. */ csr_purge_vdev_all_scan_ser_cmd_list(mac_ctx, vdev_id); + /* Flush all the pending commands */ + csr_purge_vdev_pending_ser_cmd_list(mac_ctx, vdev_id); if (!mac_ctx->session_close_cb) { sme_err("no close session callback registered"); return QDF_STATUS_E_FAILURE; } - status = csr_issue_vdev_del_req(mac_ctx, vdev_id, - session->self_mac_addr.bytes, - mac_ctx->session_close_cb, NULL); + return status; } diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index e98ff3cf4607..35947fb39c60 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -359,15 +359,15 @@ QDF_STATUS csr_save_to_channel_power2_g_5_g(struct mac_context *mac, *channelTable); /* - * csr_roam_vdev_delete() - CSR api to delete vdev + * csr_prepare_vdev_delete() - CSR api to delete vdev * @mac_ctx: pointer to mac context * @vdev_id: vdev id to be deleted. * @cleanup: clean up vdev session on true * * Return QDF_STATUS */ -QDF_STATUS csr_roam_vdev_delete(struct mac_context *mac_ctx, - uint8_t vdev_id, bool cleanup); +QDF_STATUS csr_prepare_vdev_delete(struct mac_context *mac_ctx, + uint8_t vdev_id, bool cleanup); /* * csr_cleanup_vdev_session() - CSR api to cleanup vdev diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 199c94a1e607..bec4a6e139c4 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1843,6 +1843,7 @@ QDF_STATUS wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t buf, uint32_t desc_id, void *mgmt_tx_params); +#ifndef CONFIG_HL_SUPPORT /** * wma_mgmt_nbuf_unmap_cb() - dma unmap for pending mgmt pkts * @pdev: objmgr pdev @@ -1852,13 +1853,29 @@ QDF_STATUS wma_mgmt_unified_cmd_send(struct wlan_objmgr_vdev *vdev, * * Return: None */ -#ifndef CONFIG_HL_SUPPORT void wma_mgmt_nbuf_unmap_cb(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t buf); +/** + * wma_mgmt_nbuf_unmap_cb() - dma unmap for pending mgmt pkts + * @pdev: objmgr pdev + * @buf: buffer + * + * This is a cb function drains all mgmt packets of a vdev. + * This is called in event of target going down without sending completions. + * + * Return: QDF_STATUS + */ +QDF_STATUS wma_mgmt_frame_fill_peer_cb(struct wlan_objmgr_peer *peer, + qdf_nbuf_t buf); #else static inline void wma_mgmt_nbuf_unmap_cb(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t buf) {} +static inline QDF_STATUS wma_mgmt_frame_fill_peer_cb(struct wlan_objmgr_peer *peer, + qdf_nbuf_t buf) +{ + return QDF_STATUS_SUCCESS; +} #endif /** @@ -2615,5 +2632,14 @@ QDF_STATUS wma_pre_vdev_start_setup(uint8_t vdev_id, QDF_STATUS wma_send_ani_level_request(tp_wma_handle wma_handle, uint32_t *freqs, uint8_t num_freqs); #endif /* FEATURE_ANI_LEVEL_REQUEST */ + +/** + * wma_vdev_detach() - send vdev delete command to fw + * @wma_handle: wma handle + * @pdel_vdev_req_param: del vdev params + * + * Return: QDF status + */ +QDF_STATUS wma_vdev_detach(struct del_vdev_params *pdel_vdev_req_param); #endif diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 14520ce4b668..293debaf4b4e 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -713,14 +713,14 @@ struct set_dtim_params { * struct del_vdev_params - Del Sta Self params * @session_id: SME Session ID * @status: response status code - * @sme_callback: callback to be called from WMA to SME + * @vdev: Object to vdev * @sme_ctx: pointer to context provided by SME */ struct del_vdev_params { tSirMacAddr self_mac_addr; uint8_t vdev_id; uint32_t status; - csr_session_close_cb sme_callback; + struct wlan_objmgr_vdev *vdev; void *sme_ctx; }; diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index be5b3ffe85ba..90fa4e789f66 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -794,16 +794,6 @@ static inline uint8_t *wma_find_bssid_by_vdev_id(tp_wma_handle wma, QDF_STATUS wma_find_vdev_id_by_bssid(tp_wma_handle wma, uint8_t *bssid, uint8_t *vdev_id); -/** - * wma_vdev_detach() - send vdev delete command to fw - * @wma_handle: wma handle - * @pdel_vdev_req_param: del vdev params - * - * Return: QDF status - */ -QDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, - struct del_vdev_params *pdel_vdev_req_param); - QDF_STATUS wma_vdev_set_param(wmi_unified_t wmi_handle, uint32_t if_id, uint32_t param_id, uint32_t param_value); diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index b5efee29c27c..ea99ea008279 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -424,32 +424,10 @@ static struct wma_target_req *wma_find_remove_req_msgtype(tp_wma_handle wma, return req_msg; } -/** - * wma_send_vdev_del_resp() - send vdev del resp to Upper layer - * @param: params of del vdev response - * - * Return: none - */ -static inline void wma_send_vdev_del_resp(struct del_vdev_params *param) -{ - struct scheduler_msg sme_msg = {0}; - QDF_STATUS status; - - sme_msg.type = eWNI_SME_VDEV_DELETE_RSP; - sme_msg.bodyptr = param; - - status = scheduler_post_message(QDF_MODULE_ID_WMA, - QDF_MODULE_ID_SME, - QDF_MODULE_ID_SME, &sme_msg); - if (!QDF_IS_STATUS_SUCCESS(status)) - qdf_mem_free(param); -} - QDF_STATUS wma_vdev_detach_callback(struct vdev_delete_response *rsp) { tp_wma_handle wma; struct wma_txrx_node *iface = NULL; - struct del_vdev_params *param; wma = cds_get_context(QDF_MODULE_ID_WMA); @@ -468,13 +446,7 @@ QDF_STATUS wma_vdev_detach_callback(struct vdev_delete_response *rsp) iface = &wma->interfaces[rsp->vdev_id]; - if (!iface->del_staself_req) { - wma_err(" iface handle is NULL for VDEV_%d", rsp->vdev_id); - return QDF_STATUS_E_FAILURE; - } - wma_debug("vdev del response received for VDEV_%d", rsp->vdev_id); - param = (struct del_vdev_params *)iface->del_staself_req; iface->del_staself_req = NULL; if (iface->roam_scan_stats_req) { @@ -489,10 +461,9 @@ QDF_STATUS wma_vdev_detach_callback(struct vdev_delete_response *rsp) qdf_mem_zero(iface, sizeof(*iface)); wma_vdev_init(iface); - param->status = QDF_STATUS_SUCCESS; - wma_send_vdev_del_resp(param); + mlme_vdev_del_resp(rsp->vdev_id); - return param->status; + return QDF_STATUS_SUCCESS; } static void @@ -564,46 +535,27 @@ static void wma_handle_monitor_mode_vdev_detach(tp_wma_handle wma, static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle, struct del_vdev_params *del_vdev_req_param) { - QDF_STATUS status = QDF_STATUS_E_FAILURE; + QDF_STATUS status = QDF_STATUS_SUCCESS; uint8_t vdev_id = del_vdev_req_param->vdev_id; struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; void *soc = cds_get_context(QDF_MODULE_ID_SOC); - struct vdev_mlme_obj *vdev_mlme; + int i; if (!soc) { WMA_LOGE("%s:SOC context is NULL", __func__); - goto rel_ref; - } - - vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(iface->vdev); - if (!vdev_mlme) { - wma_err("Failed to get vdev mlme obj for vdev id %d", - del_vdev_req_param->vdev_id); + status = QDF_STATUS_E_FAILURE; goto rel_ref; } if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) wma_handle_monitor_mode_vdev_detach(wma_handle, vdev_id); - iface->del_staself_req = del_vdev_req_param; - wma_cdp_vdev_detach(soc, wma_handle, vdev_id); - wma_release_vdev_ref(iface); - - status = vdev_mgr_delete_send(vdev_mlme); - if (QDF_IS_STATUS_ERROR(status)) { - WMA_LOGE("Unable to remove an interface"); - goto out; - } - - return status; - rel_ref: wma_cdp_vdev_detach(soc, wma_handle, vdev_id); + wlan_mgmt_txrx_vdev_drain(iface->vdev, + wma_mgmt_frame_fill_peer_cb, &i); + wma_debug("Releasing wma reference for vdev:%d", vdev_id); wma_release_vdev_ref(iface); -out: - wma_vdev_deinit(iface); - qdf_mem_zero(iface, sizeof(*iface)); - wma_vdev_init(iface); return status; } @@ -662,21 +614,6 @@ error: return qdf_status; } -static bool wma_vdev_uses_self_peer(uint32_t vdev_type, uint32_t vdev_subtype) -{ - switch (vdev_type) { - case WMI_VDEV_TYPE_AP: - return vdev_subtype == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE; - - case WMI_VDEV_TYPE_MONITOR: - case WMI_VDEV_TYPE_OCB: - return true; - - default: - return false; - } -} - /** * wma_remove_objmgr_peer() - remove objmgr peer information from host driver * @wma: wma handle @@ -685,12 +622,12 @@ static bool wma_vdev_uses_self_peer(uint32_t vdev_type, uint32_t vdev_subtype) * * Return: none */ -static void wma_remove_objmgr_peer(tp_wma_handle wma, uint8_t vdev_id, +static void wma_remove_objmgr_peer(tp_wma_handle wma, + struct wlan_objmgr_vdev *obj_vdev, uint8_t *peer_addr) { struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_peer *obj_peer; - struct wlan_objmgr_vdev *obj_vdev; struct wlan_objmgr_pdev *obj_pdev; uint8_t pdev_id = 0; @@ -700,12 +637,6 @@ static void wma_remove_objmgr_peer(tp_wma_handle wma, uint8_t vdev_id, return; } - obj_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, - WLAN_LEGACY_WMA_ID); - if (!obj_vdev) { - WMA_LOGE("Obj vdev not found. Unable to remove peer"); - return; - } obj_pdev = wlan_vdev_get_pdev(obj_vdev); pdev_id = wlan_objmgr_pdev_get_pdev_id(obj_pdev); obj_peer = wlan_objmgr_get_peer(psoc, pdev_id, peer_addr, @@ -715,10 +646,9 @@ static void wma_remove_objmgr_peer(tp_wma_handle wma, uint8_t vdev_id, /* Unref to decrement ref happened in find_peer */ wlan_objmgr_peer_release_ref(obj_peer, WLAN_LEGACY_WMA_ID); } else { - WMA_LOGE("Peer %pM not found", peer_addr); + wma_nofl_err("Peer %pM not found", peer_addr); } - wlan_objmgr_vdev_release_ref(obj_vdev, WLAN_LEGACY_WMA_ID); } static QDF_STATUS wma_check_for_deffered_peer_delete(tp_wma_handle wma_handle, @@ -761,38 +691,40 @@ static QDF_STATUS wma_vdev_self_peer_delete(tp_wma_handle wma_handle, uint8_t vdev_id = pdel_vdev_req_param->vdev_id; struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; - if (wma_vdev_uses_self_peer(iface->type, iface->sub_type)) { + if (mlme_vdev_uses_self_peer(iface->type, iface->sub_type)) { status = wma_self_peer_remove(wma_handle, pdel_vdev_req_param); if (QDF_IS_STATUS_ERROR(status)) { wma_err("can't remove selfpeer, send rsp session: %d", vdev_id); - status = wma_handle_vdev_detach(wma_handle, - pdel_vdev_req_param); - if (QDF_IS_STATUS_ERROR(status)) { - wma_err("Trigger recovery for vdev %d", - vdev_id); - cds_trigger_recovery(QDF_REASON_UNSPECIFIED); - } + wma_handle_vdev_detach(wma_handle, pdel_vdev_req_param); + mlme_vdev_self_peer_delete_resp(pdel_vdev_req_param); + cds_trigger_recovery(QDF_REASON_UNSPECIFIED); return status; } } else if (iface->type == WMI_VDEV_TYPE_STA) { - wma_remove_objmgr_peer(wma_handle, vdev_id, + wma_remove_objmgr_peer(wma_handle, iface->vdev, pdel_vdev_req_param->self_mac_addr); } return status; } -QDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, - struct del_vdev_params *pdel_vdev_req_param) +QDF_STATUS wma_vdev_detach(struct del_vdev_params *pdel_vdev_req_param) { QDF_STATUS status = QDF_STATUS_SUCCESS; - uint8_t vdev_id = pdel_vdev_req_param->vdev_id; - struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id]; + uint8_t vdev_id; + struct wma_txrx_node *iface = NULL; + tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); + if (!wma_handle) + return QDF_STATUS_E_INVAL; + + vdev_id = wlan_vdev_get_id(pdel_vdev_req_param->vdev); + iface = &wma_handle->interfaces[vdev_id]; if (!iface->vdev) { WMA_LOGE("vdev %d is NULL", vdev_id); - goto send_rsp; + mlme_vdev_self_peer_delete_resp(pdel_vdev_req_param); + return status; } status = wma_check_for_deffered_peer_delete(wma_handle, @@ -804,38 +736,33 @@ QDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle, return status; iface->is_del_sta_defered = false; + iface->del_staself_req = NULL; status = wma_vdev_self_peer_delete(wma_handle, pdel_vdev_req_param); - if (QDF_IS_STATUS_ERROR(status)) { wma_err("Failed to send self peer delete:%d", status); - goto send_rsp; + status = QDF_STATUS_E_INVAL; + return status; } if (iface->type != WMI_VDEV_TYPE_MONITOR) iface->vdev_active = false; - if (!wma_vdev_uses_self_peer(iface->type, iface->sub_type) || + if (!mlme_vdev_uses_self_peer(iface->type, iface->sub_type) || !wmi_service_enabled(wma_handle->wmi_handle, wmi_service_sync_delete_cmds)) { status = wma_handle_vdev_detach(wma_handle, pdel_vdev_req_param); + pdel_vdev_req_param->status = status; + mlme_vdev_self_peer_delete_resp(pdel_vdev_req_param); } - if (QDF_IS_STATUS_ERROR(status)) - goto send_rsp; - return status; send_fail_rsp: WMA_LOGE("rcvd del_self_sta without del_bss; vdev_id:%d", vdev_id); cds_trigger_recovery(QDF_REASON_UNSPECIFIED); status = QDF_STATUS_E_FAILURE; - -send_rsp: - pdel_vdev_req_param->status = status; - wma_send_vdev_del_resp(pdel_vdev_req_param); - return status; } @@ -1710,7 +1637,7 @@ peer_detach: cdp_peer_delete(soc, vdev_id, peer_addr, bitmap); } - wma_remove_objmgr_peer(wma, vdev_id, peer_mac); + wma_remove_objmgr_peer(wma, wma->interfaces[vdev_id].vdev, peer_mac); wma->interfaces[vdev_id].peer_count--; #undef PEER_ALL_TID_BITMASK @@ -2029,6 +1956,9 @@ static int wma_remove_bss_peer(tp_wma_handle wma, uint32_t vdev_id, return -EINVAL; } + if (cds_is_driver_recovering()) + return -EINVAL; + if (wmi_service_enabled(wma->wmi_handle, wmi_service_sync_delete_cmds)) { WMA_LOGD(FL("Wait for the peer delete. vdev_id %d"), @@ -2192,7 +2122,7 @@ void wma_send_del_bss_response(tp_wma_handle wma, struct del_bss_resp *resp) iface->is_del_sta_defered = false; WMA_LOGA("scheduling defered deletion (vdev id %x)", vdev_id); - wma_vdev_detach(wma, iface->del_staself_req); + wma_vdev_detach(iface->del_staself_req); } } @@ -2344,7 +2274,7 @@ __wma_handle_vdev_stop_rsp(struct vdev_stop_response *resp_event) cdp_peer_delete(soc, resp_event->vdev_id, bssid.bytes, 1 << CDP_PEER_DELETE_NO_SPECIAL); - wma_remove_objmgr_peer(wma, resp_event->vdev_id, + wma_remove_objmgr_peer(wma, iface->vdev, bssid.bytes); iface->peer_count--; @@ -2484,8 +2414,8 @@ QDF_STATUS wma_vdev_self_peer_create(struct vdev_mlme_obj *vdev_mlme) return QDF_STATUS_E_FAILURE; } - if (wma_vdev_uses_self_peer(vdev_mlme->mgmt.generic.type, - vdev_mlme->mgmt.generic.subtype)) { + if (mlme_vdev_uses_self_peer(vdev_mlme->mgmt.generic.type, + vdev_mlme->mgmt.generic.subtype)) { status = wma_create_peer(wma_handle, vdev->vdev_mlme.macaddr, WMI_PEER_TYPE_DEFAULT, @@ -3057,6 +2987,7 @@ int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info, data = (struct del_sta_self_rsp_params *)req_msg->user_data; WMA_LOGD(FL("Calling vdev detach handler")); wma_handle_vdev_detach(wma, data->self_sta_param); + mlme_vdev_self_peer_delete_resp(data->self_sta_param); qdf_mem_free(data); } else if (req_msg->type == WMA_SET_LINK_PEER_RSP || req_msg->type == WMA_DELETE_PEER_RSP) { @@ -3173,6 +3104,7 @@ void wma_hold_req_timer(void *data) wma_trigger_recovery_assert_on_fw_timeout( WMA_DELETE_STA_REQ); wma_handle_vdev_detach(wma, del_sta->self_sta_param); + mlme_vdev_self_peer_delete_resp(del_sta->self_sta_param); qdf_mem_free(tgt_req->user_data); } else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) && (tgt_req->type == WMA_SET_LINK_PEER_RSP || diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 386b79a6338a..9dda4fd38318 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -4010,4 +4010,29 @@ void wma_mgmt_nbuf_unmap_cb(struct wlan_objmgr_pdev *pdev, if (wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_WMI_MGMT_REF)) qdf_nbuf_unmap_single(dev, buf, QDF_DMA_TO_DEVICE); } + +QDF_STATUS wma_mgmt_frame_fill_peer_cb(struct wlan_objmgr_peer *peer, + qdf_nbuf_t buf) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + + psoc = wlan_peer_get_psoc(peer); + if (!psoc) { + WMA_LOGE("%s: Psoc handle NULL", __func__); + return QDF_STATUS_E_INVAL; + } + + pdev = wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, + wlan_peer_get_pdev_id(peer), + WLAN_LEGACY_WMA_ID); + if (!pdev) { + WMA_LOGE("%s: Pdev handle NULL", __func__); + return QDF_STATUS_E_INVAL; + } + wma_mgmt_nbuf_unmap_cb(pdev, buf); + wlan_objmgr_pdev_release_ref(pdev, WLAN_LEGACY_WMA_ID); + + return QDF_STATUS_SUCCESS; +} #endif