Merge "qcacld-3.0: pass supported device id list to platform driver when loading" into wlan-cld3.driver.lnx.2.0.c2
diff --git a/Android.mk b/Android.mk
index c06f690..e5320eb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -68,13 +68,14 @@
 
 else # Multi-ok check
 
+WLAN_PROFILE := default
+
 ifeq ($(LOCAL_DEV_NAME), qcacld-3.0)
 
 LOCAL_DEV_NAME := wlan
 LOCAL_MOD_NAME := wlan
 CMN_OFFSET := ..
 LOCAL_SRC_DIR :=
-WLAN_PROFILE := default
 TARGET_FW_DIR := firmware/wlan/qca_cld
 TARGET_CFG_PATH := /vendor/etc/wifi
 TARGET_MAC_BIN_PATH := /mnt/vendor/persist
@@ -83,7 +84,10 @@
 
 LOCAL_SRC_DIR := .$(LOCAL_DEV_NAME)
 CMN_OFFSET := .
+# Use default profile if WLAN_CFG_USE_DEFAULT defined.
+ifeq ($(WLAN_CFG_USE_DEFAULT),)
 WLAN_PROFILE := $(LOCAL_DEV_NAME)
+endif
 TARGET_FW_DIR := firmware/wlan/qca_cld/$(LOCAL_DEV_NAME)
 TARGET_CFG_PATH := /vendor/etc/wifi/$(LOCAL_DEV_NAME)
 TARGET_MAC_BIN_PATH := /mnt/vendor/persist/$(LOCAL_DEV_NAME)
diff --git a/Kbuild b/Kbuild
index 22f9c66..e69054e 100644
--- a/Kbuild
+++ b/Kbuild
@@ -31,7 +31,6 @@
 endif
 endif
 
-include $(WLAN_ROOT)/configs/$(CONFIG_QCA_CLD_WLAN_PROFILE)_defconfig
 
 # add configurations in WLAN_CFG_OVERRIDE
 ifneq ($(WLAN_CFG_OVERRIDE),)
@@ -45,6 +44,8 @@
 $(warning "Overriding WLAN config with: $(shell cat $(WLAN_CFG_OVERRIDE_FILE))")
 endif
 
+include $(WLAN_ROOT)/configs/$(CONFIG_QCA_CLD_WLAN_PROFILE)_defconfig
+
 ############ UAPI ############
 UAPI_DIR :=	uapi
 UAPI_INC :=	-I$(WLAN_ROOT)/$(UAPI_DIR)/linux
@@ -277,6 +278,10 @@
 HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_cfr.o
 endif
 
