Parcourir la source

qcacld-3.0: Send vdev delete to firmware on notification

Presently vdev delete is sent to firmware 1st and the object manager
vdev delete is deleted after all the references are released.
With this change the vdev delete is sent to firmware when all the
references are released and the vdev delete is sent to firmware via
the object manager vdev delete notification.

Change-Id: I67bea0d2b2a0d2d9eb4602e5d0b8bbdcafdd4d26
CRs-Fixed: 2618278
Arun Kumar Khandavalli il y a 5 ans
Parent
commit
68c99e72e7

+ 36 - 1
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 <wlan_objmgr_vdev_obj.h>
 #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

+ 83 - 3
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/wlan_mlme_cmn.h>
 #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

+ 24 - 17
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);
 	}
 

+ 0 - 22
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)
 {

+ 1 - 11
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

+ 5 - 6
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 {

+ 0 - 19
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;

+ 37 - 1
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 ) */

+ 0 - 3
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

+ 121 - 36
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,42 +4506,26 @@ 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;
-	struct wlan_objmgr_vdev *vdev;
-	struct vdev_mlme_obj *vdev_mlme;
-
-	sme_debug("addr:%pM opmode:%d", vdev_params->macaddr,
-		  vdev_params->opmode);
-
-	vdev = wlan_objmgr_vdev_obj_create(mac_ctx->pdev, vdev_params);
-	if (!vdev) {
-		sme_err("Failed to create vdev object");
-		return NULL;
-	}
-
-	if (wlan_objmgr_vdev_try_get_ref(vdev, WLAN_LEGACY_SME_ID) !=
-	    QDF_STATUS_SUCCESS) {
-		wlan_objmgr_vdev_obj_delete(vdev);
-		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;
+		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);
-		goto vdev_obj_del;
+		return status;
 	}
 
 	status = csr_setup_vdev_session(vdev_mlme);
@@ -4557,20 +4539,79 @@ struct wlan_objmgr_vdev *sme_vdev_create(mac_handle_t mac_handle,
 		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));
 
-	return vdev;
+	return status;
 
 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);
+	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;
+
+	sme_debug("addr:%pM opmode:%d", vdev_params->macaddr,
+		  vdev_params->opmode);
+
+	vdev = wlan_objmgr_vdev_obj_create(mac_ctx->pdev, vdev_params);
+	if (!vdev) {
+		sme_err("Failed to create vdev object");
+		return NULL;
+	}
+
+	if (wlan_objmgr_vdev_try_get_ref(vdev, WLAN_LEGACY_SME_ID) !=
+	    QDF_STATUS_SUCCESS) {
+		wlan_objmgr_vdev_obj_delete(vdev);
+		return NULL;
+	}
+
+	MTRACE(qdf_trace(QDF_MODULE_ID_SME,
+			 TRACE_CODE_SME_RX_HDD_OPEN_SESSION,
+			 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;
+	}
+
 	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;
 }
 

+ 7 - 86
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;
 }
 

+ 3 - 3
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

+ 27 - 1
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
 

+ 2 - 2
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;
 };
 

+ 0 - 10
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);
 

+ 43 - 111
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 ||

+ 25 - 0
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