Browse Source

qcacld-3.0: Refine PASN peer delete all & pasn auth status path

Refine PASN peer delete all path, to post message to
scheduler thread to process the peer delete all
message for PASN peers. Handle response timeout in WMA.
Resume vdev deletion after removing pasn peers

Add vendor command support to parse below vendor commands:
QCA_NL80211_VENDOR_SUBCMD_PASN
QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT

Send install key command to firmware to install the
PTK upon receiving
QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT
vendor command. If LTF keyseed is also received,
send the LTF keyseed to firmware.

Sent PASN auth status to firmware upon receiving
QCA_NL80211_VENDOR_SUBCMD_PASN command.

Change-Id: Idc9c69f7288b0774cc6d9bdcfed13ba3684bbc72
CRs-Fixed: 3231205
Pragaspathi Thilagaraj 2 years ago
parent
commit
832fee1036

+ 6 - 0
Kbuild

@@ -535,6 +535,12 @@ ifeq ($(CONFIG_WLAN_FEATURE_PEER_TXQ_FLUSH_CONF), y)
 HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_peer_txq_flush.o
 endif
 
+ifeq ($(CONFIG_WIFI_POS_CONVERGED), y)
+ifeq ($(CONFIG_WIFI_POS_PASN), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_wifi_pos_pasn.o
+endif
+endif
+
 $(call add-wlan-objs,hdd,$(HDD_OBJS))
 
 ###### OSIF_SYNC ########

+ 5 - 1
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c

@@ -1696,7 +1696,7 @@ vdevmgr_vdev_peer_delete_all_rsp_handle(struct vdev_mlme_obj *vdev_mlme,
 	if (!psoc)
 		return -QDF_STATUS_E_INVAL;
 
-	if (rsp->peer_type_bitmap == BIT(WLAN_PEER_RTT_PASN)) {
+	if (QDF_HAS_PARAM(rsp->peer_type_bitmap, WLAN_PEER_RTT_PASN)) {
 		rx_ops = wifi_pos_get_rx_ops(psoc);
 		if (!rx_ops ||
 		    !rx_ops->wifi_pos_vdev_delete_all_ranging_peers_rsp_cb) {
@@ -1871,6 +1871,8 @@ static QDF_STATUS ap_mlme_vdev_csa_complete(struct vdev_mlme_obj *vdev_mlme)
  *                                      to INIT state
  * @mlme_vdev_sta_disconn_start         callback to trigger vdev stop to
  *                                      firmware when resaaoc failure
+ * @mlme_vdev_ext_peer_delete_all_rsp:  Callback to trigger Delete all
+ *                                      peers for the given vdev
  */
 static struct vdev_mlme_ops sta_mlme_ops = {
 	.mlme_vdev_start_send = sta_mlme_vdev_start_send,
@@ -1889,6 +1891,8 @@ static struct vdev_mlme_ops sta_mlme_ops = {
 	.mlme_vdev_ext_stop_rsp = vdevmgr_vdev_stop_rsp_handle,
 	.mlme_vdev_ext_start_rsp = vdevmgr_vdev_start_rsp_handle,
 	.mlme_vdev_sta_disconn_start = sta_mlme_vdev_sta_disconnect_start,
+	.mlme_vdev_ext_peer_delete_all_rsp =
+			vdevmgr_vdev_peer_delete_all_rsp_handle,
 };
 
 /**

+ 18 - 1
components/wifi_pos/core/inc/wlan_wifi_pos_interface.h

@@ -21,9 +21,19 @@
 #define _WLAN_WIFI_POS_IFACE_API_H_
 
 #include <wlan_objmgr_vdev_obj.h>
-#include "wma_if.h"
+#include "lim_types.h"
+#include "wifi_pos_pasn_api.h"
 
 #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+/**
+ * wlan_wifi_pos_pasn_peer_delete_all  - Delete all pasn peer callback
+ * @self_peer_del_msg: Scheduler message
+ *
+ * Return: True if PASN peer delete all is required
+ */
+bool wlan_wifi_pos_pasn_peer_delete_all(struct wlan_objmgr_psoc *psoc,
+					uint8_t vdev_id);
+
 /**
  * wifi_pos_register_legacy_ops() - Register wifi pos legacy callbacks
  * @psoc: Psoc pointer
@@ -53,5 +63,12 @@ wifi_pos_deregister_legacy_ops(struct wlan_objmgr_psoc *psoc)
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline bool
+wlan_wifi_pos_pasn_peer_delete_all(struct wlan_objmgr_psoc *psoc,
+				   uint8_t vdev_id)
+{
+	return false;
+}
 #endif
 #endif /* _WLAN_WIFI_POS_IFACE_API_H_ */

+ 53 - 2
components/wifi_pos/core/src/wlan_wifi_pos_interface.c

@@ -17,9 +17,9 @@
  * DOC: define internal APIs related to the mlme component, legacy APIs are
  *	called for the time being, but will be cleaned up after convergence
  */
-#include "wma_pasn_peer_api.h"
 #include "wifi_pos_api.h"
 #include "wlan_wifi_pos_interface.h"
+#include "wma_pasn_peer_api.h"
 
 #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
 /**
@@ -64,7 +64,58 @@ static QDF_STATUS wlan_wifi_pos_pasn_peer_delete(struct wlan_objmgr_psoc *psoc,
 static QDF_STATUS
 wlan_wifi_pos_vdev_delete_resume(struct wlan_objmgr_vdev *vdev)
 {
-	return QDF_STATUS_SUCCESS;
+	return wma_pasn_peer_delete_all_complete(vdev);
+}
+
+bool
+wlan_wifi_pos_pasn_peer_delete_all(struct wlan_objmgr_psoc *psoc,
+				   uint8_t vdev_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	QDF_STATUS status;
+	struct scheduler_msg msg = {0};
+	struct pasn_peer_delete_msg *req;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_WIFI_POS_TGT_IF_ID);
+	if (!vdev) {
+		mlme_err("Vdev is not found for id:%d", vdev_id);
+		return false;
+	}
+
+	if (!(vdev->vdev_mlme.vdev_opmode == QDF_STA_MODE ||
+	      vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE)) {
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_TGT_IF_ID);
+		return false;
+	}
+
+	if (!wifi_pos_get_pasn_peer_count(vdev) ||
+	    wifi_pos_is_delete_all_peer_in_progress(vdev)) {
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_TGT_IF_ID);
+		return false;
+	}
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_TGT_IF_ID);
+
+	req = qdf_mem_malloc(sizeof(*req));
+	if (!req)
+		return false;
+
+	req->vdev_id = vdev_id;
+
+	msg.type = WIFI_POS_PASN_PEER_DELETE_ALL;
+	msg.bodyptr = req;
+
+	status = scheduler_post_message(QDF_MODULE_ID_WIFIPOS,
+					QDF_MODULE_ID_PE,
+					QDF_MODULE_ID_PE, &msg);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		qdf_mem_free(req);
+		mlme_err("Delete all pasn peers failed");
+		return false;
+	}
+
+	return true;
 }
 
 static struct wifi_pos_legacy_ops wifi_pos_ops = {

+ 1 - 0
configs/default_defconfig

@@ -127,6 +127,7 @@ ifeq (y,$(findstring y,$(CONFIG_CNSS_KIWI) $(CONFIG_CNSS_KIWI_V2)))
 	CONFIG_WLAN_TSF_UPLINK_DELAY := y
 	CONFIG_WLAN_SYNC_TSF_PLUS := y
 	CONFIG_WLAN_SYNC_TSF_TIMER := y
+	CONFIG_WIFI_POS_PASN := y
 	CONFIG_WLAN_DP_SRNG_USAGE_WM_TRACKING := y
 	CONFIG_WLAN_FEATURE_PEER_TXQ_FLUSH_CONF := y
 endif

+ 76 - 0
core/hdd/inc/wlan_hdd_wifi_pos_pasn.h

@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_hdd_wifi_pos_pasn.h
+ *
+ * WLAN Host Device Driver WIFI POSITION module PASN authentication
+ * feature interface definitions
+ *
+ */
+#ifndef __WLAN_HDD_WIFI_POS_PASN_H__
+#define __WLAN_HDD_WIFI_POS_PASN_H__
+#include "qdf_types.h"
+#include "qdf_status.h"
+#include "qca_vendor.h"
+#include <net/cfg80211.h>
+#include "wlan_hdd_object_manager.h"
+
+#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+
+extern const struct nla_policy
+wifi_pos_pasn_auth_status_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+
+extern const struct nla_policy
+wifi_pos_pasn_auth_policy[QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAX + 1];
+
+extern const struct nla_policy
+wifi_pos_pasn_set_ranging_ctx_policy[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_MAX + 1];
+
+int wlan_hdd_wifi_pos_send_pasn_auth_status(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data,
+					    int data_len);
+
+#define FEATURE_WIFI_POS_11AZ_AUTH_COMMANDS                                  \
+{                                                                            \
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,                             \
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PASN,                       \
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,  \
+	.doit = wlan_hdd_wifi_pos_send_pasn_auth_status,                     \
+	vendor_command_policy(wifi_pos_pasn_auth_status_policy,              \
+			      QCA_WLAN_VENDOR_ATTR_MAX)                      \
+},
+
+int
+wlan_hdd_cfg80211_set_secure_ranging_context(struct wiphy *wiphy,
+					     struct wireless_dev *wdev,
+					     const void *data, int data_len);
+
+#define FEATURE_WIFI_POS_SET_SECURE_RANGING_CONTEXT_COMMANDS                 \
+{                                                                            \
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,                             \
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT,     \
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,  \
+	.doit = wlan_hdd_cfg80211_set_secure_ranging_context,                \
+	vendor_command_policy(wifi_pos_pasn_set_ranging_ctx_policy,          \
+			      QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_MAX)   \
+},
+#else
+#define FEATURE_WIFI_POS_11AZ_AUTH_COMMANDS
+#define FEATURE_WIFI_POS_SET_SECURE_RANGING_CONTEXT_COMMANDS
+#endif /* WIFI_POS_CONVERGED && WLAN_FEATURE_RTT_11AZ_SUPPORT */
+#endif /* __WLAN_HDD_WIFI_POS_PASN_H__ */

+ 6 - 336
core/hdd/src/wlan_hdd_cfg80211.c

@@ -132,7 +132,6 @@
 #include "cfg_ucfg_api.h"
 
 #include "wlan_crypto_def_i.h"
-#include "wifi_pos_ucfg_i.h"
 #include "wlan_crypto_global_api.h"
 #include "wlan_nl_to_crypto_params.h"
 #include "wlan_crypto_global_def.h"
@@ -168,6 +167,7 @@
 #include "wlan_if_mgr_ucfg_api.h"
 #include "wlan_if_mgr_public_struct.h"
 #include "wlan_wfa_ucfg_api.h"
+#include "wifi_pos_ucfg_i.h"
 #include <osif_cm_util.h>
 #include <osif_cm_req.h>
 #include "wlan_hdd_bootup_marker.h"
@@ -185,6 +185,7 @@
 #include "wlan_hdd_peer_txq_flush.h"
 #include "wlan_cfg80211_wifi_pos.h"
 #include "wlan_osif_features.h"
+#include "wlan_hdd_wifi_pos_pasn.h"
 
 #define g_mode_rates_size (12)
 #define a_mode_rates_size (8)
@@ -1792,6 +1793,7 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
 		.vendor_id = QCA_NL80211_VENDOR_ID,
 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY,
 	},
+	FEATURE_WIFI_POS_11AZ_AUTH_EVENTS
 };
 
 /**
@@ -18387,6 +18389,8 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
 			      QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX)
 	},
 #endif
+	FEATURE_WIFI_POS_11AZ_AUTH_COMMANDS
+	FEATURE_WIFI_POS_SET_SECURE_RANGING_CONTEXT_COMMANDS
 	FEATURE_MCC_QUOTA_VENDOR_COMMANDS
 	FEATURE_PEER_FLUSH_VENDOR_COMMANDS
 	{
@@ -20390,129 +20394,6 @@ static int wlan_hdd_add_key_sta(struct wlan_objmgr_pdev *pdev,
 	return errno;
 }
 
-#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
-static int wlan_cfg80211_set_pasn_key(struct wlan_objmgr_psoc *psoc,
-				      struct wlan_objmgr_vdev *vdev,
-				      struct key_params *params,
-				      const u8 *mac_addr,
-				      const u8 *src_addr,
-				      enum wlan_crypto_key_type key_type,
-				      int key_index)
-{
-	struct wlan_crypto_key *crypto_key;
-	struct wlan_objmgr_peer *peer;
-	struct wlan_pasn_auth_status *pasn_status;
-	enum wlan_crypto_cipher_type cipher;
-	int cipher_len, ret = 0;
-	bool is_ltf_keyseed_required;
-	QDF_STATUS status;
-
-	if (!params) {
-		osif_err("Key params is NULL");
-		return -EINVAL;
-	}
-
-	crypto_key = qdf_mem_malloc(sizeof(*crypto_key));
-	if (!crypto_key)
-		return -ENOMEM;
-
-	cipher_len = osif_nl_to_crypto_cipher_len(params->cipher);
-	if (cipher_len < 0 || params->key_len < cipher_len) {
-		osif_err("cipher length %d less than reqd len %d",
-			 params->key_len, cipher_len);
-		qdf_mem_free(crypto_key);
-		return -EINVAL;
-	}
-
-	cipher = osif_nl_to_crypto_cipher_type(params->cipher);
-	if (!IS_WEP_CIPHER(cipher) &&
-	    key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST && !mac_addr) {
-		osif_err("mac_addr is NULL for pairwise Key");
-		qdf_mem_free(crypto_key);
-		return -EINVAL;
-	}
-
-	status = wlan_crypto_validate_key_params(cipher, key_index,
-						 params->key_len,
-						 params->seq_len);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		osif_err("Invalid key params");
-		qdf_mem_free(crypto_key);
-		return -EINVAL;
-	}
-
-	wlan_cfg80211_translate_key(vdev, key_index, key_type, mac_addr,
-				    params, crypto_key);
-
-	hdd_debug("Set PASN unicast key");
-	status = ucfg_crypto_set_key_req(vdev, crypto_key, key_type);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		osif_err("PASN set_key failed");
-		qdf_mem_free(crypto_key);
-		return -EFAULT;
-	}
-
-	qdf_mem_free(crypto_key);
-
-	peer = wlan_objmgr_get_peer_by_mac(psoc, (uint8_t *)mac_addr,
-					   WLAN_WIFI_POS_CORE_ID);
-	if (!peer) {
-		osif_err("PASN peer is not found");
-		return -EFAULT;
-	}
-
-	/*
-	 * If LTF key seed is not required for the peer, then update
-	 * the source mac address for that peer by sending PASN auth
-	 * status command.
-	 * If LTF keyseed is required, then PASN Auth status command
-	 * will be sent after LTF keyseed command.
-	 */
-	is_ltf_keyseed_required =
-			ucfg_wifi_pos_is_ltf_keyseed_required_for_peer(peer);
-	wlan_objmgr_peer_release_ref(peer, WLAN_WIFI_POS_CORE_ID);
-	if (is_ltf_keyseed_required)
-		return 0;
-
-	pasn_status = qdf_mem_malloc(sizeof(*pasn_status));
-	if (!pasn_status)
-		return -ENOMEM;
-
-	pasn_status->vdev_id = vdev->vdev_objmgr.vdev_id;
-	pasn_status->num_peers = 1;
-
-	if (mac_addr)
-		qdf_mem_copy(pasn_status->auth_status[0].peer_mac.bytes,
-			     mac_addr, QDF_MAC_ADDR_SIZE);
-
-	if (src_addr)
-		qdf_mem_copy(pasn_status->auth_status[0].self_mac.bytes,
-			     src_addr, QDF_MAC_ADDR_SIZE);
-
-	status = wifi_pos_send_pasn_auth_status(psoc, pasn_status);
-	if (QDF_IS_STATUS_ERROR(status))
-		osif_err("Send PASN auth status failed");
-
-	ret = qdf_status_to_os_return(status);
-
-	qdf_mem_free(pasn_status);
-
-	return ret;
-}
-#else
-static inline
-int wlan_cfg80211_set_pasn_key(struct wlan_objmgr_psoc *psoc,
-			       struct wlan_objmgr_vdev *vdev,
-			       struct key_params *params,
-			       const u8 *mac_addr,
-			       const u8 *src_addr,
-			       enum wlan_crypto_key_type key_type,
-			       int key_index)
-{
-	return 0;
-}
-#endif
-
 static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
 				       struct net_device *ndev,
 				       u8 key_index, bool pairwise,
@@ -20523,8 +20404,7 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
 	mac_handle_t mac_handle;
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
 	struct wlan_objmgr_vdev *vdev;
-	struct wlan_objmgr_peer *peer;
-	bool ft_mode = false, is_peer_type_pasn;
+	bool ft_mode = false;
 	enum wlan_crypto_cipher_type cipher;
 	int errno;
 	int32_t cipher_cap, ucast_cipher = 0;
@@ -20576,24 +20456,6 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
 				     QDF_MAC_ADDR_SIZE);
 	}
 
-	peer = wlan_objmgr_get_peer_by_mac(hdd_ctx->psoc, mac_address.bytes,
-					   WLAN_OSIF_ID);
-	is_peer_type_pasn = peer &&
-			    (wlan_peer_get_peer_type(peer) ==
-			     WLAN_PEER_RTT_PASN);
-	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
-
-	if (is_peer_type_pasn) {
-		errno = wlan_cfg80211_set_pasn_key(
-				hdd_ctx->psoc,
-				vdev, params, mac_addr, NULL,
-				(pairwise ?
-				 WLAN_CRYPTO_KEY_TYPE_UNICAST : WLAN_CRYPTO_KEY_TYPE_GROUP),
-				 key_index);
-
-		return errno;
-	}
-
 	errno = wlan_cfg80211_store_key(vdev, key_index,
 					(pairwise ?
 					WLAN_CRYPTO_KEY_TYPE_UNICAST :
@@ -24043,194 +23905,6 @@ wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
 }
 #endif
 
-#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
-static int
-__wlan_hdd_cfg80211_send_pasn_auth_status(struct wiphy *wiphy,
-					  struct net_device *dev,
-					  struct cfg80211_pasn_params *params)
-{
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	struct wlan_pasn_auth_status *data;
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	int ret, i;
-
-	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
-		hdd_err("Command not allowed in FTM mode");
-		return -EPERM;
-	}
-
-	if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
-		return -EINVAL;
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret)
-		return ret;
-
-	data = qdf_mem_malloc(sizeof(*data));
-	if (!data)
-		return -ENOMEM;
-
-	data->vdev_id = adapter->vdev_id;
-	data->num_peers = params->num_pasn_peers;
-	if (!data->num_peers) {
-		hdd_err("No peers");
-		qdf_mem_free(data);
-		return -EINVAL;
-	}
-
-	if (data->num_peers > WLAN_MAX_11AZ_PEERS)
-		data->num_peers = WLAN_MAX_11AZ_PEERS;
-
-	for (i = 0; i < data->num_peers; i++) {
-		data->auth_status[i].status = params->peer[i].status;
-		if (params->peer[i].peer_addr)
-			qdf_mem_copy(data->auth_status[i].peer_mac.bytes,
-				     params->peer[i].peer_addr,
-				     QDF_MAC_ADDR_SIZE);
-
-		if (params->peer[i].src_addr)
-			qdf_mem_copy(data->auth_status[i].self_mac.bytes,
-				     params->peer[i].src_addr,
-				     QDF_MAC_ADDR_SIZE);
-	}
-
-	status = wifi_pos_send_pasn_auth_status(hdd_ctx->psoc, data);
-	if (QDF_IS_STATUS_ERROR(status))
-		hdd_err("Send pasn auth status failed");
-
-	qdf_mem_free(data);
-	ret = qdf_status_to_os_return(status);
-
-	return ret;
-}
-
-static int
-__wlan_hdd_cfg80211_set_ltf_keyseed(struct wiphy *wiphy, struct net_device *dev,
-				    struct cfg80211_ltf_keyseed_conf *conf)
-{
-	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
-	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	struct wlan_crypto_ltf_keyseed_data *data;
-	struct wlan_pasn_auth_status *pasn_auth_status;
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	int ret;
-
-	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
-		hdd_err("Command not allowed in FTM mode");
-		return -EPERM;
-	}
-
-	if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
-		return -EINVAL;
-
-	ret = wlan_hdd_validate_context(hdd_ctx);
-	if (ret)
-		return ret;
-
-	if (!conf->bssid) {
-		hdd_err("Null BSSID");
-		return -EINVAL;
-	}
-
-	data = qdf_mem_malloc(sizeof(*data));
-	if (!data)
-		return -ENOMEM;
-
-	data->vdev_id = adapter->vdev_id;
-	qdf_mem_copy(data->peer_mac_addr.bytes, conf->bssid, QDF_MAC_ADDR_SIZE);
-
-	if (conf->src_addr)
-		qdf_mem_copy(data->src_mac_addr.bytes, conf->src_addr,
-			     QDF_MAC_ADDR_SIZE);
-
-	data->key_seed_len = conf->ltf_keyseed_len;
-	if (!data->key_seed_len ||
-	    data->key_seed_len < WLAN_MIN_SECURE_LTF_KEYSEED_LEN) {
-		hdd_err("Invalid key seed length:%d", conf->ltf_keyseed_len);
-		ret = -EINVAL;
-		goto err;
-	}
-
-	qdf_mem_copy(data->key_seed, conf->ltf_keyseed,
-		     data->key_seed_len);
-
-	status = wlan_crypto_set_ltf_keyseed(hdd_ctx->psoc, data);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_err("Set LTF Keyseed failed");
-		ret = qdf_status_to_os_return(status);
-		goto err;
-	}
-
-	/*
-	 * Send PASN Auth status followed by SET LTF keyseed command to
-	 * set the peer as authorized at firmware and firmware will start
-	 * ranging after this.
-	 */
-	pasn_auth_status = qdf_mem_malloc(sizeof(*pasn_auth_status));
-	if (!pasn_auth_status) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	pasn_auth_status->vdev_id = adapter->vdev_id;
-	pasn_auth_status->num_peers = 1;
-	qdf_mem_copy(pasn_auth_status->auth_status[0].peer_mac.bytes,
-		     conf->bssid, QDF_MAC_ADDR_SIZE);
-	qdf_mem_copy(pasn_auth_status->auth_status[0].self_mac.bytes,
-		     conf->src_addr, QDF_MAC_ADDR_SIZE);
-
-	status = wifi_pos_send_pasn_auth_status(hdd_ctx->psoc,
-						pasn_auth_status);
-	qdf_mem_free(pasn_auth_status);
-	if (QDF_IS_STATUS_ERROR(status))
-		hdd_err("Send PASN auth status failed");
-
-	ret = qdf_status_to_os_return(status);
-err:
-	qdf_mem_free(data);
-
-	return ret;
-}
-
-static int
-wlan_hdd_cfg80211_set_ltf_keyseed(struct wiphy *wiphy, struct net_device *dev,
-				  struct cfg80211_ltf_keyseed_conf *conf)
-{
-	int errno;
-	struct osif_vdev_sync *vdev_sync;
-
-	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
-	if (errno)
-		return errno;
-
-	errno = __wlan_hdd_cfg80211_set_ltf_keyseed(wiphy, dev, conf);
-
-	osif_vdev_sync_op_stop(vdev_sync);
-
-	return errno;
-}
-
-static int
-wlan_hdd_cfg80211_send_pasn_auth_status(struct wiphy *wiphy,
-					struct net_device *dev,
-					struct cfg80211_pasn_params *params)
-{
-	int errno;
-	struct osif_vdev_sync *vdev_sync;
-
-	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
-	if (errno)
-		return errno;
-
-	errno = __wlan_hdd_cfg80211_send_pasn_auth_status(wiphy, dev, params);
-
-	osif_vdev_sync_op_stop(vdev_sync);
-
-	return errno;
-}
-#endif
-
 #if defined(WLAN_FEATURE_NAN) && \
 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
 static int