+ifeq ($(CONFIG_WLAN_HANG_EVENT), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_hang_event.o
+endif
+
 ###### OSIF_SYNC ########
 SYNC_DIR := os_if/sync
 SYNC_INC_DIR := $(SYNC_DIR)/inc
@@ -646,6 +651,10 @@
 	QDF_OBJS += $(QDF_OBJ_DIR)/qdf_tracker.o
 endif
 
+ifeq ($(CONFIG_WLAN_HANG_EVENT), y)
+	QDF_OBJS += $(QDF_OBJ_DIR)/qdf_notifier.o
+endif
+
 ifeq ($(CONFIG_QDF_TEST), y)
 	QDF_OBJS += $(QDF_TEST_OBJ_DIR)/qdf_delayed_work_test.o
 	QDF_OBJS += $(QDF_TEST_OBJ_DIR)/qdf_hashtable_test.o
@@ -657,6 +666,10 @@
 	QDF_OBJS += $(QDF_TEST_OBJ_DIR)/qdf_types_test.o
 endif
 
+ifeq ($(CONFIG_WLAN_HANG_EVENT), y)
+	QDF_OBJS += $(QDF_OBJ_DIR)/qdf_hang_event_notifier.o
+endif
+
 cppflags-$(CONFIG_TALLOC_DEBUG) += -DWLAN_TALLOC_DEBUG
 cppflags-$(CONFIG_QDF_TEST) += -DWLAN_DELAYED_WORK_TEST
 cppflags-$(CONFIG_QDF_TEST) += -DWLAN_HASHTABLE_TEST
@@ -666,6 +679,7 @@
 cppflags-$(CONFIG_QDF_TEST) += -DWLAN_TALLOC_TEST
 cppflags-$(CONFIG_QDF_TEST) += -DWLAN_TRACKER_TEST
 cppflags-$(CONFIG_QDF_TEST) += -DWLAN_TYPES_TEST
+cppflags-$(CONFIG_WLAN_HANG_EVENT) += -DWLAN_HANG_EVENT
 
 ############ WBUFF ############
 WBUFF_OS_DIR :=	wbuff
@@ -1353,6 +1367,10 @@
 WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_cfr_api.o
 endif
 
+ifeq ($(CONFIG_WLAN_HANG_EVENT), y)
+WMI_OBJS += $(WMI_OBJ_DIR)/wmi_hang_event.o
+endif
+
 ########### FWLOG ###########
 FWLOG_DIR := $(WLAN_COMMON_ROOT)/utils/fwlog
 
@@ -1677,6 +1695,10 @@
 HTC_OBJS += $(WLAN_COMMON_ROOT)/$(HTC_DIR)/htc_credit_history.o
 endif
 
+ifeq ($(CONFIG_WLAN_HANG_EVENT), y)
+HTC_OBJS += $(WLAN_COMMON_ROOT)/$(HTC_DIR)/htc_hang_event.o
+endif
+
 ########### HIF ###########
 HIF_DIR := hif
 HIF_CE_DIR := $(HIF_DIR)/src/ce
@@ -2871,6 +2893,7 @@
 cppflags-$(CONFIG_LITHIUM) += -DDP_RX_PKT_NO_PEER_DELIVER
 cppflags-$(CONFIG_LITHIUM) += -DFEATURE_ALIGN_STATS_FROM_DP
 cppflags-$(CONFIG_LITHIUM) += -DDROP_RXDMA_DECRYPT_ERR
+cppflags-$(CONFIG_LITHIUM) += -DDP_RX_SPECIAL_FRAME_NEED
 cppflags-$(CONFIG_VERBOSE_DEBUG) += -DENABLE_VERBOSE_DEBUG
 cppflags-$(CONFIG_RX_DESC_DEBUG_CHECK) += -DRX_DESC_DEBUG_CHECK
 cppflags-$(CONFIG_REGISTER_OP_DEBUG) += -DHAL_REGISTER_WRITE_DEBUG
@@ -2923,6 +2946,9 @@
 ifdef CONFIG_HIF_LARGE_CE_RING_HISTORY
 ccflags-y += -DHIF_CE_HISTORY_MAX=$(CONFIG_HIF_LARGE_CE_RING_HISTORY)
 endif
+
+cppflags-$(CONFIG_WLAN_HANG_EVENT) += -DHIF_CE_LOG_INFO
+cppflags-$(CONFIG_WLAN_HANG_EVENT) += -DDP_SUPPORT_RECOVERY_NOTIFY
 #endof dummy flags
 
 ccflags-$(CONFIG_ENABLE_SIZE_OPTIMIZE) += -Os
@@ -3198,6 +3224,8 @@
 
 cppflags-$(CONFIG_RX_FISA) += -DWLAN_SUPPORT_RX_FISA
 
+cppflags-$(CONFIG_MORE_TX_DESC) += -DTX_TO_NPEERS_INC_TX_DESCS
+
 ccflags-$(CONFIG_HASTINGS_BT_WAR) += -DHASTINGS_BT_WAR
 
 cppflags-$(CONFIG_SLUB_DEBUG_ON) += -DHIF_CONFIG_SLUB_DEBUG_ON
@@ -3212,6 +3240,8 @@
 cppflags-$(CONFIG_WLAN_CUSTOM_DSCP_UP_MAP) += -DWLAN_CUSTOM_DSCP_UP_MAP
 cppflags-$(CONFIG_WLAN_SEND_DSCP_UP_MAP_TO_FW) += -DWLAN_SEND_DSCP_UP_MAP_TO_FW
 
+cppflags-$(CONFIG_HIF_CPU_PERF_AFFINE_MASK) += -DHIF_CPU_PERF_AFFINE_MASK
+
 KBUILD_CPPFLAGS += $(cppflags-y)
 
 # Currently, for versions of gcc which support it, the kernel Makefile
diff --git a/components/blacklist_mgr/core/inc/wlan_blm_core.h b/components/blacklist_mgr/core/inc/wlan_blm_core.h
index 697c56f..a89c8e5 100644
--- a/components/blacklist_mgr/core/inc/wlan_blm_core.h
+++ b/components/blacklist_mgr/core/inc/wlan_blm_core.h
@@ -183,6 +183,22 @@
 			     struct reject_ap_info *ap_info);
 
 /**
+ * blm_send_reject_ap_list_to_fw() - Send the blacklist BSSIDs to FW
+ * @pdev: Pdev object
+ * @reject_db_list: List of blacklist BSSIDs
+ * @cfg: Blacklist manager cfg
+ *
+ * This API will send the blacklist BSSIDs to FW for avoiding or blacklisting
+ * in roaming scenarios.
+ *
+ * Return: None
+ */
+void
+blm_send_reject_ap_list_to_fw(struct wlan_objmgr_pdev *pdev,
+			      qdf_list_t *reject_db_list,
+			      struct blm_config *cfg);
+
+/**
  * blm_add_userspace_black_list() - Clear already existing userspace BSSID, and
  * add the new ones to blacklist manager.
  * @pdev: pdev object
diff --git a/components/blacklist_mgr/core/src/wlan_blm_core.c b/components/blacklist_mgr/core/src/wlan_blm_core.c
index 40d2842..0ff1d15 100644
--- a/components/blacklist_mgr/core/src/wlan_blm_core.c
+++ b/components/blacklist_mgr/core/src/wlan_blm_core.c
@@ -659,7 +659,7 @@
 	}
 }
 
-static void
+void
 blm_send_reject_ap_list_to_fw(struct wlan_objmgr_pdev *pdev,
 			      qdf_list_t *reject_db_list,
 			      struct blm_config *cfg)
@@ -695,12 +695,6 @@
 			     DRIVER_AVOID_TYPE,
 			     PDEV_MAX_NUM_BSSID_DISALLOW_LIST, cfg);
 
-	if (!reject_params.num_of_reject_bssid) {
-		blm_debug("no candidate present in reject ap list.");
-		qdf_mem_free(reject_params.bssid_list);
-		return;
-	}
-
 	status = tgt_blm_send_reject_list_to_fw(pdev, &reject_params);
 
 	if (QDF_IS_STATUS_ERROR(status))
diff --git a/components/blacklist_mgr/dispatcher/src/wlan_blm_ucfg_api.c b/components/blacklist_mgr/dispatcher/src/wlan_blm_ucfg_api.c
index afd603b..b53d5f3 100644
--- a/components/blacklist_mgr/dispatcher/src/wlan_blm_ucfg_api.c
+++ b/components/blacklist_mgr/dispatcher/src/wlan_blm_ucfg_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-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
@@ -144,6 +144,9 @@
 ucfg_blm_wifi_off(struct wlan_objmgr_pdev *pdev)
 {
 	struct blm_pdev_priv_obj *blm_ctx;
+	struct blm_psoc_priv_obj *blm_psoc_obj;
+	struct blm_config *cfg;
+	QDF_STATUS status;
 
 	if (!pdev) {
 		blm_err("pdev is NULL");
@@ -151,10 +154,22 @@
 	}
 
 	blm_ctx = blm_get_pdev_obj(pdev);
-	if (!blm_ctx) {
-		blm_err("blm_ctx is NULL");
+	blm_psoc_obj = blm_get_psoc_obj(wlan_pdev_get_psoc(pdev));
+
+	if (!blm_ctx || !blm_psoc_obj) {
+		blm_err("blm_ctx or blm_psoc_obj is NULL");
+		return ;
+	}
+
+	status = qdf_mutex_acquire(&blm_ctx->reject_ap_list_lock);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		blm_err("failed to acquire reject_ap_list_lock");
 		return;
 	}
 
+	cfg = &blm_psoc_obj->blm_cfg;
+
 	blm_flush_reject_ap_list(blm_ctx);
+	blm_send_reject_ap_list_to_fw(pdev, &blm_ctx->reject_ap_list, cfg);
+	qdf_mutex_release(&blm_ctx->reject_ap_list_lock);
 }
diff --git a/components/interop_issues_ap/dispatcher/src/wlan_interop_issues_ap_tgt_api.c b/components/interop_issues_ap/dispatcher/src/wlan_interop_issues_ap_tgt_api.c
index dd6cdae..e58bd4a 100644
--- a/components/interop_issues_ap/dispatcher/src/wlan_interop_issues_ap_tgt_api.c
+++ b/components/interop_issues_ap/dispatcher/src/wlan_interop_issues_ap_tgt_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-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
@@ -37,10 +37,11 @@
 	return QDF_STATUS_SUCCESS;
 }
 
-static void wlan_interop_issues_ap_info_cbk(struct scheduler_msg *msg)
+static QDF_STATUS wlan_interop_issues_ap_info_cbk(struct scheduler_msg *msg)
 {
 	struct wlan_interop_issues_ap_event *data;
 	struct wlan_interop_issues_ap_callbacks *cbs;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	data = msg->bodyptr;
 	data->pdev = wlan_objmgr_get_pdev_by_id(data->psoc,
@@ -48,6 +49,7 @@
 						WLAN_INTEROP_ISSUES_AP_ID);
 	if (!data->pdev) {
 		interop_issues_ap_err("pdev is null.");
+		status = QDF_STATUS_E_FAILURE;
 		goto err;
 	}
 
@@ -59,6 +61,7 @@
 err:
 	qdf_mem_free(data);
 	msg->bodyptr = NULL;
+	return status;
 }
 
 QDF_STATUS tgt_interop_issues_ap_info_callback(struct wlan_objmgr_psoc *psoc,
diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c
index c5d19df..384c4ac 100644
--- a/components/mlme/core/src/wlan_mlme_main.c
+++ b/components/mlme/core/src/wlan_mlme_main.c
@@ -1462,6 +1462,7 @@
 {
 	lfr->lfr3_roaming_offload =
 		cfg_get(psoc, CFG_LFR3_ROAMING_OFFLOAD);
+	lfr->enable_self_bss_roam = cfg_get(psoc, CFG_LFR3_ENABLE_SELF_BSS_ROAM);
 	lfr->enable_roam_reason_vsie =
 		cfg_get(psoc, CFG_ENABLE_ROAM_REASON_VSIE);
 	lfr->enable_disconnect_roam_offload =
diff --git a/components/mlme/dispatcher/inc/cfg_mlme_lfr.h b/components/mlme/dispatcher/inc/cfg_mlme_lfr.h
index 2299c7d..fbf30d2 100644
--- a/components/mlme/dispatcher/inc/cfg_mlme_lfr.h
+++ b/components/mlme/dispatcher/inc/cfg_mlme_lfr.h
@@ -2150,6 +2150,28 @@
 
 /*
  * <ini>
+ * enable_self_bss_roam - enable/disable roaming to self bss
+ * @Min: 0
+ * @Max: 1
+ * @Default: 1
+ *
+ * This INI is used to enable/disable roaming to already connected BSSID
+ *
+ * Related: None
+ *
+ * Supported Feature: Roaming
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_LFR3_ENABLE_SELF_BSS_ROAM CFG_INI_BOOL( \
+	"enable_self_bss_roam", \
+	0, \
+	"enable self bss roam")
+
+/*
+ * <ini>
  * enable_disconnect_roam_offload - Enable/Disable emergency roaming during
  * deauth/disassoc
  * @Min: 0 - Disabled
@@ -2414,6 +2436,7 @@
 
 #define ROAM_OFFLOAD_ALL \
 	CFG(CFG_LFR3_ROAMING_OFFLOAD) \
+	CFG(CFG_LFR3_ENABLE_SELF_BSS_ROAM) \
 	CFG(CFG_LFR_ENABLE_DISCONNECT_ROAM) \
 	CFG(CFG_LFR_ENABLE_IDLE_ROAM) \
 	CFG(CFG_LFR_IDLE_ROAM_RSSI_DELTA) \
diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
index b5740d1..76071e6 100644
--- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
+++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
@@ -1431,6 +1431,7 @@
  * @mawc_roam_enabled:              Enable/Disable MAWC during roaming
  * @enable_fast_roam_in_concurrency:Enable LFR roaming on STA during concurrency
  * @lfr3_roaming_offload:           Enable/disable roam offload feature
+ * @enable_self_bss_roam:               enable roaming to connected BSSID
  * @enable_disconnect_roam_offload: enable disassoc/deauth roam scan.
  * @enable_idle_roam: flag to enable/disable idle roam in fw
  * @idle_roam_rssi_delta: rssi delta of connected ap which is used to
@@ -1540,6 +1541,7 @@
 	bool enable_fast_roam_in_concurrency;
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	bool lfr3_roaming_offload;
+	bool enable_self_bss_roam;
 	bool enable_disconnect_roam_offload;
 	bool enable_idle_roam;
 	uint32_t idle_roam_rssi_delta;
diff --git a/components/nan/core/inc/nan_public_structs.h b/components/nan/core/inc/nan_public_structs.h
index 15e612b..2b72edb 100644
--- a/components/nan/core/inc/nan_public_structs.h
+++ b/components/nan/core/inc/nan_public_structs.h
@@ -613,6 +613,17 @@
 };
 
 /**
+ * struct nan_datapath_peer_ind - ndp peer indication
+ * @msg: msg received by FW
+ * @data_len: data length
+ *
+ */
+struct nan_dump_msg {
+	uint8_t *msg;
+	uint32_t data_len;
+};
+
+/**
  * struct nan_datapath_confirm_event - ndp confirmation event from FW
  * @vdev: pointer to vdev object
  * @ndp_instance_id: ndp instance id for which confirm is being generated
diff --git a/components/pmo/core/src/wlan_pmo_suspend_resume.c b/components/pmo/core/src/wlan_pmo_suspend_resume.c
index 3e9b1c3..73ac668 100644
--- a/components/pmo/core/src/wlan_pmo_suspend_resume.c
+++ b/components/pmo/core/src/wlan_pmo_suspend_resume.c
@@ -816,7 +816,7 @@
 			pmo_tgt_psoc_get_host_credits(psoc),
 			pmo_tgt_psoc_get_pending_cmnds(psoc));
 		pmo_tgt_update_target_suspend_flag(psoc, false);
-		qdf_trigger_self_recovery(QDF_SUSPEND_TIMEOUT);
+		qdf_trigger_self_recovery(psoc, QDF_SUSPEND_TIMEOUT);
 		goto out;
 	}
 
@@ -834,7 +834,7 @@
 		pmo_err("No Credits after HTC ACK:%d, pending_cmds:%d,"
 			 "cannot resume back", host_credits, wmi_pending_cmds);
 		htc_dump_counter_info(pmo_core_psoc_get_htc_handle(psoc));
-		qdf_trigger_self_recovery(QDF_SUSPEND_TIMEOUT);
+		qdf_trigger_self_recovery(psoc, QDF_SUSPEND_TIMEOUT);
 	}
 	pmo_debug("WOW enabled successfully in fw: credits:%d pending_cmds: %d",
 		host_credits, wmi_pending_cmds);
@@ -871,7 +871,7 @@
 	if (QDF_IS_STATUS_ERROR(status)) {
 		pmo_err("Failed to get ACK from firmware for pdev suspend");
 		pmo_tgt_update_target_suspend_flag(psoc, false);
-		qdf_trigger_self_recovery(QDF_SUSPEND_TIMEOUT);
+		qdf_trigger_self_recovery(psoc, QDF_SUSPEND_TIMEOUT);
 	}
 
 out:
@@ -1136,7 +1136,7 @@
 
 fail:
 	if (status != QDF_STATUS_SUCCESS)
-		qdf_trigger_self_recovery(QDF_RESUME_TIMEOUT);
+		qdf_trigger_self_recovery(psoc, QDF_RESUME_TIMEOUT);
 
 dec_psoc_ref:
 	pmo_psoc_put_ref(psoc);
@@ -1182,7 +1182,7 @@
 		pmo_err("Pending commands %d credits %d",
 			pmo_tgt_psoc_get_pending_cmnds(psoc),
 			pmo_tgt_psoc_get_host_credits(psoc));
-		qdf_trigger_self_recovery(QDF_RESUME_TIMEOUT);
+		qdf_trigger_self_recovery(psoc, QDF_RESUME_TIMEOUT);
 	} else {
 		pmo_debug("Host wakeup received");
 	}
@@ -1254,7 +1254,7 @@
 		pmo_fatal("Pending commands %d credits %d",
 			pmo_tgt_psoc_get_pending_cmnds(psoc),
 			pmo_tgt_psoc_get_host_credits(psoc));
-		qdf_trigger_self_recovery(QDF_RESUME_TIMEOUT);
+		qdf_trigger_self_recovery(psoc, QDF_RESUME_TIMEOUT);
 	} else {
 		pmo_debug("Host wakeup received");
 	}
diff --git a/components/target_if/nan/src/target_if_nan.c b/components/target_if/nan/src/target_if_nan.c
index 3919315..3706b3f 100644
--- a/components/target_if/nan/src/target_if_nan.c
+++ b/components/target_if/nan/src/target_if_nan.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -224,6 +224,42 @@
 	return status;
 }
 
+static int target_if_nan_dmesg_handler(ol_scn_t scn, uint8_t *data,
+				       uint32_t data_len)
+{
+	QDF_STATUS status;
+	struct nan_dump_msg msg;
+	struct wmi_unified *wmi_handle;
+	struct wlan_objmgr_psoc *psoc;
+
+	psoc = target_if_get_psoc_from_scn_hdl(scn);
+	if (!psoc) {
+		target_if_err("psoc is null");
+		return -EINVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		target_if_err("wmi_handle is null");
+		return -EINVAL;
+	}
+
+	status = wmi_extract_nan_msg(wmi_handle, data, &msg);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		target_if_err("parsing of event failed, %d", status);
+		return -EINVAL;
+	}
+
+	if (!msg.msg) {
+		target_if_err("msg not present %d", msg.data_len);
+		return -EINVAL;
+	}
+
+	target_if_info("%s", msg.msg);
+
+	return 0;
+}
+
 static int target_if_ndp_initiator_rsp_handler(ol_scn_t scn, uint8_t *data,
 						uint32_t len)
 {
@@ -968,6 +1004,15 @@
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	ret = wmi_unified_register_event_handler(handle, wmi_nan_dmesg_event_id,
+						 target_if_nan_dmesg_handler,
+						 WMI_RX_UMAC_CTX);
+	if (ret) {
+		target_if_err("wmi event registration failed, ret: %d", ret);
+		target_if_nan_deregister_events(psoc);
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	ret = wmi_unified_register_event_handler(handle,
 		wmi_ndp_indication_event_id,
 		target_if_ndp_ind_handler,
@@ -1092,6 +1137,13 @@
 	}
 
 	ret = wmi_unified_unregister_event_handler(handle,
+						   wmi_nan_dmesg_event_id);
+	if (ret) {
+		target_if_err("wmi event deregistration failed, ret: %d", ret);
+		status = ret;
+	}
+
+	ret = wmi_unified_unregister_event_handler(handle,
 				wmi_ndp_initiator_rsp_event_id);
 	if (ret) {
 		target_if_err("wmi event deregistration failed, ret: %d", ret);
diff --git a/configs/default_defconfig b/configs/default_defconfig
index 7fde710..a60e322 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -973,6 +973,7 @@
 		CONFIG_WLAN_FEATURE_DP_EVENT_HISTORY := y
 		CONFIG_HIF_CE_DEBUG_DATA_BUF := y
 		CONFIG_WLAN_RECORD_RX_PADDR := y
+		CONFIG_HIF_CPU_PERF_AFFINE_MASK := y
 	endif
 	CONFIG_WLAN_SUPPORT_DATA_STALL := y
 	CONFIG_WLAN_DP_PER_RING_TYPE_CONFIG := y
@@ -1068,6 +1069,7 @@
 #Enable 6 GHz Band
 CONFIG_BAND_6GHZ := y
 CONFIG_RX_FISA := y
+CONFIG_MORE_TX_DESC := y
 
 endif
 
diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h
index 473f609..3c43e6d 100644
--- a/core/cds/inc/cds_api.h
+++ b/core/cds/inc/cds_api.h
@@ -372,6 +372,10 @@
  */
 #define cds_trigger_recovery(reason) \
 	__cds_trigger_recovery(reason, __func__, __LINE__)
+
+void cds_trigger_recovery_psoc(void *psoc, enum qdf_hang_reason reason,
+			       const char *func, const uint32_t line);
+
 void __cds_trigger_recovery(enum qdf_hang_reason reason, const char *func,
 			    const uint32_t line);
 
diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c
index 33245a5..78b8fa3 100644
--- a/core/cds/src/cds_api.c
+++ b/core/cds/src/cds_api.c
@@ -74,6 +74,10 @@
 #include "wlan_mlme_ucfg_api.h"
 #include "cfg_ucfg_api.h"
 #include "wlan_cp_stats_mc_ucfg_api.h"
+#include <qdf_hang_event_notifier.h>
+#include <qdf_notifier.h>
+#include <qwlan_version.h>
+#include <qdf_trace.h>
 
 /* Preprocessor Definitions and Constants */
 
@@ -86,7 +90,22 @@
 
 static uint8_t cds_multicast_logging;
 
+struct cds_hang_event_fixed_param {
+	uint32_t tlv_header;
+	uint32_t recovery_reason;
+	char driver_version[11];
+	char hang_event_version[3];
+} qdf_packed;
+
 #ifdef QCA_WIFI_QCA8074
+static inline int
+cds_send_delba(struct cdp_ctrl_objmgr_psoc *psoc,
+	       uint8_t vdev_id, uint8_t *peer_macaddr,
+	       uint8_t tid, uint8_t reason_code)
+{
+	return wma_dp_send_delba_ind(vdev_id, peer_macaddr, tid, reason_code);
+}
+
 static struct ol_if_ops  dp_ol_if_ops = {
 	.peer_set_default_routing = target_if_peer_set_default_routing,
 	.peer_rx_reorder_queue_setup = target_if_peer_rx_reorder_queue_setup,
@@ -95,7 +114,8 @@
 	.lro_hash_config = target_if_lro_hash_config,
 	.rx_invalid_peer = wma_rx_invalid_peer_ind,
 	.is_roam_inprogress = wma_is_roam_in_progress,
-	.get_con_mode = cds_get_conparam
+	.get_con_mode = cds_get_conparam,
+	.send_delba = cds_send_delba,
     /* TODO: Add any other control path calls required to OL_IF/WMA layer */
 };
 #else
@@ -195,7 +215,7 @@
 
 	gp_cds_context->qdf_ctx = &g_qdf_ctx;
 
-	qdf_register_self_recovery_callback(__cds_trigger_recovery);
+	qdf_register_self_recovery_callback(cds_trigger_recovery_psoc);
 	qdf_register_fw_down_callback(cds_is_fw_down);
 	qdf_register_is_driver_unloading_callback(cds_is_driver_unloading);
 	qdf_register_recovering_state_query_callback(cds_is_driver_recovering);
@@ -504,6 +524,47 @@
 	}
 }
 
+static int cds_hang_event_notifier_call(struct notifier_block *block,
+					unsigned long state,
+					void *data)
+{
+	struct qdf_notifer_data *cds_hang_data = data;
+	uint32_t total_len;
+	struct cds_hang_event_fixed_param *cmd;
+	uint8_t *cds_hang_evt_buff;
+
+	if (!cds_hang_data)
+		return NOTIFY_STOP_MASK;
+
+	cds_hang_evt_buff = cds_hang_data->hang_data;
+
+	if (!cds_hang_evt_buff)
+		return NOTIFY_STOP_MASK;
+
+	if (cds_hang_data->offset >= QDF_WLAN_MAX_HOST_OFFSET)
+		return NOTIFY_STOP_MASK;
+
+	total_len = sizeof(*cmd);
+
+	cds_hang_evt_buff = cds_hang_data->hang_data + cds_hang_data->offset;
+	cmd = (struct cds_hang_event_fixed_param *)cds_hang_evt_buff;
+	QDF_HANG_EVT_SET_HDR(&cmd->tlv_header, HANG_EVT_TAG_CDS,
+			     QDF_HANG_GET_STRUCT_TLVLEN(*cmd));
+
+	cmd->recovery_reason = gp_cds_context->recovery_reason;
+
+	qdf_mem_copy(&cmd->driver_version, QWLAN_VERSIONSTR, 11);
+
+	qdf_mem_copy(&cmd->hang_event_version, QDF_HANG_EVENT_VERSION, 3);
+
+	cds_hang_data->offset += total_len;
+	return NOTIFY_OK;
+}
+
+static qdf_notif_block cds_hang_event_notifier = {
+	.notif_block.notifier_call = cds_hang_event_notifier_call,
+};
+
 /**
  * cds_open() - open the CDS Module
  *
@@ -729,6 +790,7 @@
 	}
 
 	ucfg_mc_cp_stats_register_pmo_handler();
+	qdf_hang_event_register_notifier(&cds_hang_event_notifier);
 
 	return QDF_STATUS_SUCCESS;
 
@@ -1164,6 +1226,7 @@
 {
 	QDF_STATUS qdf_status;
 
+	qdf_hang_event_unregister_notifier(&cds_hang_event_notifier);
 	qdf_status = cds_sched_close();
 	QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
 	if (QDF_IS_STATUS_ERROR(qdf_status))
@@ -1832,6 +1895,13 @@
 	cds_trigger_recovery_handler(func, line);
 }
 
+void cds_trigger_recovery_psoc(void *psoc, enum qdf_hang_reason reason,
+			       const char *func, const uint32_t line)
+{
+	__cds_trigger_recovery(reason, func, line);
+}
+
+
 /**
  * cds_get_recovery_reason() - get self recovery reason
  * @reason: recovery reason
diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c
index 8d1dde1..3bdf3f0 100644
--- a/core/dp/txrx/ol_txrx.c
+++ b/core/dp/txrx/ol_txrx.c
@@ -83,7 +83,10 @@
 #include <ol_txrx_ipa.h>
 #include "wlan_roam_debug.h"
 #include "cfg_ucfg_api.h"
-
+#ifdef DP_SUPPORT_RECOVERY_NOTIFY
+#include <qdf_notifier.h>
+#include <qdf_hang_event_notifier.h>
+#endif
 
 #define DPT_DEBUGFS_PERMS	(QDF_FILE_USR_READ |	\
 				QDF_FILE_USR_WRITE |	\
@@ -3322,6 +3325,63 @@
 	return status;
 }
 
+#ifdef DP_SUPPORT_RECOVERY_NOTIFY
+static
+int ol_peer_recovery_notifier_cb(struct notifier_block *block,
+				 unsigned long state, void *data)
+{
+	struct qdf_notifer_data *notif_data = data;
+	qdf_notif_block *notif_block;
+	struct ol_txrx_peer_t *peer;
+	struct peer_hang_data hang_data;
+	enum peer_debug_id_type dbg_id;
+
+	if (!data || !block)
+		return -EINVAL;
+
+	notif_block = qdf_container_of(block, qdf_notif_block, notif_block);
+
+	peer = notif_block->priv_data;
+	if (!peer)
+		return -EINVAL;
+
+	QDF_HANG_EVT_SET_HDR(&hang_data.tlv_header,
+			     HANG_EVT_TAG_DP_PEER_INFO,
+			     QDF_HANG_GET_STRUCT_TLVLEN(struct peer_hang_data));
+
+	qdf_mem_copy(&hang_data.peer_mac_addr, &peer->mac_addr.raw,
+		     QDF_MAC_ADDR_SIZE);
+
+	for (dbg_id = 0; dbg_id < PEER_DEBUG_ID_MAX; dbg_id++)
+		if (qdf_atomic_read(&peer->access_list[dbg_id]))
+			hang_data.peer_timeout_bitmask |= (1 << dbg_id);
+
+	qdf_mem_copy(notif_data->hang_data + notif_data->offset,
+		     &hang_data, sizeof(struct peer_hang_data));
+	notif_data->offset += sizeof(struct peer_hang_data);
+
+	return 0;
+}
+
+static qdf_notif_block ol_peer_recovery_notifier = {
+	.notif_block.notifier_call = ol_peer_recovery_notifier_cb,
+};
+
+static
+QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer)
+{
+	ol_peer_recovery_notifier.priv_data = peer;
+
+	return qdf_hang_event_register_notifier(&ol_peer_recovery_notifier);
+}
+#else
+static inline
+QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 /**
  * peer_unmap_timer_handler() - peer unmap timer function
  * @data: peer object pointer
@@ -3340,6 +3400,7 @@
 	ol_txrx_err("peer %pK ("QDF_MAC_ADDR_STR")",
 		    peer,
 		    QDF_MAC_ADDR_ARRAY(peer->mac_addr.raw));
+	ol_register_peer_recovery_notifier(peer);
 
 	cds_trigger_recovery(QDF_PEER_UNMAP_TIMEDOUT);
 }
diff --git a/core/dp/txrx/ol_txrx.h b/core/dp/txrx/ol_txrx.h
index 695b0c2..07e3127 100644
--- a/core/dp/txrx/ol_txrx.h
+++ b/core/dp/txrx/ol_txrx.h
@@ -117,6 +117,12 @@
 #define TXRX_HL_TX_DESC_QUEUE_RESTART_TH \
 		(TXRX_HL_TX_DESC_HI_PRIO_RESERVED + 100)
 
+struct peer_hang_data {
+	uint32_t tlv_header;
+	uint8_t peer_mac_addr[QDF_MAC_ADDR_SIZE];
+	uint16_t peer_timeout_bitmask;
+} qdf_packed;
+
 #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS)
 
 void
diff --git a/core/hdd/inc/hdd_dp_cfg.h b/core/hdd/inc/hdd_dp_cfg.h
index 1756aeb..1fe2d77 100644
--- a/core/hdd/inc/hdd_dp_cfg.h
+++ b/core/hdd/inc/hdd_dp_cfg.h
@@ -1251,7 +1251,7 @@
  * <ini>
  * gEnableNUDTracking - Will enable or disable NUD tracking within driver
  * @Min: 0
- * @Max: 2
+ * @Max: 3
  * @Default: 2
  *
  * This ini is used to specify the behaviour of the driver for NUD tracking.
@@ -1261,7 +1261,7 @@
  * the connected BSSID.
  * 2: Driver will track the NUD failures and if honoured will roam away from
  * the connected BSSID to a new BSSID to retain the data connectivity.
- *
+ * 3: Driver will try to roam to a new AP but if roam fails, disconnect.
  * Related: None
  *
  * Supported Feature: STA
@@ -1270,15 +1270,11 @@
  *
  * <ini>
  */
-#define CFG_DP_ROAM_AFTER_NUD_FAIL                   2
-#define CFG_DP_DISCONNECT_AFTER_NUD_FAIL             1
-#define CFG_DP_DISABLE_NUD_TRACKING                  0
-
 #define CFG_DP_ENABLE_NUD_TRACKING \
 		CFG_INI_UINT("gEnableNUDTracking", \
-		 CFG_DP_DISABLE_NUD_TRACKING, \
-		 CFG_DP_ROAM_AFTER_NUD_FAIL, \
-		 CFG_DP_ROAM_AFTER_NUD_FAIL, \
+		 0, \
+		 3, \
+		 2, \
 		 CFG_VALUE_OR_DEFAULT, "Driver NUD tracking behaviour")
 
 #define CFG_DP_ENABLE_NUD_TRACKING_ALL \
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index cdfb7d8..069356d 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -204,9 +204,7 @@
 	bool enable_dp_trace;
 	uint8_t dp_trace_config[DP_TRACE_CONFIG_STRING_LENGTH];
 #endif
-#ifdef WLAN_NUD_TRACKING
 	uint8_t enable_nud_tracking;
-#endif
 	uint32_t operating_chan_freq;
 	uint8_t num_vdevs;
 	uint8_t enable_concurrent_sta[CFG_CONCURRENT_IFACE_MAX_LEN];