@@ -25210,10 +24884,6 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
 	.external_auth = wlan_hdd_cfg80211_external_auth,
 #endif
-#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
-	.set_ltf_keyseed = wlan_hdd_cfg80211_set_ltf_keyseed,
-	.pasn_auth = wlan_hdd_cfg80211_send_pasn_auth_status,
-#endif
 #if defined(WLAN_FEATURE_NAN) && \
 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
 	.start_nan = wlan_hdd_cfg80211_start_nan,

+ 15 - 4
core/hdd/src/wlan_hdd_p2p.c

@@ -1052,8 +1052,10 @@ __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
 	uint8_t type = 0;
 	uint8_t sub_type = 0;
 	struct hdd_context *hdd_ctx;
-	uint8_t *dest_addr;
+	uint8_t *dest_addr = NULL;
+	uint16_t auth_algo;
 	enum nl80211_rxmgmt_flags nl80211_flag = 0;
+	bool is_pasn_auth_frame = false;
 
 	hdd_debug("Frame Type = %d Frame Length = %d freq = %d",
 		  frame_type, frm_len, rx_freq);
@@ -1076,10 +1078,19 @@ __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
 
 	type = WLAN_HDD_GET_TYPE_FRM_FC(pb_frames[0]);
 	sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(pb_frames[0]);