diff --git a/core/hdd/inc/wlan_hdd_hang_event.h b/core/hdd/inc/wlan_hdd_hang_event.h
new file mode 100644
index 0000000..3376b2c
--- /dev/null
+++ b/core/hdd/inc/wlan_hdd_hang_event.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 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 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.
+ */
+#ifndef WLAN_HDD_HANG_EVENT_H
+#define WLAN_HDD_HANG_EVENT_H
+#include <qdf_hang_event_notifier.h>
+#include <wlan_hdd_main.h>
+
+#ifdef WLAN_HANG_EVENT
+/**
+ * wlan_hdd_hang_event_notifier_register() - HDD hang event notifier register
+ * @hdd_ctx: HDD context
+ *
+ * This function registers hdd layer notifier for the hang event notifier chain.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_hdd_hang_event_notifier_register(struct hdd_context *hdd_ctx);
+/**
+ * wlan_hdd_hang_event_notifier_unregister() - HDD hang event notifier
+ * unregister
+ * @hdd_ctx: HDD context
+ *
+ * This function unregisters hdd layer notifier for the hang event notifier
+ * chain.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_hdd_hang_event_notifier_unregister(void);
+#else
+static inline
+QDF_STATUS wlan_hdd_hang_event_notifier_register(struct hdd_context *hdd_ctx)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline
+QDF_STATUS wlan_hdd_hang_event_notifier_unregister(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+#endif
diff --git a/core/hdd/src/wlan_hdd_bcn_recv.c b/core/hdd/src/wlan_hdd_bcn_recv.c
index 2a01791..c426a38 100644
--- a/core/hdd/src/wlan_hdd_bcn_recv.c
+++ b/core/hdd/src/wlan_hdd_bcn_recv.c
@@ -120,8 +120,9 @@
  * Send beacon info to userspace for connected AP through a vendor event:
  * QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING.
  */
-static void hdd_send_bcn_recv_info(hdd_handle_t hdd_handle,
-				   struct wlan_beacon_report *beacon_report)
+static QDF_STATUS hdd_send_bcn_recv_info(hdd_handle_t hdd_handle,
+					 struct wlan_beacon_report
+					 *beacon_report)
 {
 	struct sk_buff *vendor_event;
 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
@@ -130,13 +131,13 @@
 	struct hdd_adapter *adapter;
 
 	if (wlan_hdd_validate_context(hdd_ctx))
-		return;
+		return QDF_STATUS_E_FAILURE;
 
 	data_len = get_beacon_report_data_len(beacon_report);
 
 	adapter = hdd_get_adapter_by_vdev(hdd_ctx, beacon_report->vdev_id);
 	if (hdd_validate_adapter(adapter))
-		return;
+		return QDF_STATUS_E_FAILURE;
 
 	vendor_event =
 		cfg80211_vendor_event_alloc(
@@ -146,7 +147,7 @@
 			flags);
 	if (!vendor_event) {
 		hdd_err("cfg80211_vendor_event_alloc failed");
-		return;
+		return QDF_STATUS_E_FAILURE;
 	}
 
 	if (nla_put_u32(vendor_event,
@@ -169,10 +170,11 @@
 				      beacon_report->boot_time)) {
 		hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
 		kfree_skb(vendor_event);
-		return;
+		return QDF_STATUS_E_FAILURE;
 	}
 
 	cfg80211_vendor_event(vendor_event, flags);
+	return QDF_STATUS_SUCCESS;
 }
 
 /**
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index 3eaee70..5fec346 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -853,7 +853,7 @@
 	 */
 	sme_config->csr_config.phyMode =
 		hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
-
+	sme_update_nud_config(mac_handle, config->enable_nud_tracking);
 	if (config->dot11Mode == eHDD_DOT11_MODE_abg ||
 	    config->dot11Mode == eHDD_DOT11_MODE_11b ||
 	    config->dot11Mode == eHDD_DOT11_MODE_11g ||
@@ -884,7 +884,6 @@
 						&enable_dfs_scan);
 	sme_config->csr_config.fEnableDFSChnlScan = enable_dfs_scan;
 	sme_config->csr_config.Csr11dinfo.Channels.numChannels = 0;
-
 	hdd_set_power_save_offload_config(hdd_ctx);
 
 #ifdef FEATURE_WLAN_ESE
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index ac1cdb9..96d4d37 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -430,6 +430,54 @@
 }
 #endif
 
+#if defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
+/*akm suits supported by sta*/
+static const u32 hdd_sta_akm_suites[] = {
+	WLAN_AKM_SUITE_8021X,
+	WLAN_AKM_SUITE_PSK,
+	WLAN_AKM_SUITE_FT_8021X,
+	WLAN_AKM_SUITE_FT_PSK,
+	WLAN_AKM_SUITE_8021X_SHA256,
+	WLAN_AKM_SUITE_PSK_SHA256,
+	WLAN_AKM_SUITE_TDLS,
+	WLAN_AKM_SUITE_SAE,
+	WLAN_AKM_SUITE_FT_OVER_SAE,
+	WLAN_AKM_SUITE_8021X_SUITE_B,
+	WLAN_AKM_SUITE_8021X_SUITE_B_192,
+	WLAN_AKM_SUITE_FILS_SHA256,
+	WLAN_AKM_SUITE_FILS_SHA384,
+	WLAN_AKM_SUITE_FT_FILS_SHA256,
+	WLAN_AKM_SUITE_FT_FILS_SHA384,
+	WLAN_AKM_SUITE_OWE,
+};
+
+/*akm suits supported by AP*/
+static const u32 hdd_ap_akm_suites[] = {
+	WLAN_AKM_SUITE_PSK,
+	WLAN_AKM_SUITE_SAE,
+	WLAN_AKM_SUITE_OWE,
+};
+
+/* This structure contain information what akm suits are
+ * supported for each mode
+ */
+static const struct wiphy_iftype_akm_suites
+	wlan_hdd_akm_suites[] = {
+	{
+		.iftypes_mask = BIT(NL80211_IFTYPE_STATION) |
+				BIT(NL80211_IFTYPE_P2P_CLIENT),
+		.akm_suites = hdd_sta_akm_suites,
+		.n_akm_suites = (sizeof(hdd_sta_akm_suites) / sizeof(u32)),
+	},
+	{
+		.iftypes_mask = BIT(NL80211_IFTYPE_AP) |
+				BIT(NL80211_IFTYPE_P2P_GO),
+		.akm_suites = hdd_ap_akm_suites,
+		.n_akm_suites = (sizeof(hdd_ap_akm_suites) / sizeof(u32)),
+	},
+};
+#endif
+
 /* This structure contain information what kind of frame are expected in
  * TX/RX direction for each kind of interface
  */
@@ -1040,6 +1088,33 @@
 	case QDF_WMI_EXCEED_MAX_PENDING_CMDS:
 		ret_val = QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS;
 		break;
+	case QDF_AP_STA_CONNECT_REQ_TIMEOUT:
+		ret_val = QCA_WLAN_HANG_AP_STA_CONNECT_REQ_TIMEOUT;
+		break;
+	case QDF_STA_AP_CONNECT_REQ_TIMEOUT:
+		ret_val = QCA_WLAN_HANG_STA_AP_CONNECT_REQ_TIMEOUT;
+		break;
+	case QDF_MAC_HW_MODE_CHANGE_TIMEOUT:
+		ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CHANGE_TIMEOUT;
+		break;
+	case QDF_MAC_HW_MODE_CONFIG_TIMEOUT:
+		ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CONFIG_TIMEOUT;
+		break;
+	case QDF_VDEV_START_RESPONSE_TIMED_OUT:
+		ret_val = QCA_WLAN_HANG_VDEV_START_RESPONSE_TIMED_OUT;
+		break;
+	case QDF_VDEV_RESTART_RESPONSE_TIMED_OUT:
+		ret_val = QCA_WLAN_HANG_VDEV_RESTART_RESPONSE_TIMED_OUT;
+		break;
+	case QDF_VDEV_STOP_RESPONSE_TIMED_OUT:
+		ret_val = QCA_WLAN_HANG_VDEV_STOP_RESPONSE_TIMED_OUT;
+		break;
+	case QDF_VDEV_DELETE_RESPONSE_TIMED_OUT:
+		ret_val = QCA_WLAN_HANG_VDEV_DELETE_RESPONSE_TIMED_OUT;
+		break;
+	case QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT:
+		ret_val = QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
+		break;
 	case QDF_REASON_UNSPECIFIED:
 	default:
 		ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
@@ -15374,6 +15449,27 @@
 }
 #endif
 
+/**
+ * wlan_hdd_update_akm_suit_info() - Populate akm suits supported by driver
+ * @wiphy: wiphy
+ *
+ * Return: void
+ */
+#if defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
+static void
+wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
+{
+	wiphy->iftype_akm_suites = wlan_hdd_akm_suites;
+	wiphy->num_iftype_akm_suites = QDF_ARRAY_SIZE(wlan_hdd_akm_suites) /
+				       sizeof(struct wiphy_iftype_akm_suites);
+}
+#else
+static void
+wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
+{
+}
+#endif
+
 /*
  * FUNCTION: wlan_hdd_cfg80211_init
  * This function is called by hdd_wlan_startup()
@@ -15391,7 +15487,7 @@
 	set_wiphy_dev(wiphy, dev);
 
 	wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
-
+	wlan_hdd_update_akm_suit_info(wiphy);
 	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
 			| WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
 			| WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
@@ -21326,9 +21422,9 @@
  * wlan_hdd_del_station() - delete station wrapper
  * @adapter: pointer to the hdd adapter
  *
- * Return: None
+ * Return: Errno
  */
-void wlan_hdd_del_station(struct hdd_adapter *adapter)
+int wlan_hdd_del_station(struct hdd_adapter *adapter)
 {
 	struct station_del_parameters del_sta;
 
@@ -21336,13 +21432,14 @@
 	del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
 	del_sta.reason_code = eCsrForcedDeauthSta;
 
-	wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
-				      &del_sta);
+	return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
+					     adapter->dev, &del_sta);
 }
 #else
-void wlan_hdd_del_station(struct hdd_adapter *adapter)
+int wlan_hdd_del_station(struct hdd_adapter *adapter)
 {
-	wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
+	return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
+					     adapter->dev, NULL);
 }
 #endif
 
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index 1cc0490..b23bbe4 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -333,7 +333,7 @@
  * Return: true or false based on findings
  */
 bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length);
-void wlan_hdd_del_station(struct hdd_adapter *adapter);
+int wlan_hdd_del_station(struct hdd_adapter *adapter);
 
 #if defined(USE_CFG80211_DEL_STA_V2)
 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
diff --git a/core/hdd/src/wlan_hdd_data_stall_detection.c b/core/hdd/src/wlan_hdd_data_stall_detection.c
index 195468a..6458ed4 100644
--- a/core/hdd/src/wlan_hdd_data_stall_detection.c
+++ b/core/hdd/src/wlan_hdd_data_stall_detection.c
@@ -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
@@ -67,10 +67,12 @@
  *
  * Return: void
  */
-static void hdd_data_stall_process_event(
+static QDF_STATUS hdd_data_stall_process_event(
 			struct data_stall_event_info *data_stall_info)
 {
 	hdd_data_stall_send_event(data_stall_info->data_stall_type);
+
+	return QDF_STATUS_SUCCESS;
 }
 
 /**
diff --git a/core/hdd/src/wlan_hdd_hang_event.c b/core/hdd/src/wlan_hdd_hang_event.c
new file mode 100644
index 0000000..2f0ab34
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_hang_event.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 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 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.
+ */
+#include <qdf_hang_event_notifier.h>
+#include <qdf_notifier.h>
+#include <wlan_hdd_hang_event.h>
+#include <wlan_objmgr_vdev_obj.h>
+#include "wlan_hdd_object_manager.h"
+#include <qdf_types.h>
+
+struct hdd_hang_event_fixed_param  {
+	uint32_t tlv_header;
+	uint8_t vdev_id;
+	uint8_t vdev_opmode;
+	uint8_t vdev_state;
+	uint8_t vdev_substate;
+} qdf_packed;
+
+struct hdd_scan_fixed_param {
+	uint32_t tlv_header;
+	uint8_t last_scan_reject_vdev_id;
+	enum scan_reject_states last_scan_reject_reason;
+	unsigned long last_scan_reject_timestamp;
+	uint8_t scan_reject_cnt;
+} qdf_packed;
+
+static int wlan_hdd_recovery_notifier_call(struct notifier_block *block,
+					   unsigned long state,
+					   void *data)
+{
+	qdf_notif_block *notif_block = qdf_container_of(block, qdf_notif_block,
+							notif_block);
+	struct hdd_context *hdd_ctx;
+	struct qdf_notifer_data *hdd_hang_data = data;
+	uint8_t *hdd_buf_ptr;
+	struct hdd_adapter *adapter;
+	uint32_t total_len;
+	struct wlan_objmgr_vdev *vdev;
+	struct hdd_hang_event_fixed_param *cmd;
+	struct hdd_scan_fixed_param *cmd_scan;
+
+	if (!data)
+		return NOTIFY_STOP_MASK;
+
+	hdd_ctx = notif_block->priv_data;
+	if (!hdd_ctx)
+		return NOTIFY_STOP_MASK;
+
+	if (hdd_hang_data->offset >= QDF_WLAN_MAX_HOST_OFFSET)
+		return NOTIFY_STOP_MASK;
+
+	if (state == QDF_SCAN_ATTEMPT_FAILURES) {
+		total_len = sizeof(*cmd_scan);
+		hdd_buf_ptr = hdd_hang_data->hang_data + hdd_hang_data->offset;
+		cmd_scan = (struct hdd_scan_fixed_param *)hdd_buf_ptr;
+		QDF_HANG_EVT_SET_HDR(&cmd_scan->tlv_header,
+				     HANG_EVT_TAG_OS_IF_SCAN,
+		QDF_HANG_GET_STRUCT_TLVLEN(struct hdd_scan_fixed_param));
+		cmd_scan->last_scan_reject_vdev_id =
+					hdd_ctx->last_scan_reject_vdev_id;
+		cmd_scan->last_scan_reject_reason =
+					hdd_ctx->last_scan_reject_reason;
+		cmd_scan->scan_reject_cnt =
+					hdd_ctx->scan_reject_cnt;
+		hdd_hang_data->offset += total_len;
+	}
+
+	hdd_for_each_adapter_dev_held(hdd_ctx, adapter) {
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev) {
+			dev_put(adapter->dev);
+			continue;
+		}
+		total_len = sizeof(*cmd);
+		hdd_buf_ptr = hdd_hang_data->hang_data + hdd_hang_data->offset;
+		cmd = (struct hdd_hang_event_fixed_param *)hdd_buf_ptr;
+		QDF_HANG_EVT_SET_HDR(&cmd->tlv_header,
+				     HANG_EVT_TAG_OS_IF,
+		QDF_HANG_GET_STRUCT_TLVLEN(struct hdd_hang_event_fixed_param));
+		cmd->vdev_id = wlan_vdev_get_id(vdev);
+		cmd->vdev_opmode = wlan_vdev_mlme_get_opmode(vdev);
+		cmd->vdev_state = wlan_vdev_mlme_get_state(vdev);
+		cmd->vdev_substate = wlan_vdev_mlme_get_substate(vdev);
+		hdd_hang_data->offset += total_len;
+		hdd_objmgr_put_vdev(vdev);
+		dev_put(adapter->dev);
+	}
+
+	return NOTIFY_OK;
+}
+
+static qdf_notif_block hdd_recovery_notifier = {
+	.notif_block.notifier_call = wlan_hdd_recovery_notifier_call,
+};
+
+QDF_STATUS wlan_hdd_hang_event_notifier_register(struct hdd_context *hdd_ctx)
+{
+	hdd_recovery_notifier.priv_data = hdd_ctx;
+	return qdf_hang_event_register_notifier(&hdd_recovery_notifier);
+}
+
+QDF_STATUS wlan_hdd_hang_event_notifier_unregister(void)
+{
+	return qdf_hang_event_unregister_notifier(&hdd_recovery_notifier);
+}
diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c
index 15e4dd3..1984324 100644
--- a/core/hdd/src/wlan_hdd_hostapd.c
+++ b/core/hdd/src/wlan_hdd_hostapd.c
@@ -1498,7 +1498,6 @@
 	 * should always be true.
 	 */
 	is_dot11_mode_abgn = true;
-	stainfo->support_mode |= is_dot11_mode_abgn << HDD_80211_MODE_ABGN;
 
 	if (event->vht_caps.present) {
 		stainfo->vht_present = true;
@@ -1514,6 +1513,11 @@
 	stainfo->support_mode |=
 			(event->he_caps_present << HDD_80211_MODE_AX);
 
+	if (event->he_caps_present && !(event->vht_caps.present ||
+					event->ht_caps.present))
+		is_dot11_mode_abgn = false;
+
+	stainfo->support_mode |= is_dot11_mode_abgn << HDD_80211_MODE_ABGN;
 	/* Initialize DHCP info */
 	stainfo->dhcp_phase = DHCP_PHASE_ACK;
 	stainfo->dhcp_nego_status = DHCP_NEGO_STOP;
@@ -5075,17 +5079,7 @@
 	 */
 	hdd_abort_ongoing_sta_connection(hdd_ctx);
 
-	/*
-	 * Reject start bss if reassoc in progress on any adapter.
-	 * sme_is_any_session_in_middle_of_roaming is for LFR2 and
-	 * hdd_is_roaming_in_progress is for LFR3
-	 */
 	mac_handle = hdd_ctx->mac_handle;
-	if (sme_is_any_session_in_middle_of_roaming(mac_handle) ||
-	    hdd_is_roaming_in_progress(hdd_ctx)) {
-		hdd_info("Reassociation in progress");
-		return -EINVAL;
-	}
 
 	/* Disable Roaming on all adapters before starting bss */
 	wlan_hdd_disable_roaming(adapter, RSO_START_BSS);
diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c
index 45f05b2..79fdfce 100644
--- a/core/hdd/src/wlan_hdd_ioctl.c
+++ b/core/hdd/src/wlan_hdd_ioctl.c
@@ -4025,6 +4025,10 @@
 	 */
 	if (!roam_ch->command_resp) {
 		len = roam_ch->num_channels * sizeof(roam_ch->chan_list[0]);
+		if (!len) {
+			hdd_err("Invalid len");
+			return;
+		}
 		event = (uint8_t *)qdf_mem_malloc(len);
 		if (!event) {
 			hdd_err("Failed to alloc event response buf vdev_id: %d",
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 6ddde68..267a837 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -179,6 +179,7 @@
 #include "wlan_pkt_capture_ucfg_api.h"
 #include <wlan_hdd_sar_limits.h>
 #include "cfg_nan_api.h"
+#include <wlan_hdd_hang_event.h>
 
 #ifdef MODULE
 #define WLAN_MODULE_NAME  module_name(THIS_MODULE)
@@ -3432,6 +3433,11 @@
 {
 	int ret;
 
+	if (hdd_ctx->config->runtime_pm != hdd_runtime_pm_dynamic) {
+		hdd_debug("Dynamic Runtime PM disabled");
+		return;
+	}
+
 	ret = pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY,
 				     &hdd_ctx->pm_qos_notifier);
 	if (ret)
@@ -3445,6 +3451,8 @@
 	}
 
 	qdf_spin_unlock_irqrestore(&hdd_ctx->pm_qos_lock);
+
+	qdf_spinlock_destroy(&hdd_ctx->pm_qos_lock);
 }
 #else
 static int hdd_wlan_register_pm_qos_notifier(struct hdd_context *hdd_ctx)
@@ -6291,8 +6299,10 @@
 	case QDF_SAP_MODE:
 		wlan_hdd_scan_abort(adapter);
 		/* Diassociate with all the peers before stop ap post */
-		if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))
-			wlan_hdd_del_station(adapter);
+		if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
+			if (wlan_hdd_del_station(adapter))
+				hdd_sap_indicate_disconnect_for_sta(adapter);
+		}
 		sap_config = &adapter->session.ap.sap_config;
 		wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
 
@@ -12346,6 +12356,7 @@
 
 	hdd_hastings_bt_war_initialize(hdd_ctx);
 
+	wlan_hdd_hang_event_notifier_register(hdd_ctx);
 	return 0;
 
 cds_disable:
@@ -12370,6 +12381,7 @@
 
 	hdd_enter();
 
+	wlan_hdd_hang_event_notifier_unregister();
 	/* De-init features */
 	hdd_features_deinit(hdd_ctx);
 
diff --git a/core/hdd/src/wlan_hdd_nud_tracking.c b/core/hdd/src/wlan_hdd_nud_tracking.c
index 3876202..62f46a8 100644
--- a/core/hdd/src/wlan_hdd_nud_tracking.c
+++ b/core/hdd/src/wlan_hdd_nud_tracking.c
@@ -290,7 +290,8 @@
 static bool
 hdd_is_roam_after_nud_enabled(struct hdd_config *config)
 {
-	if (config->enable_nud_tracking == CFG_DP_ROAM_AFTER_NUD_FAIL)
+	if (config->enable_nud_tracking == ROAM_AFTER_NUD_FAIL ||
+	    config->enable_nud_tracking == DISCONNECT_AFTER_ROAM_FAIL)
 		return true;
 
 	return false;
diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c
index 74fa521..586a63d 100644
--- a/core/hdd/src/wlan_hdd_p2p.c
+++ b/core/hdd/src/wlan_hdd_p2p.c
@@ -978,20 +978,17 @@
  * @flag: flags set by driver(SME/PE) from enum rxmgmt_flags
  *
  * Convert driver internal RXMGMT flag value to nl80211 defined RXMGMT flag
- * Return: 0 on success, -EINVAL on invalid value
+ * Return: void
  */
-static int
+static void
 wlan_hdd_cfg80211_convert_rxmgmt_flags(enum rxmgmt_flags flag,
 				       enum nl80211_rxmgmt_flags *nl80211_flag)
 {
-	int ret = -EINVAL;
 
 	if (flag & RXMGMT_FLAG_EXTERNAL_AUTH) {
 		wlan_hdd_set_rxmgmt_external_auth_flag(nl80211_flag);
-		ret = 0;
 	}
 
-	return ret;
 }
 
 static void
@@ -1088,9 +1085,7 @@
 	hdd_debug("Indicate Frame over NL80211 sessionid : %d, idx :%d",
 		   adapter->vdev_id, adapter->dev->ifindex);
 
-	if (wlan_hdd_cfg80211_convert_rxmgmt_flags(rx_flags, &nl80211_flag))
-		hdd_debug("Failed to convert RXMGMT flags :0x%x to nl80211 format",
-			  rx_flags);
+	wlan_hdd_cfg80211_convert_rxmgmt_flags(rx_flags, &nl80211_flag);
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
 	cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr,
diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c
index 30d9c0d..49534ad 100644
--- a/core/hdd/src/wlan_hdd_power.c
+++ b/core/hdd/src/wlan_hdd_power.c
@@ -974,7 +974,7 @@
 		hdd_ctx->runtime_pm_prevented = true;
 	} else if (hdd_ctx->runtime_pm_prevented &&
 		   curr_val == PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE) {
-		hif_pm_runtime_put_noidle(hif_ctx);
+		hif_pm_runtime_put(hif_ctx);
 		hdd_ctx->runtime_pm_prevented = false;
 	}
 
diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h
index 7fc43cd..4b241c4 100644
--- a/core/mac/inc/ani_global.h
+++ b/core/mac/inc/ani_global.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -762,6 +762,7 @@
 	struct wlan_mlme_chain_cfg fw_chain_cfg;
 	struct wlan_mlme_cfg *mlme_cfg;
 	tAniSirLim lim;
+	uint8_t nud_fail_behaviour;
 	struct sch_context sch;
 	tAniSirSys sys;
 
diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h
index e2ba275..5209f98 100644
--- a/core/mac/inc/qwlan_version.h
+++ b/core/mac/inc/qwlan_version.h
@@ -32,9 +32,9 @@
 #define QWLAN_VERSION_MAJOR            5
 #define QWLAN_VERSION_MINOR            2
 #define QWLAN_VERSION_PATCH            022