+	if (type == SIR_MAC_MGMT_FRAME &&
+	    sub_type == SIR_MAC_MGMT_AUTH &&
+	    frm_len > (sizeof(struct wlan_frame_hdr) +
+		       WLAN_AUTH_FRAME_MIN_LEN)) {
+		auth_algo = *(uint16_t *)(pb_frames +
+					  sizeof(struct wlan_frame_hdr));
+		if (auth_algo == eSIR_AUTH_TYPE_PASN)
+			is_pasn_auth_frame = true;
+	}
 
 	/* Get adapter from Destination mac address of the frame */
-	if ((type == SIR_MAC_MGMT_FRAME) &&
-	    (sub_type != SIR_MAC_MGMT_PROBE_REQ) &&
+	if (type == SIR_MAC_MGMT_FRAME &&
+	    sub_type != SIR_MAC_MGMT_PROBE_REQ && !is_pasn_auth_frame &&
 	    !qdf_is_macaddr_broadcast(
 	     (struct qdf_mac_addr *)&pb_frames[WLAN_HDD_80211_FRM_DA_OFFSET])) {
 		dest_addr = &pb_frames[WLAN_HDD_80211_FRM_DA_OFFSET];
@@ -1135,7 +1146,7 @@ __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
 
 	/* Indicate Frame Over Normal Interface */
 	hdd_debug("Indicate Frame over NL80211 sessionid : %d, idx :%d",
-		   adapter->vdev_id, adapter->dev->ifindex);
+		  adapter->vdev_id, adapter->dev->ifindex);
 
 	wlan_hdd_cfg80211_convert_rxmgmt_flags(rx_flags, &nl80211_flag);
 

+ 515 - 0
core/hdd/src/wlan_hdd_wifi_pos_pasn.c

@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/**
+ * DOC: wlan_hdd_wifi_pos_pasn.c
+ *
+ * WLAN Host Device Driver WIFI POSITION PASN authentication APIs implementation
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/wireless.h>
+#include "osif_sync.h"
+#include <wlan_hdd_includes.h>
+#include <net/cfg80211.h>
+#include "qdf_trace.h"
+#include "qdf_types.h"
+#include "wlan_hdd_wifi_pos_pasn.h"
+#include "wifi_pos_pasn_api.h"
+#include "wifi_pos_ucfg_i.h"
+#include "wlan_crypto_global_api.h"
+#include "wifi_pos_ucfg_i.h"
+#include "wlan_nl_to_crypto_params.h"
+
+const struct nla_policy
+wifi_pos_pasn_auth_status_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_PASN_ACTION] = {.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_PASN_PEERS] = {.type = NLA_NESTED},
+};
+
+const struct nla_policy
+wifi_pos_pasn_auth_policy[QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_PASN_PEER_SRC_ADDR] = VENDOR_NLA_POLICY_MAC_ADDR,
+	[QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAC_ADDR] = VENDOR_NLA_POLICY_MAC_ADDR,
+	[QCA_WLAN_VENDOR_ATTR_PASN_PEER_STATUS_SUCCESS] = {.type = NLA_FLAG},
+	[QCA_WLAN_VENDOR_ATTR_PASN_PEER_LTF_KEYSEED_REQUIRED] = {
+							.type = NLA_FLAG},
+};
+
+const struct nla_policy
+wifi_pos_pasn_set_ranging_ctx_policy[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_ACTION] = {
+					.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SRC_ADDR] =
+					VENDOR_NLA_POLICY_MAC_ADDR,
+	[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_PEER_MAC_ADDR] =
+					VENDOR_NLA_POLICY_MAC_ADDR,
+	[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SHA_TYPE] = {
+					.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_TK] = {
+					.type = NLA_BINARY, .len = MAX_PMK_LEN},
+	[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_CIPHER] = {
+					.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_LTF_KEYSEED] = {
+					.type = NLA_BINARY, .len = MAX_PMK_LEN},
+};
+
+static int
+wlan_hdd_cfg80211_send_pasn_auth_status(struct wiphy *wiphy,
+					struct net_device *dev,
+					const void *data, int data_len)
+{
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct wlan_pasn_auth_status *pasn_data;
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAX + 1];
+	struct nlattr *curr_attr;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	bool is_pasn_success = false;
+	int ret, i = 0, rem;
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
+		return -EINVAL;
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
+				    data, data_len,
+				    wifi_pos_pasn_auth_status_policy)) {
+		hdd_err_rl("Invalid PASN auth status attributes");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_PASN_PEERS]) {
+		hdd_err_rl("No PASN peer");
+		return -EINVAL;
+	}
+
+	pasn_data = qdf_mem_malloc(sizeof(*pasn_data));
+	if (!pasn_data)
+		return -ENOMEM;
+
+	pasn_data->vdev_id = adapter->vdev_id;
+	nla_for_each_nested(curr_attr, tb[QCA_WLAN_VENDOR_ATTR_PASN_PEERS],
+			    rem) {
+		if (wlan_cfg80211_nla_parse_nested(
+			tb2, QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAX, curr_attr,
+			wifi_pos_pasn_auth_policy)) {
+			hdd_err_rl("nla_parse failed");
+			qdf_mem_free(pasn_data);
+			return -EINVAL;
+		}
+
+		is_pasn_success = nla_get_flag(
+			tb2[QCA_WLAN_VENDOR_ATTR_PASN_PEER_STATUS_SUCCESS]);
+		if (!is_pasn_success)
+			pasn_data->auth_status[i].status =
+					WLAN_PASN_AUTH_STATUS_PASN_FAILED;
+
+		hdd_debug("PASN auth status:%d",
+			  pasn_data->auth_status[i].status);
+
+		if (tb2[QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAC_ADDR]) {
+			nla_memcpy(pasn_data->auth_status[i].peer_mac.bytes,
+				   tb2[QCA_WLAN_VENDOR_ATTR_PASN_PEER_MAC_ADDR],
+				   QDF_MAC_ADDR_SIZE);
+			hdd_debug("Peer mac[%d]: " QDF_MAC_ADDR_FMT, i,
+				  QDF_MAC_ADDR_REF(
+				  pasn_data->auth_status[i].peer_mac.bytes));
+		}
+
+		if (tb2[QCA_WLAN_VENDOR_ATTR_PASN_PEER_SRC_ADDR]) {
+			nla_memcpy(pasn_data->auth_status[i].self_mac.bytes,
+				   tb2[QCA_WLAN_VENDOR_ATTR_PASN_PEER_SRC_ADDR],
+				   QDF_MAC_ADDR_SIZE);
+			hdd_debug("Src addr[%d]: " QDF_MAC_ADDR_FMT, i,
+				  QDF_MAC_ADDR_REF(
+				  pasn_data->auth_status[i].self_mac.bytes));
+		}
+
+		i++;
+		pasn_data->num_peers++;
+		if (pasn_data->num_peers >= WLAN_MAX_11AZ_PEERS) {
+			hdd_err_rl("Invalid num_peers:%d",
+				   pasn_data->num_peers);
+			qdf_mem_free(pasn_data);
+			return -EINVAL;
+		}
+	}
+
+	status = wifi_pos_send_pasn_auth_status(hdd_ctx->psoc, pasn_data);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Send pasn auth status failed");
+
+	qdf_mem_free(pasn_data);
+	ret = qdf_status_to_os_return(status);
+
+	return ret;
+}
+
+int wlan_hdd_wifi_pos_send_pasn_auth_status(struct wiphy *wiphy,
+					    struct wireless_dev *wdev,
+					    const void *data, int data_len)
+{
+	struct osif_vdev_sync *vdev_sync;
+	int errno;
+
+	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
+	if (errno)
+		return errno;
+
+	errno = wlan_hdd_cfg80211_send_pasn_auth_status(wiphy, wdev->netdev,
+							data, data_len);
+
+	osif_vdev_sync_op_stop(vdev_sync);
+
+	return errno;
+}
+
+#define WLAN_PASN_AUTH_KEY_INDEX 0
+
+static int wlan_cfg80211_set_pasn_key(struct hdd_adapter *adapter,
+				      struct nlattr **tb)
+{
+	struct wlan_crypto_key *crypto_key;
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_peer *peer;
+	struct wlan_objmgr_psoc *psoc =
+			adapter->hdd_ctx->psoc;
+	struct qdf_mac_addr peer_mac = {0};
+	struct wlan_pasn_auth_status *pasn_status;
+	bool is_ltf_keyseed_required;
+	QDF_STATUS status;
+	int ret = 0;
+	int cipher_len;
+	uint32_t cipher;
+
+	vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_WIFI_POS_CORE_ID);
+	if (!vdev) {
+		hdd_err("Key params is NULL");
+		return -EINVAL;
+	}
+
+	crypto_key = qdf_mem_malloc(sizeof(*crypto_key));
+	if (!crypto_key) {
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_WIFI_POS_CORE_ID);
+		return -ENOMEM;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_CIPHER]) {
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_WIFI_POS_CORE_ID);
+		qdf_mem_free(crypto_key);
+		return -EINVAL;
+	}
+
+	cipher = nla_get_u32(
+		tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_CIPHER]);
+	crypto_key->cipher_type = osif_nl_to_crypto_cipher_type(cipher);
+
+	cipher_len = osif_nl_to_crypto_cipher_len(cipher);
+	crypto_key->keylen =
+		nla_len(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_TK]);
+	if (cipher_len < 0 || crypto_key->keylen < cipher_len ||
+	    (crypto_key->keylen >
+	     (WLAN_CRYPTO_KEYBUF_SIZE + WLAN_CRYPTO_MICBUF_SIZE))) {
+		hdd_err_rl("Invalid key length %d", crypto_key->keylen);
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_WIFI_POS_CORE_ID);
+		qdf_mem_free(crypto_key);
+		return -EINVAL;
+	}
+
+	crypto_key->keyix = WLAN_PASN_AUTH_KEY_INDEX;
+	qdf_mem_copy(&crypto_key->keyval[0],
+		     nla_data(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_TK]),
+		     crypto_key->keylen);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_PEER_MAC_ADDR]) {
+		hdd_err_rl("BSSID is not present");
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_WIFI_POS_CORE_ID);
+		qdf_mem_free(crypto_key);
+		return -EINVAL;
+	}
+
+	qdf_mem_copy(crypto_key->macaddr,
+		     nla_data(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_PEER_MAC_ADDR]),
+		     QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(peer_mac.bytes,
+		     nla_data(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_PEER_MAC_ADDR]),
+		     QDF_MAC_ADDR_SIZE);
+
+	hdd_debug("PASN unicast key opmode %d, key_len %d",
+		  vdev->vdev_mlme.vdev_opmode,
+		  crypto_key->keylen);
+
+	status = ucfg_crypto_set_key_req(vdev, crypto_key,
+					 WLAN_CRYPTO_KEY_TYPE_UNICAST);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("PASN set_key failed");
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_WIFI_POS_CORE_ID);
+		qdf_mem_free(crypto_key);
+		return -EFAULT;
+	}
+	hdd_objmgr_put_vdev_by_user(vdev, WLAN_WIFI_POS_CORE_ID);
+	qdf_mem_free(crypto_key);
+
+	peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac.bytes,
+					   WLAN_WIFI_POS_CORE_ID);
+	if (!peer) {
+		hdd_err("PASN peer is not found");
+		return -EFAULT;
+	}
+
+	/*
+	 * If LTF key seed is not required for the peer, then update
+	 * the source mac address for that peer by sending PASN auth
+	 * status command.
+	 * If LTF keyseed is required, then PASN Auth status command
+	 * will be sent after LTF keyseed command.
+	 */
+	is_ltf_keyseed_required =
+			ucfg_wifi_pos_is_ltf_keyseed_required_for_peer(peer);
+	wlan_objmgr_peer_release_ref(peer, WLAN_WIFI_POS_CORE_ID);
+	if (is_ltf_keyseed_required)
+		return 0;
+
+	pasn_status = qdf_mem_malloc(sizeof(*pasn_status));
+	if (!pasn_status)
+		return -ENOMEM;
+
+	pasn_status->vdev_id = adapter->vdev_id;
+	pasn_status->num_peers = 1;
+
+	qdf_mem_copy(pasn_status->auth_status[0].peer_mac.bytes,
+		     peer_mac.bytes, QDF_MAC_ADDR_SIZE);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SRC_ADDR])
+		qdf_mem_copy(pasn_status->auth_status[0].self_mac.bytes,
+			     nla_data(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SRC_ADDR]),
+			     QDF_MAC_ADDR_SIZE);
+
+	status = wifi_pos_send_pasn_auth_status(psoc, pasn_status);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Send PASN auth status failed");
+
+	ret = qdf_status_to_os_return(status);
+
+	qdf_mem_free(pasn_status);
+
+	return ret;
+}
+
+static int
+wlan_hdd_cfg80211_send_set_ltf_keyseed(struct wiphy *wiphy,
+				       struct net_device *dev,
+				       struct nlattr **tb)
+{
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct wlan_pasn_auth_status *pasn_auth_status;
+	struct wlan_objmgr_peer *peer;
+	struct wlan_crypto_ltf_keyseed_data *data;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	bool is_ltf_keyseed_required;
+	int ret;
+
+	hdd_enter();
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
+		return -EINVAL;
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	data = qdf_mem_malloc(sizeof(*data));
+	if (!data)
+		return -ENOMEM;
+
+	data->vdev_id = adapter->vdev_id;
+	if (!tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_PEER_MAC_ADDR]) {
+		hdd_err_rl("BSSID is not present");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	qdf_mem_copy(data->peer_mac_addr.bytes,
+		     nla_data(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_PEER_MAC_ADDR]),
+		     QDF_MAC_ADDR_SIZE);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SRC_ADDR])
+		qdf_mem_copy(data->src_mac_addr.bytes,
+			     nla_data(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_SRC_ADDR]),
+			     QDF_MAC_ADDR_SIZE);
+
+	data->key_seed_len =
+		nla_len(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_LTF_KEYSEED]);
+	if (!data->key_seed_len ||
+	    data->key_seed_len < WLAN_MIN_SECURE_LTF_KEYSEED_LEN ||
+	    data->key_seed_len > WLAN_MAX_SECURE_LTF_KEYSEED_LEN) {
+		hdd_err_rl("Invalid key seed length:%d", data->key_seed_len);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	qdf_mem_copy(data->key_seed,
+		     nla_data(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_LTF_KEYSEED]),
+		     data->key_seed_len);
+
+	status = wlan_crypto_set_ltf_keyseed(hdd_ctx->psoc, data);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Set LTF Keyseed failed");
+		ret = qdf_status_to_os_return(status);
+		goto err;
+	}
+
+	peer = wlan_objmgr_get_peer_by_mac(hdd_ctx->psoc,
+					   data->peer_mac_addr.bytes,
+					   WLAN_WIFI_POS_CORE_ID);
+	if (!peer) {
+		hdd_err_rl("PASN peer is not found");
+		ret = -EFAULT;
+		goto err;
+	}
+
+	/*
+	 * If LTF key seed is not required for the peer, then update
+	 * the source mac address for that peer by sending PASN auth
+	 * status command.
+	 * If LTF keyseed is required, then PASN Auth status command
+	 * will be sent after LTF keyseed command.
+	 */
+	is_ltf_keyseed_required =
+			ucfg_wifi_pos_is_ltf_keyseed_required_for_peer(peer);
+	wlan_objmgr_peer_release_ref(peer, WLAN_WIFI_POS_CORE_ID);
+
+	if (!is_ltf_keyseed_required) {
+		ret = 0;
+		goto err;
+	}
+
+	/*
+	 * Send PASN Auth status followed by SET LTF keyseed command to
+	 * set the peer as authorized at firmware and firmware will start
+	 * ranging after this.
+	 */
+	pasn_auth_status = qdf_mem_malloc(sizeof(*pasn_auth_status));
+	if (!pasn_auth_status) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	pasn_auth_status->vdev_id = adapter->vdev_id;
+	pasn_auth_status->num_peers = 1;
+	qdf_mem_copy(pasn_auth_status->auth_status[0].peer_mac.bytes,
+		     data->peer_mac_addr.bytes, QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(pasn_auth_status->auth_status[0].self_mac.bytes,
+		     data->src_mac_addr.bytes, QDF_MAC_ADDR_SIZE);
+
+	status = wifi_pos_send_pasn_auth_status(hdd_ctx->psoc,
+						pasn_auth_status);
+	qdf_mem_free(pasn_auth_status);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Send PASN auth status failed");
+
+	ret = qdf_status_to_os_return(status);
+err:
+	qdf_mem_free(data);
+	hdd_exit();
+
+	return ret;
+}
+
+static int
+__wlan_hdd_cfg80211_set_secure_ranging_context(struct wiphy *wiphy,
+					       struct wireless_dev *wdev,
+					       const void *data, int data_len)
+{
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
+	int errno = 0;
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_MAX + 1];
+
+	hdd_enter();
+
+	if (wlan_cfg80211_nla_parse(tb,
+				    QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_MAX,
+				    data, data_len,
+				    wifi_pos_pasn_set_ranging_ctx_policy)) {
+		hdd_err_rl("Invalid PASN auth status attributes");
+		return -EINVAL;
+	}
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_ACTION]) {
+		hdd_err_rl("Action attribute is missing");
+		return -EINVAL;
+	}
+
+	if (nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_ACTION]) ==
+			QCA_WLAN_VENDOR_SECURE_RANGING_CTX_ACTION_ADD) {
+		if (tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_TK] &&
+		    nla_len(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_TK])) {
+			hdd_debug("Sec ranging CTX TK");
+			errno = wlan_cfg80211_set_pasn_key(adapter, tb);
+			if (errno)
+				return errno;
+		}
+
+		if (tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_LTF_KEYSEED] &&
+		    nla_len(tb[QCA_WLAN_VENDOR_ATTR_SECURE_RANGING_CTX_LTF_KEYSEED])) {
+			hdd_debug("Set LTF keyseed");
+			errno = wlan_hdd_cfg80211_send_set_ltf_keyseed(wiphy,
+								       wdev->netdev, tb);
+			if (errno)
+				return errno;
+		}
+	}
+	hdd_exit();
+
+	return errno;
+}
+
+int
+wlan_hdd_cfg80211_set_secure_ranging_context(struct wiphy *wiphy,
+					     struct wireless_dev *wdev,
+					     const void *data, int data_len)
+{
+	int errno;
+	struct osif_vdev_sync *vdev_sync;
+
+	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
+	if (errno)
+		return errno;
+
+	errno = __wlan_hdd_cfg80211_set_secure_ranging_context(wiphy,
+							       wdev,
+							       data, data_len);
+
+	osif_vdev_sync_op_stop(vdev_sync);
+
+	return errno;
+}