-#define QWLAN_VERSION_EXTRA            "Z"
-#define QWLAN_VERSION_BUILD            0
+#define QWLAN_VERSION_EXTRA            "C"
+#define QWLAN_VERSION_BUILD            1
 
-#define QWLAN_VERSIONSTR               "5.2.022.0Z"
+#define QWLAN_VERSIONSTR               "5.2.022.1C"
 
 #endif /* QWLAN_VERSION_H */
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 8b815cb..b7e6a42 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -2229,6 +2229,7 @@
 	eSirDFSRoamScanMode allowDFSChannelRoam;
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	uint8_t roam_offload_enabled;
+	bool enable_self_bss_roam;
 	uint8_t PSK_PMK[SIR_ROAM_SCAN_PSK_SIZE];
 	uint32_t pmk_len;
 	uint8_t Prefer5GHz;
@@ -4452,6 +4453,11 @@
 	uint8_t   vdev_id;
 };
 
+#define IGNORE_NUD_FAIL                      0
+#define DISCONNECT_AFTER_NUD_FAIL            1
+#define ROAM_AFTER_NUD_FAIL                  2
+#define DISCONNECT_AFTER_ROAM_FAIL           3
+
 /**
  * struct sir_sme_ext_change_chan_ind.
  * @session_id: session id
diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h
index 37bbf3e..72b594a 100644
--- a/core/mac/src/include/sir_params.h
+++ b/core/mac/src/include/sir_params.h
@@ -654,6 +654,8 @@
 
 #define SIR_HAL_ROAM_SCAN_CH_REQ           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 414)
 
+#define SIR_HAL_REQ_SEND_DELBA_REQ_IND     (SIR_HAL_ITC_MSG_TYPES_BEGIN + 415)
+
 #define SIR_HAL_MSG_TYPES_END               (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
 /* LIM message types */
diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h
index 11a971e..6a71333 100644
--- a/core/mac/src/pe/include/lim_global.h
+++ b/core/mac/src/pe/include/lim_global.h
@@ -491,4 +491,17 @@
 	tLimDot11hChanSwStates dot11hChanSwState;
 } tLimSpecMgmtInfo, *tpLimSpecMgmtInfo;
 
+/**
+ * struct lim_delba_req_info - Delba request struct
+ * @vdev_id: vdev id
+ * @peer_macaddr: peer mac address
+ * @tid: tid
+ * @reason_code: reason code
+ */
+struct lim_delba_req_info {
+	uint8_t vdev_id;
+	tSirMacAddr peer_macaddr;
+	uint8_t tid;
+	uint8_t reason_code;
+};
 #endif
diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c
index 5639d8b..59147b4 100644
--- a/core/mac/src/pe/lim/lim_api.c
+++ b/core/mac/src/pe/lim/lim_api.c
@@ -75,6 +75,17 @@
 #include "cfg_ucfg_api.h"
 #include "wlan_mlme_public_struct.h"
 #include "wlan_scan_utils_api.h"
+#include <qdf_hang_event_notifier.h>
+#include <qdf_notifier.h>
+
+struct pe_hang_event_fixed_param {
+	uint32_t tlv_header;
+	uint8_t vdev_id;
+	uint8_t limmlmstate;
+	uint8_t limprevmlmstate;
+	uint8_t limsmestate;
+	uint8_t limprevsmestate;
+} qdf_packed;
 
 static void __lim_init_bss_vars(struct mac_context *mac)
 {
@@ -726,6 +737,51 @@
 	return status;
 }
 
+static int pe_hang_event_notifier_call(struct notifier_block *block,
+				       unsigned long state,
+				       void *data)
+{
+	qdf_notif_block *notif_block = qdf_container_of(block, qdf_notif_block,
+							notif_block);
+	struct mac_context *mac;
+	struct pe_session *session;
+	struct qdf_notifer_data *pe_hang_data = data;
+	uint8_t *pe_data;
+	uint8_t i;
+	struct pe_hang_event_fixed_param *cmd;
+
+	if (!data)
+		return NOTIFY_STOP_MASK;
+
+	mac = notif_block->priv_data;
+	if (!mac)
+		return NOTIFY_STOP_MASK;
+
+	if (pe_hang_data->offset >= QDF_WLAN_MAX_HOST_OFFSET)
+		return NOTIFY_STOP_MASK;
+
+	for (i = 0; i < mac->lim.maxBssId; i++) {
+		session = &mac->lim.gpSession[i];
+		if (!session->valid)
+			continue;
+
+		pe_data = (pe_hang_data->hang_data + pe_hang_data->offset);
+		cmd = (struct pe_hang_event_fixed_param *)pe_data;
+		cmd->vdev_id = session->vdev_id;
+		cmd->limmlmstate = session->limMlmState;
+		cmd->limprevmlmstate = session->limPrevMlmState;
+		cmd->limsmestate = session->limSmeState;
+		cmd->limprevsmestate = session->limPrevSmeState;
+		pe_hang_data->offset += sizeof(*cmd);
+	}
+
+	return NOTIFY_OK;
+}
+
+static qdf_notif_block pe_hang_event_notifier = {
+	.notif_block.notifier_call = pe_hang_event_notifier_call,
+};
+
 /** -------------------------------------------------------------
    \fn pe_open
    \brief will be called in Open sequence from mac_open
@@ -794,6 +850,9 @@
 		pe_err("%s: Shutdown notifier register failed", __func__);
 	}
 
+	pe_hang_event_notifier.priv_data = mac;
+	qdf_hang_event_register_notifier(&pe_hang_event_notifier);
+
 	return status; /* status here will be QDF_STATUS_SUCCESS */
 
 pe_open_lock_fail:
@@ -822,6 +881,7 @@
 	if (ANI_DRIVER_TYPE(mac) == QDF_DRIVER_TYPE_MFG)
 		return QDF_STATUS_SUCCESS;
 
+	qdf_hang_event_unregister_notifier(&pe_hang_event_notifier);
 	lim_cleanup(mac);
 	lim_unregister_sap_bcn_callback(mac);
 
diff --git a/core/mac/src/pe/lim/lim_link_monitoring_algo.c b/core/mac/src/pe/lim/lim_link_monitoring_algo.c
index 11565c3..1e4dedd 100644
--- a/core/mac/src/pe/lim/lim_link_monitoring_algo.c
+++ b/core/mac/src/pe/lim/lim_link_monitoring_algo.c
@@ -584,3 +584,27 @@
 	qdf_mem_free(msg);
 	lim_msg->bodyptr = NULL;
 }
+
+void lim_req_send_delba_ind_process(struct mac_context *mac_ctx,
+				    struct scheduler_msg *lim_msg)
+{
+	struct lim_delba_req_info *req =
+			(struct lim_delba_req_info *)lim_msg->bodyptr;
+	QDF_STATUS status;
+	void *dp_soc = cds_get_context(QDF_MODULE_ID_SOC);
+
+	if (!req) {
+		pe_err("Invalid body pointer in message");
+		return;
+	}
+
+	status = lim_send_delba_action_frame(mac_ctx, req->vdev_id,
+					     req->peer_macaddr,
+					     req->tid, req->reason_code);
+	if (status != QDF_STATUS_SUCCESS)
+		cdp_delba_tx_completion(dp_soc, req->peer_macaddr,
+					req->vdev_id, req->tid,
+					WMI_MGMT_TX_COMP_TYPE_DISCARD);
+	qdf_mem_free(req);
+	lim_msg->bodyptr = NULL;
+}
diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
index 79d72ae..27f1bbc 100644
--- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
+++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
@@ -2623,6 +2623,39 @@
 	}
 }
 
+/**
+ *lim_convert_channel_width_enum() - map between two channel width enums
+ *@ch_width: channel width of enum type phy_ch_width
+ *
+ *Return: channel width of enum type tSirMacHTChannelWidth
+ */
+static tSirMacHTChannelWidth
+lim_convert_channel_width_enum(enum phy_ch_width ch_width)
+{
+	switch (ch_width) {
+	case CH_WIDTH_20MHZ:
+		return eHT_CHANNEL_WIDTH_20MHZ;
+	case CH_WIDTH_40MHZ:
+		return eHT_CHANNEL_WIDTH_40MHZ;
+	case CH_WIDTH_80MHZ:
+		return eHT_CHANNEL_WIDTH_80MHZ;
+	case CH_WIDTH_160MHZ:
+		return eHT_CHANNEL_WIDTH_160MHZ;
+	case CH_WIDTH_80P80MHZ:
+		return eHT_CHANNEL_WIDTH_80P80MHZ;
+	case CH_WIDTH_MAX:
+		return eHT_MAX_CHANNEL_WIDTH;
+	case CH_WIDTH_5MHZ:
+		break;
+	case CH_WIDTH_10MHZ:
+		break;
+	case CH_WIDTH_INVALID:
+		break;
+	}
+	pe_debug("invalid enum: %d", ch_width);
+	return eHT_CHANNEL_WIDTH_20MHZ;
+}
+
 bool lim_fill_lim_assoc_ind_params(
 		tpLimMlmAssocInd assoc_ind,
 		struct mac_context *mac_ctx,
@@ -2837,7 +2870,10 @@
 	assoc_ind->he_caps_present = assoc_req->he_cap.present;
 	assoc_ind->is_sae_authenticated =
 				assoc_req->is_sae_authenticated;
-
+	/* updates HE bandwidth in assoc indication */
+	if (wlan_reg_is_6ghz_chan_freq(session_entry->curr_op_freq))
+		assoc_ind->ch_width =
+			lim_convert_channel_width_enum(sta_ds->ch_width);
 	return true;
 }
 
diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c
index ba57f77..fc8e3b4 100644
--- a/core/mac/src/pe/lim/lim_process_message_queue.c
+++ b/core/mac/src/pe/lim/lim_process_message_queue.c
@@ -1855,6 +1855,9 @@
 	case SIR_LIM_RX_INVALID_PEER:
 		lim_rx_invalid_peer_process(mac_ctx, msg);
 		break;
+	case SIR_HAL_REQ_SEND_DELBA_REQ_IND:
+		lim_req_send_delba_ind_process(mac_ctx, msg);
+		break;
 	case SIR_LIM_JOIN_FAIL_TIMEOUT:
 	case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT:
 	case SIR_LIM_AUTH_FAIL_TIMEOUT:
diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c
index b855fbf..0051df3 100644
--- a/core/mac/src/pe/lim/lim_prop_exts_utils.c
+++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c
@@ -494,6 +494,7 @@
 			else
 				session->gLimOperatingMode.chanWidth =
 					CH_WIDTH_160MHZ;
+			session->gLimOperatingMode.rxNSS = session->nss - 1;
 		} else {
 			pe_err("AP does not support op_mode rx");
 		}
diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c
index 392a7ba..2434c80 100644
--- a/core/mac/src/pe/lim/lim_send_management_frames.c
+++ b/core/mac/src/pe/lim/lim_send_management_frames.c
@@ -2057,9 +2057,8 @@
 		pe_debug("Populate VHT IEs in Assoc Request");
 		populate_dot11f_vht_caps(mac_ctx, pe_session, &frm->VHTCaps);
 		vht_enabled = true;
-		if (pe_session->enableHtSmps &&
-				!pe_session->supported_nss_1x1) {
-			pe_err("VHT OP mode IE in Assoc Req");
+		if (pe_session->gLimOperatingMode.present) {
+			pe_debug("VHT OP mode IE in Assoc Req");
 			populate_dot11f_operating_mode(mac_ctx,
 					&frm->OperatingMode, pe_session);
 		}
@@ -5115,6 +5114,165 @@
 }
 
 /**
+ * lim_delba_tx_complete_cnf() - Confirmation for Delba OTA
+ * @context: pointer to global mac
+ * @buf: netbuf of Del BA frame
+ * @tx_complete : Sent status
+ * @params; tx completion params
+ *
+ * Return: This returns QDF_STATUS
+ */
+static QDF_STATUS lim_delba_tx_complete_cnf(void *context,
+					    qdf_nbuf_t buf,
+					    uint32_t tx_complete,
+					    void *params)
+{
+	struct mac_context *mac_ctx = (struct mac_context *)context;
+	tSirMacMgmtHdr *mac_hdr;
+	struct sDot11fdelba_req frm;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	uint32_t frame_len;
+	QDF_STATUS status;
+	uint8_t *data;
+	struct wmi_mgmt_params *mgmt_params = (struct wmi_mgmt_params *)params;
+
+	if (!mgmt_params || !mac_ctx || !buf || !soc) {
+		pe_err("delba tx cnf invalid parameters");
+		goto error;
+	}
+	data = qdf_nbuf_data(buf);
+	if (!data) {
+		pe_err("Delba frame is NULL");
+		goto error;
+	}
+
+	mac_hdr = (tSirMacMgmtHdr *)data;
+	qdf_mem_zero((void *)&frm, sizeof(struct sDot11fdelba_req));
+	frame_len = sizeof(frm);
+	status = dot11f_unpack_delba_req(mac_ctx, (uint8_t *)data +
+					 sizeof(*mac_hdr), frame_len,
+					 &frm, false);
+	if (DOT11F_FAILED(status)) {
+		pe_err("Failed to unpack and parse delba (0x%08x, %d bytes)",
+		       status, frame_len);
+		goto error;
+	}
+	pe_debug("delba ota done vdev %d %pM tid %d desc_id %d status %d",
+		 mgmt_params->vdev_id, mac_hdr->da, frm.delba_param_set.tid,
+		 mgmt_params->desc_id, tx_complete);
+	cdp_delba_tx_completion(soc, mac_hdr->da, mgmt_params->vdev_id,
+				frm.delba_param_set.tid, tx_complete);
+
+error:
+	if (buf)
+		qdf_nbuf_free(buf);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS lim_send_delba_action_frame(struct mac_context *mac_ctx,
+				       uint8_t vdev_id, uint8_t *peer_macaddr,
+				       uint8_t tid, uint8_t reason_code)
+{
+	struct pe_session *session;
+	struct sDot11fdelba_req frm;
+	QDF_STATUS qdf_status;
+	tpSirMacMgmtHdr mgmt_hdr;
+	uint32_t num_bytes, payload_size = 0;
+	uint32_t status;
+	void *pkt_ptr = NULL;
+	uint8_t *frame_ptr;
+	uint8_t tx_flag = 0;
+
+	session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
+	if (!session) {
+		pe_debug("delba invalid vdev id %d ", vdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+	pe_debug("send delba vdev %d %pM tid %d reason %d", vdev_id,
+		 peer_macaddr, tid, reason_code);
+	qdf_mem_zero((uint8_t *)&frm, sizeof(frm));
+	frm.Category.category = ACTION_CATEGORY_BACK;
+	frm.Action.action = DELBA;
+	frm.delba_param_set.initiator = 0;
+	frm.delba_param_set.tid = tid;
+	frm.Reason.code = reason_code;
+
+	status = dot11f_get_packed_delba_req_size(mac_ctx, &frm, &payload_size);
+	if (DOT11F_FAILED(status)) {
+		pe_err("Failed to calculate the packed size for a DELBA(0x%08x).",
+		       status);
+		/* We'll fall back on the worst case scenario: */
+		payload_size = sizeof(struct sDot11fdelba_req);
+	} else if (DOT11F_WARNED(status)) {
+		pe_warn("Warnings in calculating the packed size for a DELBA (0x%08x).",
+			status);
+	}
+	num_bytes = payload_size + sizeof(*mgmt_hdr);
+	qdf_status = cds_packet_alloc(num_bytes, (void **)&frame_ptr,
+				      (void **)&pkt_ptr);
+	if (!QDF_IS_STATUS_SUCCESS(qdf_status) || !pkt_ptr) {
+		pe_err("Failed to allocate %d bytes for a DELBA",
+		       num_bytes);
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_mem_zero(frame_ptr, num_bytes);
+
+	lim_populate_mac_header(mac_ctx, frame_ptr, SIR_MAC_MGMT_FRAME,
+				SIR_MAC_MGMT_ACTION, peer_macaddr,
+				session->self_mac_addr);
+
+	/* Update A3 with the BSSID */
+	mgmt_hdr = (tpSirMacMgmtHdr)frame_ptr;
+	sir_copy_mac_addr(mgmt_hdr->bssId, session->bssId);
+
+	/* DEL is a robust mgmt action frame,
+	 * set the "protect" (aka WEP) bit in the FC
+	 */
+	lim_set_protected_bit(mac_ctx, session, peer_macaddr, mgmt_hdr);
+
+	status = dot11f_pack_delba_req(mac_ctx, &frm,
+				       frame_ptr + sizeof(tSirMacMgmtHdr),
+				       payload_size, &payload_size);
+	if (DOT11F_FAILED(status)) {
+		pe_err("Failed to pack a DELBA (0x%08x)",
+		       status);
+		qdf_status = QDF_STATUS_E_FAILURE;
+		goto error_delba;
+	} else if (DOT11F_WARNED(status)) {
+		pe_warn("There were warnings while packing DELBA (0x%08x)",
+			status);
+	}
+	if (wlan_reg_is_5ghz_ch_freq(session->curr_op_freq) ||
+	    wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) ||
+	    session->opmode == QDF_P2P_CLIENT_MODE ||
+	    session->opmode == QDF_P2P_GO_MODE)
+		tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+			 session->peSessionId, mgmt_hdr->fc.subType));
+	qdf_status = wma_tx_frameWithTxComplete(mac_ctx, pkt_ptr,
+						(uint16_t)num_bytes,
+						TXRX_FRM_802_11_MGMT,
+						ANI_TXDIR_TODS, 7,
+						NULL, frame_ptr,
+						lim_delba_tx_complete_cnf,
+						tx_flag, vdev_id,
+						false, 0, RATEID_DEFAULT);
+	if (qdf_status != QDF_STATUS_SUCCESS) {
+		pe_err("delba wma_tx_frame FAILED! Status [%d]", qdf_status);
+		return qdf_status;
+	} else {
+		return QDF_STATUS_SUCCESS;
+	}
+
+error_delba:
+	if (pkt_ptr)
+		cds_packet_free((void *)pkt_ptr);
+
+	return qdf_status;
+}
+
+/**
  * lim_tx_mgmt_frame() - Transmits Auth mgmt frame
  * @mac_ctx Pointer to Global MAC structure
  * @mb_msg: Received message info
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
index 4774520..738bc0e 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -1163,6 +1163,22 @@
 					 struct pe_session *session,
 					 uint8_t addba_extn_present,
 					 uint8_t amsdu_support, uint8_t is_wep);
+
+/**
+ * lim_send_delba_action_frame() - Send delba to peer
+ * @mac_ctx: mac context
+ * @vdev_id: vdev id
+ * @peer_macaddr: Peer mac addr
+ * @tid: Tid number
+ * @reason_code: reason code
+ *
+ * Return: 0 for success, non-zero for failure
+ */
+QDF_STATUS lim_send_delba_action_frame(struct mac_context *mac_ctx,
+				       uint8_t vdev_id,
+				       uint8_t *peer_macaddr, uint8_t tid,
+				       uint8_t reason_code);
+
 /**
  * lim_process_join_failure_timeout() - This function is called to process
  * JoinFailureTimeout
diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h
index 843e032..af0aa14 100644
--- a/core/mac/src/pe/lim/lim_utils.h
+++ b/core/mac/src/pe/lim/lim_utils.h
@@ -1798,6 +1798,18 @@
 				 struct scheduler_msg *lim_msg);
 
 /**
+ * lim_req_send_delba_ind_process() - process send delba indication
+ * @mac_ctx: mac context
+ * @lim_msg: lim message
+ *
+ * This function will process the send delba indication from DP.
+ *
+ * Return: None
+ */
+void lim_req_send_delba_ind_process(struct mac_context *mac_ctx,
+				    struct scheduler_msg *lim_msg);
+
+/**
  * lim_send_beacon() - send beacon indication to firmware
  * @mac_ctx: Pointer to Global MAC structure
  * @session: session pointer
diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c
index 611df34..dc8dc3a 100644
--- a/core/mac/src/pe/sch/sch_beacon_gen.c
+++ b/core/mac/src/pe/sch/sch_beacon_gen.c
@@ -901,6 +901,14 @@
 			     sizeof(beacon2->he_op));
 	}
 
+	if (beacon2->he_6ghz_band_cap.present) {
+		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+					DOT11F_EID_HE_6GHZ_BAND_CAP);
+		qdf_mem_copy((void *)&prb_rsp->he_6ghz_band_cap,
+			     (void *)&beacon2->he_6ghz_band_cap,
+			     sizeof(beacon2->he_6ghz_band_cap));
+	}
+
 }
 
 void set_probe_rsp_ie_bitmap(uint32_t *IeBitmap, uint32_t pos)
diff --git a/core/mac/src/sys/common/src/wlan_qct_sys.c b/core/mac/src/sys/common/src/wlan_qct_sys.c
index 66499fd..91eccca 100644
--- a/core/mac/src/sys/common/src/wlan_qct_sys.c
+++ b/core/mac/src/sys/common/src/wlan_qct_sys.c
@@ -57,18 +57,19 @@
  * Return: none
  */
 #ifdef QDF_ENABLE_TRACING
-static void umac_stop_complete_cb(void *user_data)
+static QDF_STATUS umac_stop_complete_cb(void *user_data)
 {
 	qdf_event_t *stop_evt = (qdf_event_t *) user_data;
 	QDF_STATUS qdf_status = qdf_event_set(stop_evt);
 
 	QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
 
+	return QDF_STATUS_SUCCESS;
 }
 #else
-static void umac_stop_complete_cb(void *user_data)
+static QDF_STATUS umac_stop_complete_cb(void *user_data)
 {
-	return;
+	return QDF_STATUS_SUCCESS;
 }
 #endif
 
diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h
index a427da5..7b15976 100644
--- a/core/pld/inc/pld_common.h
+++ b/core/pld/inc/pld_common.h
@@ -154,6 +154,8 @@
 	union {
 		struct {
 			bool crashed;
+			void *hang_event_data;
+			u16 hang_event_data_len;
 		} fw_down;
 	};
 };