+ 3 - 1
core/mac/inc/wni_api.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. 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
@@ -234,7 +235,8 @@ enum eWniMsgTypes {
 	CM_PREAUTH_REQ = SIR_SME_MSG_TYPES_BEGIN + 175,
 	eWNI_SME_CSA_REQ = SIR_SME_MSG_TYPES_BEGIN + 176,
 	CM_ABORT_CONN_TIMER = SIR_SME_MSG_TYPES_BEGIN + 177,
-	eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 178
+	WIFI_POS_PASN_PEER_DELETE_ALL = SIR_SME_MSG_TYPES_BEGIN + 178,
+	eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 179
 };
 
 typedef struct sAniCfgTxRateCtrs {

+ 1 - 0
core/mac/src/include/sir_params.h

@@ -649,6 +649,7 @@ enum halmsgtype {
 	SIR_HAL_TWT_RESUME_DIALOG_REQUEST = (SIR_HAL_ITC_MSG_TYPES_BEGIN + 420),
 	SIR_HAL_PEER_CREATE_REQ           = (SIR_HAL_ITC_MSG_TYPES_BEGIN + 421),
 	SIR_HAL_TWT_NUDGE_DIALOG_REQUEST  = (SIR_HAL_ITC_MSG_TYPES_BEGIN + 422),
+	SIR_HAL_PASN_PEER_DELETE_REQUEST  = (SIR_HAL_ITC_MSG_TYPES_BEGIN + 423),
 
 
 	SIR_HAL_MSG_TYPES_END               = (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF),

+ 36 - 3
core/mac/src/pe/lim/lim_process_auth_frame.c

@@ -507,7 +507,27 @@ static inline void  lim_process_sae_auth_frame(struct mac_context *mac_ctx,
 {}
 #endif
 
-#ifdef WLAN_FEATURE_RTT_11AZ_SUPPORT
+#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+static uint8_t
+lim_get_pasn_peer_vdev_id(struct mac_context *mac, uint8_t *bssid)
+{
+	struct wlan_objmgr_peer *peer;
+	uint8_t vdev_id;
+
+	peer = wlan_objmgr_get_peer_by_mac(mac->psoc, bssid,
+					   WLAN_MGMT_RX_ID);
+	if (!peer) {
+		pe_err("PASN peer doesn't exist for bssid: " QDF_MAC_ADDR_FMT,
+		       QDF_MAC_ADDR_REF(bssid));
+		return WLAN_UMAC_VDEV_ID_MAX;
+	}
+
+	vdev_id = wlan_vdev_get_id(wlan_peer_get_vdev(peer));
+	wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_RX_ID);
+
+	return vdev_id;
+}
+
 /**
  * lim_process_pasn_auth_frame()- Process PASN authentication frame
  * @mac_ctx: MAC context
@@ -530,6 +550,7 @@ lim_process_pasn_auth_frame(struct mac_context *mac_ctx,
 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
 
+	pe_debug("vdev_id:%d", vdev_id);
 	lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType,
 				    (uint8_t *)mac_hdr,
 				    frame_len + sizeof(tSirMacMgmtHdr),
@@ -547,6 +568,12 @@ lim_process_pasn_auth_frame(struct mac_context *mac_ctx,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline uint8_t
+lim_get_pasn_peer_vdev_id(struct mac_context *mac, uint8_t *bssid)
+{
+	return WLAN_UMAC_VDEV_ID_MAX;
+}
 #endif
 
 static void lim_process_auth_frame_type1(struct mac_context *mac_ctx,
@@ -1831,6 +1858,7 @@ QDF_STATUS lim_process_auth_frame_no_session(struct mac_context *mac,
 	tpSirMacMgmtHdr mac_hdr;
 	struct pe_session *pe_session = NULL;
 	uint8_t *pBody;
+	uint8_t vdev_id;
 	uint16_t frameLen, curr_seq_num, auth_alg = 0;
 	tSirMacAuthFrameBody *rx_auth_frame;
 	QDF_STATUS ret_status = QDF_STATUS_E_FAILURE;
@@ -1860,8 +1888,13 @@ QDF_STATUS lim_process_auth_frame_no_session(struct mac_context *mac,
 	if (sae_auth_frame)
 		return QDF_STATUS_SUCCESS;
 
-	if (auth_alg == eSIR_AUTH_TYPE_PASN)
-		return lim_process_pasn_auth_frame(mac, 0, pBd);
+	if (auth_alg == eSIR_AUTH_TYPE_PASN) {
+		vdev_id = lim_get_pasn_peer_vdev_id(mac, mac_hdr->bssId);
+		if (vdev_id == WLAN_UMAC_VDEV_ID_MAX)
+			return QDF_STATUS_E_FAILURE;
+
+		return lim_process_pasn_auth_frame(mac, vdev_id, pBd);
+	}
 
 	/* Auth frame has come on a new BSS, however, we need to find the session
 	 * from where the auth-req was sent to the new AP

+ 5 - 0
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -2046,6 +2046,11 @@ static void lim_process_messages(struct mac_context *mac_ctx,
 	case CM_ABORT_CONN_TIMER:
 		lim_deactivate_timers_for_vdev(mac_ctx, msg->bodyval);
 		break;
+	case WIFI_POS_PASN_PEER_DELETE_ALL:
+		lim_process_pasn_delete_all_peers(mac_ctx, msg->bodyptr);
+		qdf_mem_free(msg->bodyptr);
+		msg->bodyptr = NULL;
+		break;
 	default:
 		qdf_mem_free((void *)msg->bodyptr);
 		msg->bodyptr = NULL;

+ 28 - 0
core/mac/src/pe/lim/lim_process_mlm_req_messages.c

@@ -48,6 +48,7 @@
 #include <lim_mlo.h>
 #include "wlan_mlo_mgr_peer.h"
 #include <son_api.h>
+#include "wifi_pos_pasn_api.h"
 
 static void lim_process_mlm_auth_req(struct mac_context *, uint32_t *);
 static void lim_process_mlm_assoc_req(struct mac_context *, uint32_t *);
@@ -403,6 +404,33 @@ lim_send_peer_create_resp_mlo(struct wlan_objmgr_vdev *vdev,
 }
 #endif /* WLAN_FEATURE_11BE_MLO */
 
+#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+void
+lim_pasn_peer_del_all_resp_vdev_delete_resume(struct mac_context *mac,
+					      struct wlan_objmgr_vdev *vdev)
+{
+	if (!mac) {
+		pe_err("Mac ctx is NULL");
+		return;
+	}
+
+	/*
+	 * If PASN peer delete all command to firmware timedout, then
+	 * the PASN peers will not be cleaned up. So cleanup the
+	 * objmgr peers from here and reset the peer delete all in
+	 * progress flag.
+	 */
+	if (wifi_pos_get_pasn_peer_count(vdev))
+		wifi_pos_cleanup_pasn_peers(mac->psoc, vdev);
+
+	wifi_pos_set_delete_all_peer_in_progress(vdev, false);
+
+	pe_debug("Resume vdev delete");
+	if (mac->sme.sme_vdev_del_cb)
+		mac->sme.sme_vdev_del_cb(MAC_HANDLE(mac), vdev);
+}
+#endif
+
 void lim_send_peer_create_resp(struct mac_context *mac, uint8_t vdev_id,
 			       QDF_STATUS qdf_status, uint8_t *peer_mac)
 {

+ 60 - 0
core/mac/src/pe/lim/lim_types.h

@@ -388,6 +388,39 @@ void lim_set_cfg_protection(struct mac_context *mac, struct pe_session *pesessio
 /* Function to Initialize MLM state machine on STA */
 QDF_STATUS lim_init_mlm(struct mac_context *);
 
+/**
+ * struct pasn_peer_delete_msg  - PASN peer delete request message
+ * @message_type: Message type
+ * @length: message length
+ * @vdev_id: Vdev id
+ */
+struct pasn_peer_delete_msg {
+	uint16_t message_type;
+	uint16_t length;
+	uint8_t vdev_id;
+};
+
+#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+/**
+ * lim_process_pasn_delete_all_peers() - Process delete all PASN peers
+ * request
+ * @mac: Pointer to mac address
+ * @msg: Peer delete message
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+lim_process_pasn_delete_all_peers(struct mac_context *mac,
+				  struct pasn_peer_delete_msg *msg);
+#else
+static inline QDF_STATUS
+lim_process_pasn_delete_all_peers(struct mac_context *mac,
+				  struct pasn_peer_delete_msg *msg)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 /* Function to cleanup MLM state machine */
 void lim_cleanup_mlm(struct mac_context *);
 
@@ -1425,8 +1458,35 @@ void lim_process_mlm_start_req(struct mac_context *mac_ctx,
 void lim_process_mlm_join_req(struct mac_context *mac_ctx,
 			      tLimMlmJoinReq *mlm_join_req);
 
+#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+/**
+ * lim_pasn_peer_del_all_resp_vdev_delete_resume() - Delete all PASN peers is
+ * complete resume vdev delete.
+ * @mac: Mac context pointer
+ * @vdev: Vdev object pointer
+ *
+ * Return: None
+ */
+void
+lim_pasn_peer_del_all_resp_vdev_delete_resume(struct mac_context *mac,
+					      struct wlan_objmgr_vdev *vdev);
+#else
+static inline void
+lim_pasn_peer_del_all_resp_vdev_delete_resume(struct mac_context *mac,
+					      struct wlan_objmgr_vdev *vdev)
+{}
+#endif
+
+/**
+ * lim_send_peer_create_resp() -  Send peer create response
+ * @mac:     Pointer to MAC context
+ * @vdev_id: vdev id
+ * @status:  Status of peer create
+ * @peer_mac: Peer mac address
+ */
 void lim_send_peer_create_resp(struct mac_context *mac, uint8_t vdev_id,
 			       QDF_STATUS status, uint8_t *peer_mac);
+
 /*
  * lim_process_mlm_deauth_req() - This function is called to process
  * MLM_DEAUTH_REQ message from SME

+ 22 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -53,6 +53,7 @@
 #include "wlan_policy_mgr_api.h"
 #include "wlan_mlme_public_struct.h"
 #include "wlan_mlme_ucfg_api.h"
+#include "wma_pasn_peer_api.h"
 #ifdef WLAN_FEATURE_11AX_BSS_COLOR
 #include "wma_he.h"
 #endif
@@ -570,6 +571,27 @@ void lim_deactivate_timers_for_vdev(struct mac_context *mac_ctx,
 	}
 }
 
+#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+QDF_STATUS
+lim_process_pasn_delete_all_peers(struct mac_context *mac,
+				  struct pasn_peer_delete_msg *msg)
+{
+	struct wlan_objmgr_vdev *vdev;
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+	QDF_STATUS status;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, msg->vdev_id,
+						    WLAN_WIFI_POS_CORE_ID);
+	status = wma_delete_all_pasn_peers(wma, vdev);
+	if (QDF_IS_STATUS_ERROR(status))
+		pe_err("Failed to delete all PASN peers");
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
+
+	return status;
+}
+#endif
+
 /**
  * lim_cleanup_mlm() - This function is called to cleanup
  * @mac_ctx: Pointer to Global MAC structure

+ 2 - 1
core/sme/inc/sme_api.h

@@ -129,7 +129,8 @@
 #define SME_CMD_POLICY_MGR_CMD_TIMEOUT (SIR_VDEV_PLCY_MGR_TIMEOUT + 1000)
 #define SME_POLICY_MGR_CMD_TIMEOUT (SME_CMD_POLICY_MGR_CMD_TIMEOUT + 1000)
 
-#define SME_VDEV_DELETE_CMD_TIMEOUT (DELETE_RESPONSE_TIMER + 2000)
+#define SME_VDEV_DELETE_CMD_TIMEOUT (DELETE_RESPONSE_TIMER + \
+				     PEER_DELETE_ALL_RESPONSE_TIMER + 2000)
 #define SME_CMD_VDEV_CREATE_DELETE_TIMEOUT QDF_MAX(13000, \
 						SME_VDEV_DELETE_CMD_TIMEOUT + 1)
 

+ 2 - 0
core/sme/inc/sme_internal.h

@@ -525,6 +525,8 @@ struct sme_context {
 	void (*roam_rt_stats_cb)(hdd_handle_t hdd_handle, uint8_t idx,
 				 struct roam_stats_event *roam_stats);
 #endif
+	QDF_STATUS (*sme_vdev_del_cb)(mac_handle_t mac_handle,
+				      struct wlan_objmgr_vdev *vdev);
 };
 
 #endif /* #if !defined( __SMEINTERNAL_H ) */

+ 17 - 6
core/sme/src/common/sme_api.c

@@ -56,6 +56,7 @@
 #include "ol_txrx.h"
 #include "wifi_pos_api.h"
 #include "net/cfg80211.h"
+#include "wifi_pos_pasn_api.h"
 #include <wlan_spectral_utils_api.h>
 #include "wlan_mlme_public_struct.h"
 #include "wlan_mlme_main.h"
@@ -80,7 +81,7 @@
 #include <wlan_mlo_mgr_sta.h>
 #include <wlan_mlo_mgr_main.h>
 #include "wlan_policy_mgr_ucfg.h"
-#include "wma_pasn_peer_api.h"
+#include "wlan_wifi_pos_interface.h"
 
 static QDF_STATUS init_sme_cmd_list(struct mac_context *mac);
 
@@ -774,6 +775,12 @@ static inline void sme_unregister_power_debug_stats_cb(struct mac_context *mac)
 }
 #endif
 
+static void
+sme_register_vdev_delete_callback(struct mac_context *mac)
+{
+	mac->sme.sme_vdev_del_cb = sme_vdev_delete;
+}
+
 /* Global APIs */
 
 /**
@@ -831,6 +838,7 @@ QDF_STATUS sme_open(mac_handle_t mac_handle)
 	sme_trace_init(mac);
 	sme_register_debug_callback();
 	sme_register_power_debug_stats_cb(mac);
+	sme_register_vdev_delete_callback(mac);
 
 	return status;
 }
@@ -4777,19 +4785,22 @@ QDF_STATUS sme_vdev_delete(mac_handle_t mac_handle,
 {
 	QDF_STATUS status;
 	struct mac_context *mac = MAC_CONTEXT(mac_handle);
-	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
 	uint8_t *self_peer_macaddr, vdev_id = wlan_vdev_get_id(vdev);
 	struct scheduler_msg self_peer_delete_msg = {0};
 	struct del_vdev_params *del_self_peer;
+	bool is_pasn_peer_delete_all_required;
 
 	MTRACE(qdf_trace(QDF_MODULE_ID_SME,
 			 TRACE_CODE_SME_RX_HDD_CLOSE_SESSION, vdev_id, 0));
 
-	status = sme_acquire_global_lock(&mac->sme);
+	is_pasn_peer_delete_all_required =
+		wlan_wifi_pos_pasn_peer_delete_all(mac->psoc, vdev_id);
+	if (is_pasn_peer_delete_all_required) {
+		sme_info("Resume vdev delete after pasn peers deletion");
+		return QDF_STATUS_SUCCESS;
+	}
 
-	if (vdev->vdev_mlme.vdev_opmode == QDF_STA_MODE ||
-	    vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE)
-		wma_delete_all_pasn_peers(wma, vdev);
+	status = sme_acquire_global_lock(&mac->sme);
 
 	if (QDF_IS_STATUS_SUCCESS(status)) {
 		status = csr_prepare_vdev_delete(mac, vdev_id, false);

+ 3 - 0
core/wma/inc/wma.h

@@ -182,6 +182,9 @@
 /* Peer create response for 11az PASN peer */
 #define WMA_PASN_PEER_CREATE_RESPONSE 0x0a
 
+#define WMA_PASN_PEER_DELETE_RESPONSE 0x0b
+#define WMA_PEER_DELETE_RESPONSE_TIMEOUT SIR_DELETE_STA_TIMEOUT
+
 /* FW response timeout values in milli seconds */
 #define WMA_VDEV_PLCY_MGR_TIMEOUT        SIR_VDEV_PLCY_MGR_TIMEOUT
 #define WMA_VDEV_HW_MODE_REQUEST_TIMEOUT WMA_VDEV_PLCY_MGR_TIMEOUT

+ 15 - 0
core/wma/inc/wma_internal.h

@@ -1436,6 +1436,21 @@ int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info,
 void wma_remove_req(tp_wma_handle wma, uint8_t vdev_id,
 		    uint8_t type);
 
+/**
+ * wma_find_remove_req_msgtype() - find and remove request for vdev id
+ * @wma: wma handle
+ * @vdev_id: vdev id
+ * @msg_type: message request type
+ *
+ * Find target request for given vdev id & sub type of request.
+ * Remove the same from active list.
+ *
+ * Return: Success if request found, failure other wise
+ */
+struct wma_target_req *wma_find_remove_req_msgtype(tp_wma_handle wma,
+						   uint8_t vdev_id,
+						   uint32_t msg_type);
+
 /**
  * wma_remove_peer_req  - Remove the peer create
  * request from WMA queue

+ 12 - 0
core/wma/inc/wma_pasn_peer_api.h

@@ -77,6 +77,12 @@ wma_pasn_handle_peer_create_conf(tp_wma_handle wma,
  */
 QDF_STATUS
 wma_delete_all_pasn_peers(tp_wma_handle wma, struct wlan_objmgr_vdev *vdev);
+
+QDF_STATUS
+wma_resume_vdev_delete(tp_wma_handle wma, uint8_t vdev_id);
+
+QDF_STATUS
+wma_pasn_peer_delete_all_complete(struct wlan_objmgr_vdev *vdev);
 #else
 static inline QDF_STATUS
 wma_pasn_peer_create(struct wlan_objmgr_psoc *psoc,
@@ -107,5 +113,11 @@ wma_delete_all_pasn_peers(tp_wma_handle wma, struct wlan_objmgr_vdev *vdev)
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline QDF_STATUS
+wma_resume_vdev_delete(tp_wma_handle wma, uint8_t vdev_id)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 #endif

+ 1 - 0
core/wma/inc/wma_types.h

@@ -441,6 +441,7 @@ enum wmamsgtype {
 	WMA_TWT_RESUME_DIALOG_REQUEST =  SIR_HAL_TWT_RESUME_DIALOG_REQUEST,
 	WMA_PEER_CREATE_REQ = SIR_HAL_PEER_CREATE_REQ,
 	WMA_TWT_NUDGE_DIALOG_REQUEST = SIR_HAL_TWT_NUDGE_DIALOG_REQUEST,
+	WMA_PASN_PEER_DELETE_REQUEST = SIR_HAL_PASN_PEER_DELETE_REQUEST,
 };
 
 /* Bit 6 will be used to control BD rate for Management frames */

+ 13 - 13
core/wma/src/wma_dev_if.c

@@ -337,19 +337,9 @@ static struct wma_target_req *wma_find_req(tp_wma_handle wma,
 	return req_msg;
 }
 
-/**
- * wma_find_remove_req_msgtype() - find and remove request for vdev id
- * @wma: wma handle
- * @vdev_id: vdev id
- * @msg_type: message request type
- *
- * Find target request for given vdev id & sub type of request.
- * Remove the same from active list.
- *
- * Return: Success if request found, failure other wise
- */
-static struct wma_target_req *wma_find_remove_req_msgtype(tp_wma_handle wma,
-					   uint8_t vdev_id, uint32_t msg_type)
+struct wma_target_req *wma_find_remove_req_msgtype(tp_wma_handle wma,
+						   uint8_t vdev_id,
+						   uint32_t msg_type)
 {
 	struct wma_target_req *req_msg = NULL;
 	bool found = false;
@@ -3784,6 +3774,16 @@ void wma_hold_req_timer(void *data)
 				wma, peer_mac, QDF_STATUS_E_TIMEOUT,
 				tgt_req->vdev_id);
 		qdf_mem_free(tgt_req->user_data);
+	} else if (tgt_req->msg_type == WMA_PASN_PEER_DELETE_REQUEST &&
+		   tgt_req->type == WMA_PASN_PEER_DELETE_RESPONSE) {
+		wma_err("PASN Peer delete all resp not received. vdev:%d",
+			tgt_req->vdev_id);
+		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash))
+			wma_trigger_recovery_assert_on_fw_timeout(
+				WMA_PASN_PEER_DELETE_RESPONSE,
+				WMA_PEER_DELETE_RESPONSE_TIMEOUT);
+
+		wma_resume_vdev_delete(wma, tgt_req->vdev_id);
 	} else {
 		wma_err("Unhandled timeout for msg_type:%d and type:%d",
 				tgt_req->msg_type, tgt_req->type);

+ 67 - 3
core/wma/src/wma_pasn_peer_api.c

@@ -28,6 +28,7 @@
 #include "wma_types.h"
 #include "wma_internal.h"
 #include "wma_pasn_peer_api.h"
+#include "wifi_pos_pasn_api.h"
 #include "wifi_pos_api.h"
 #include "init_deinit_lmac.h"
 
@@ -164,8 +165,8 @@ wma_pasn_peer_create(struct wlan_objmgr_psoc *psoc,
 				    WMA_PEER_CREATE_RESPONSE_TIMEOUT);
 	if (!wma_req) {
 		wma_err("vdev:%d failed to fill peer create req", vdev_id);
-		wma_remove_req(wma, vdev_id, WMA_PASN_PEER_CREATE_RESPONSE,
-			       peer_addr);
+		wma_remove_peer_req(wma, vdev_id, WMA_PASN_PEER_CREATE_RESPONSE,
+				    peer_addr);
 		wma_pasn_peer_remove(psoc, peer_addr, vdev_id, false);
 		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
 		qdf_mem_free(peer_create_rsp);
@@ -224,11 +225,58 @@ wma_pasn_handle_peer_create_conf(tp_wma_handle wma,
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS
+wma_resume_vdev_delete(tp_wma_handle wma, uint8_t vdev_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct mac_context *mac = wma->mac_context;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
+						    WLAN_LEGACY_WMA_ID);
+	if (!vdev) {
+		wma_err("Vdev is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	lim_pasn_peer_del_all_resp_vdev_delete_resume(mac, vdev);
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wma_pasn_peer_delete_all_complete(struct wlan_objmgr_vdev *vdev)
+{
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+	struct wma_target_req *req_msg;
+	uint8_t vdev_id = wlan_vdev_get_id(vdev);
+
+	req_msg = wma_find_remove_req_msgtype(wma, vdev_id,
+					      WMA_PASN_PEER_DELETE_REQUEST);
+	if (!req_msg) {
+		wma_debug("vdev:%d Failed to lookup pasn peer del req",
+			  vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	qdf_mc_timer_stop(&req_msg->event_timeout);
+	qdf_mc_timer_destroy(&req_msg->event_timeout);
+
+	qdf_mem_free(req_msg);
+
+	wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
+
+	return wma_resume_vdev_delete(wma, vdev_id);
+}
+
 QDF_STATUS
 wma_delete_all_pasn_peers(tp_wma_handle wma, struct wlan_objmgr_vdev *vdev)
 {
 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
+	struct wma_target_req *msg;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	uint8_t vdev_id = wlan_vdev_get_id(vdev);
 
 	tx_ops = wifi_pos_get_tx_ops(wma->psoc);
 	if (!tx_ops || !tx_ops->wifi_pos_vdev_delete_all_ranging_peers_cb) {
@@ -236,12 +284,28 @@ wma_delete_all_pasn_peers(tp_wma_handle wma, struct wlan_objmgr_vdev *vdev)
 		return QDF_STATUS_E_INVAL;
 	}
 
+	wma_acquire_wakelock(&wma->wmi_cmd_rsp_wake_lock,
+			     WMA_PEER_DELETE_RESPONSE_TIMEOUT);
+	wma_err("Delete all ranging peers vdev:%d",
+		wlan_vdev_get_id(vdev));
 	status = tx_ops->wifi_pos_vdev_delete_all_ranging_peers_cb(vdev);
 	if (QDF_IS_STATUS_ERROR(status)) {
+		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
 		wma_err("Delete all ranging peers failed");
 		return status;
 	}
 
+	msg = wma_fill_hold_req(wma, vdev_id,
+				WMA_PASN_PEER_DELETE_REQUEST,
+				WMA_PASN_PEER_DELETE_RESPONSE, NULL,
+				WMA_PEER_DELETE_RESPONSE_TIMEOUT);
+	if (!msg) {
+		wma_err("Failed to allocate request for vdev_id %d", vdev_id);
+		wma_remove_req(wma, vdev_id, WMA_PASN_PEER_DELETE_RESPONSE);
+		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
+		wma_resume_vdev_delete(wma, vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	return status;
 }
-#endif