diff --git a/core/pld/src/pld_snoc.c b/core/pld/src/pld_snoc.c
index df9b160..2e7998d 100644
--- a/core/pld/src/pld_snoc.c
+++ b/core/pld/src/pld_snoc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -240,12 +240,31 @@
 	return 0;
 }
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
+static int pld_update_hang_evt_data(struct icnss_uevent_fw_down_data *evt_data,
+				    struct pld_uevent_data *data)
+{
+	if (!evt_data || !data)
+		return -EINVAL;
+
+	data->fw_down.hang_event_data = evt_data->hang_event_data;
+	data->fw_down.hang_event_data_len = evt_data->hang_event_data_len;
+	return 0;
+}
+#else
+static int pld_update_hang_evt_data(struct icnss_uevent_fw_down_data *evt_data,
+				    struct pld_uevent_data *data)
+{
+	return 0;
+}
+#endif
+
 static int pld_snoc_uevent(struct device *dev,
 			   struct icnss_uevent_data *uevent)
 {
 	struct pld_context *pld_context;
 	struct icnss_uevent_fw_down_data *uevent_data = NULL;
-	struct pld_uevent_data data;
+	struct pld_uevent_data data = {0};
 
 	pld_context = pld_get_global_context();
 	if (!pld_context)
@@ -267,6 +286,7 @@
 		uevent_data = (struct icnss_uevent_fw_down_data *)uevent->data;
 		data.uevent = PLD_FW_DOWN;
 		data.fw_down.crashed = uevent_data->crashed;
+		pld_update_hang_evt_data(uevent_data, &data);
 		break;
 	default:
 		goto out;
diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c
index 0c5154d..5be65572 100644
--- a/core/sap/src/sap_fsm.c
+++ b/core/sap/src/sap_fsm.c
@@ -2719,6 +2719,13 @@
 		qdf_status = sap_signal_hdd_event(sap_ctx, NULL,
 					eSAP_STOP_BSS_EVENT,
 					(void *)eSAP_STATUS_SUCCESS);
+	} else if (msg == eSAP_HDD_STOP_INFRA_BSS) {
+		/*
+		 * In case the SAP is already in stopping case and
+		 * we get a STOP request, return success.
+		 */
+		sap_debug("SAP already in Stopping state");
+		qdf_status = QDF_STATUS_SUCCESS;
 	} else {
 		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
 			  FL("in state %s, invalid event msg %d"),
diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h
index e63d306..921dfc5 100644
--- a/core/sme/inc/csr_api.h
+++ b/core/sme/inc/csr_api.h
@@ -901,6 +901,7 @@
 struct csr_config_params {
 	/* keep this uint32_t. This gets converted to ePhyChannelBondState */
 	uint32_t channelBondingMode24GHz;
+	uint8_t nud_fail_behaviour;
 	uint32_t channelBondingMode5GHz;
 	eCsrPhyMode phyMode;
 	uint32_t HeartbeatThresh50;
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 36e6c20..feb392f 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -412,6 +412,13 @@
 void sme_set_curr_device_mode(mac_handle_t mac_handle,
 			      enum QDF_OPMODE curr_device_mode);
 
+/**
+ * sme_update_nud_config() - update nud config
+ * @mac_handle: The handle returned by mac_open.
+ * @nud_fail_behavior: Vlaue of nud fail behaviour
+ */
+void sme_update_nud_config(mac_handle_t mac_handle, uint8_t nud_fail_behavior);
+
 QDF_STATUS sme_update_roam_params(mac_handle_t mac_handle,
 				  uint8_t session_id,
 				  struct roam_ext_params *roam_params_src,
diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h
index 46ce736..2e9bcde 100644
--- a/core/sme/inc/sme_internal.h
+++ b/core/sme/inc/sme_internal.h
@@ -253,8 +253,8 @@
  * @hdd_handle: HDD handle registered with SME
  * @beacon_report: Beacon report structure
  */
-typedef void (*beacon_report_cb)(hdd_handle_t hdd_handle,
-				 struct wlan_beacon_report *beacon_report);
+typedef QDF_STATUS (*beacon_report_cb)
+	(hdd_handle_t hdd_handle, struct wlan_beacon_report *beacon_report);
 
 /**
  * beacon_pause_cb : scan start callback fun
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 9ea328c..2ce4094 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -841,6 +841,13 @@
 	}
 }
 
+void sme_update_nud_config(mac_handle_t mac_handle, uint8_t nud_fail_behavior)
+{
+	struct mac_context *mac = MAC_CONTEXT(mac_handle);
+
+	mac->nud_fail_behaviour = nud_fail_behavior;
+}
+
 /**
  * sme_update_neighbor_report_config() - Update CSR config for 11k params
  * @mac_handle: Pointer to MAC context
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index d25234f..77d373f 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -17542,6 +17542,8 @@
 	if (!req_buf->roam_offload_enabled)
 		return;
 
+	req_buf->enable_self_bss_roam =
+			mac_ctx->mlme_cfg->lfr.enable_self_bss_roam;
 	req_buf->roam_triggers.vdev_id = session->vdev_id;
 	req_buf->roam_triggers.trigger_bitmap =
 		mlme_get_roam_trigger_bitmap(mac_ctx->psoc, session->vdev_id);
@@ -21427,9 +21429,10 @@
 				eCSR_ROAM_NAPI_OFF, eCSR_ROAM_RESULT_SUCCESS);
 		goto end;
 	case SIR_ROAMING_INVOKE_FAIL:
-		sme_debug("Roaming triggered failed source %d",
-			   vdev_roam_params->source);
-		if (vdev_roam_params->source == USERSPACE_INITIATED) {
+		sme_debug("Roaming triggered failed source %d nud behaviour %d",
+			   vdev_roam_params->source, mac_ctx->nud_fail_behaviour);
+		if (vdev_roam_params->source == USERSPACE_INITIATED ||
+		    mac_ctx->nud_fail_behaviour == DISCONNECT_AFTER_NUD_FAIL) {
 			/* Userspace roam req fail, disconnect with AP */
 			csr_roam_disconnect(mac_ctx, session_id,
 					eCSR_DISCONNECT_REASON_DEAUTH,
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h
index 50d00fc..05be4f0 100644
--- a/core/wma/inc/wma.h
+++ b/core/wma/inc/wma.h
@@ -2382,6 +2382,21 @@
 uint8_t wma_rx_invalid_peer_ind(uint8_t vdev_id, void *wh);
 
 /**
+ * wma_dp_send_delba_ind() - the callback for DP to notify WMA layer
+ * to del ba of rx
+ * @vdev_id: vdev id
+ * @peer_macaddr: peer mac address
+ * @tid: tid of rx
+ * @reason_code: reason code
+ *
+ * Return: 0 for success or non-zero on failure
+ */
+int wma_dp_send_delba_ind(uint8_t vdev_id,
+			  uint8_t *peer_macaddr,
+			  uint8_t tid,
+			  uint8_t reason_code);
+
+/**
  * is_roam_inprogress() - Is vdev in progress
  * @vdev_id: vdev of interest
  *
diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c
index 07030f8..3c06cd0 100644
--- a/core/wma/src/wma_data.c
+++ b/core/wma/src/wma_data.c
@@ -3187,6 +3187,31 @@
 	return 0;
 }
 
+int wma_dp_send_delba_ind(uint8_t vdev_id, uint8_t *peer_macaddr,
+			  uint8_t tid, uint8_t reason_code)
+{
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+	struct lim_delba_req_info *req;
+
+	if (!wma || !peer_macaddr) {
+		wma_err("wma handle or mac addr is NULL");
+		return -EINVAL;
+	}
+	req = qdf_mem_malloc(sizeof(*req));
+	if (!req)
+		return -ENOMEM;
+	req->vdev_id = vdev_id;
+	qdf_mem_copy(req->peer_macaddr, peer_macaddr, QDF_MAC_ADDR_SIZE);
+	req->tid = tid;
+	req->reason_code = reason_code;
+	WMA_LOGD("req delba_ind vdev %d %pM tid %d reason %d",
+		 vdev_id, peer_macaddr, tid, reason_code);
+	wma_send_msg_high_priority(wma, SIR_HAL_REQ_SEND_DELBA_REQ_IND,
+				   (void *)req, 0);
+
+	return 0;
+}
+
 bool wma_is_roam_in_progress(uint32_t vdev_id)
 {
 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c
index 0e8dbfe..abe0910 100644
--- a/core/wma/src/wma_dev_if.c
+++ b/core/wma/src/wma_dev_if.c
@@ -3022,11 +3022,13 @@
 	return status;
 }
 
-static void wma_trigger_recovery_assert_on_fw_timeout(uint16_t wma_msg)
+static
+void wma_trigger_recovery_assert_on_fw_timeout(uint16_t wma_msg,
+					       enum qdf_hang_reason reason)
 {
 	WMA_LOGE("%s timed out, triggering recovery",
 		 mac_trace_get_wma_msg_string(wma_msg));
-	cds_trigger_recovery(QDF_REASON_UNSPECIFIED);
+	qdf_trigger_self_recovery(NULL, reason);
 }
 
 static inline bool wma_crash_on_fw_timeout(bool crash_enabled)
@@ -3086,7 +3088,8 @@
 			 params->staMac, params->status);
 		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash))
 			wma_trigger_recovery_assert_on_fw_timeout(
-				WMA_ADD_STA_REQ);
+				WMA_ADD_STA_REQ,
+				QDF_AP_STA_CONNECT_REQ_TIMEOUT);
 		wma_send_msg_high_priority(wma, WMA_ADD_STA_RSP,
 					   (void *)params, 0);
 	} else if (tgt_req->msg_type == WMA_ADD_BSS_REQ) {
@@ -3097,7 +3100,8 @@
 
 		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash))
 			wma_trigger_recovery_assert_on_fw_timeout(
-				WMA_ADD_BSS_REQ);
+				WMA_ADD_BSS_REQ,
+				QDF_STA_AP_CONNECT_REQ_TIMEOUT);
 
 		wma_send_add_bss_resp(wma, tgt_req->vdev_id,
 				      QDF_STATUS_E_TIMEOUT);
@@ -3112,7 +3116,8 @@
 
 		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash))
 			wma_trigger_recovery_assert_on_fw_timeout(
-				WMA_DELETE_STA_REQ);
+				WMA_DELETE_STA_REQ,
+				QDF_PEER_DELETION_TIMEDOUT);
 		wma_send_msg_high_priority(wma, WMA_DELETE_STA_RSP,
 					   (void *)params, 0);
 	} else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) &&
@@ -3126,7 +3131,8 @@
 
 		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash))
 			wma_trigger_recovery_assert_on_fw_timeout(
-				WMA_DELETE_STA_REQ);
+				WMA_DELETE_STA_REQ,
+				QDF_PEER_DELETION_TIMEDOUT);
 		wma_handle_vdev_detach(wma, del_sta->self_sta_param);
 		qdf_mem_free(tgt_req->user_data);
 	} else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) &&
@@ -3140,7 +3146,8 @@
 
 		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash))
 			wma_trigger_recovery_assert_on_fw_timeout(
-				WMA_DELETE_STA_REQ);
+				WMA_DELETE_STA_REQ,
+				QDF_PEER_DELETION_TIMEDOUT);
 		wma_send_vdev_down_req(wma, params);
 	} else if ((tgt_req->msg_type == SIR_HAL_PDEV_SET_HW_MODE) &&
 			(tgt_req->type == WMA_PDEV_SET_HW_MODE_RESP)) {
@@ -3151,7 +3158,8 @@
 
 		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash))
 			wma_trigger_recovery_assert_on_fw_timeout(
-						SIR_HAL_PDEV_SET_HW_MODE);
+			  SIR_HAL_PDEV_SET_HW_MODE,
+			  QDF_MAC_HW_MODE_CHANGE_TIMEOUT);
 		if (!params) {
 			WMA_LOGE(FL("Failed to allocate memory for params"));
 			goto timer_destroy;
@@ -3169,7 +3177,8 @@
 		WMA_LOGE(FL("set dual mac config timeout"));
 		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash))
 			wma_trigger_recovery_assert_on_fw_timeout(
-						SIR_HAL_PDEV_DUAL_MAC_CFG_REQ);
+				SIR_HAL_PDEV_DUAL_MAC_CFG_REQ,
+				QDF_MAC_HW_MODE_CONFIG_TIMEOUT);
 		if (!resp) {
 			WMA_LOGE(FL("Failed to allocate memory for resp"));
 			goto timer_destroy;
@@ -5202,13 +5211,17 @@
 	}
 
 	wma_vdev_set_pause_bit(vdev_id, PAUSE_TYPE_HOST);
-	if (wma_send_vdev_stop_to_fw(wma, vdev_id)) {
-		WMA_LOGP("%s: %d Failed to send vdev stop",
-			 __func__, __LINE__);
+
+	status = wma_send_vdev_stop_to_fw(wma, vdev_id);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		struct vdev_stop_response resp_event;
+
+		wma_info("vdev %d Failed to send vdev stop", vdev_id);
+		resp_event.vdev_id = vdev_id;
+		mlme_set_connection_fail(wma->interfaces[vdev_id].vdev, false);
+		wma_handle_vdev_stop_rsp(wma, &resp_event);
 	}
 
-	WMA_LOGP("%s: %d vdev stop sent vdev %d", __func__, __LINE__,
-		 vdev_id);
 	/*
 	 * Remove peer, Vdev down and sending set link
 	 * response will be handled in vdev stop response
diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c
index 62d9295..2e412db 100644
--- a/core/wma/src/wma_scan_roam.c
+++ b/core/wma/src/wma_scan_roam.c
@@ -336,6 +336,8 @@
 				(roam_req->ConnectedNetwork.authentication,
 				 roam_req->ConnectedNetwork.encryption);
 
+	params->disable_self_roam =
+				!roam_req->enable_self_bss_roam;
 	params->roam_offload_enabled = roam_req->roam_offload_enabled;
 	params->roam_offload_params.ho_delay_for_rx =
 				roam_req->ho_delay_for_rx;