diff --git a/Makefile b/Makefile
index 2e0a5a2..92dda33 100644
--- a/Makefile
+++ b/Makefile
@@ -155,7 +155,7 @@ APPDIR= $(shell if test -d "mapp"; then echo mapp; fi)
 #############################################################################
 
 	ccflags-y += -I$(KERNELDIR)/include
-	ccflags-y += -DMLAN_RELEASE_VERSION='"437.p30"'
+	ccflags-y += -DMLAN_RELEASE_VERSION='"505.p1"'
 
 	ccflags-y += -DFPNUM='"92"'
 
@@ -272,6 +272,10 @@ ifeq ($(CONFIG_SD9097),y)
 	CONFIG_SDIO=y
 	ccflags-y += -DSD9097
 endif
+ifeq ($(CONFIG_SDIW610),y)
+	CONFIG_SDIO=y
+	ccflags-y += -DSDIW610
+endif
 ifeq ($(CONFIG_SDIW624),y)
 	CONFIG_SDIO=y
 	ccflags-y += -DSDIW624
@@ -312,6 +316,10 @@ ifeq ($(CONFIG_USB9097),y)
 	CONFIG_MUSB=y
 	ccflags-y += -DUSB9097
 endif
+ifeq ($(CONFIG_USBIW610),y)
+	CONFIG_MUSB=y
+	ccflags-y += -DUSBIW610
+endif
 ifeq ($(CONFIG_USBIW624),y)
 	CONFIG_MUSB=y
 	ccflags-y += -DUSBIW624
@@ -505,6 +513,7 @@ endif
 
 
 
+
 MOALOBJS =	mlinux/moal_main.o \
 		mlinux/moal_ioctl.o \
 		mlinux/moal_shim.o \
diff --git a/README b/README
index f523914..9aea77f 100755
--- a/README
+++ b/README
@@ -3,7 +3,7 @@
 ===============================================================================
 			U S E R  M A N U A L
 
- Copyright 2008-2023 NXP
+ Copyright 2008-2024 NXP
 
 
 1) FOR DRIVER BUILD
@@ -11,7 +11,7 @@
 	Goto source code directory wlan_src/.
 	make [clean] build
 	The driver and utility binaries can be found in ../bin_xxxx directory.
-	The driver code supports Linux kernel from 2.6.32 to 6.9.0.
+	The driver code supports Linux kernel from 2.6.32 to 6.9.10.
 
 2) FOR DRIVER INSTALL
 
@@ -46,6 +46,21 @@
 		rmmod moal
 		rmmod mlan
 
+	pref_dbc
+	This load time parameter is used to config preferred DBC mode and takes effect when dmcs is enabled
+	This parameter only used for AW693(BB)
+
+	Usage:
+		pref_dbc=[value]
+		insmod mlan.ko; insmod pcieaw693.ko fw_name=aw693w.bin dmcs=1 pref_dbc=1
+		<value = 0> : default preferred DBC mode
+		<value = 1> : Enable preferred DBC mode
+		<value = 2> : Disable preferred DBC mode
+
+	Example :
+		insmod mlan.ko; insmod pcieaw693.ko fw_name=aw693w.bin dmcs=1 pref_dbc=1 : Enable preferred DBC mode
+		insmod mlan.ko; insmod pcieaw693.ko fw_name=aw693w.bin dmcs=1 pref_dbc=2 : Disable preferred DBC mode
+
 	To load driver with MFG firmware file, use mfg_mode=1 when insmod WLAN driver and
 	specify MFG firmware name if needed.
 
@@ -53,82 +68,90 @@
 	This parameter only used for 9177(FC)
 
 	There are some other parameters for debugging purpose etc. Use modinfo to check details.
-	  drvdbg=<bit mask of driver debug message control>
-	  dev_cap_mask=<Bit mask of the device capability>
-	  This load parameter is uses to configure device features support
-	  Usage:
-	      dev_cap_mask=<value to be configured>
-	      <BIT0-BIT15> : Represents features supported
-	      <BIT16>: Indicates support for 11AX
-	      <BIT17>: Indicates support for 6G
-          Example:
-	      To disable 11AX and 6G support: dev_cap_mask=0xfffcffff
-	  mac_addr=xx:xx:xx:xx:xx:xx <override the MAC address (in hex)>
-	  auto_ds=0|1|2 <use MLAN default | enable auto deepsleep | disable auto deepsleep>
-	  ext_scan=0|1|2 <use MLAN default | Enable Extended Scan| Enable Enhanced Extended Scan>
-      net_rx=0|1 <use netif_rx_ni in rx | use netif_receive_skb in rx>
-      amsdu_deaggr=0|1 <buf copy in amsud deaggregation | avoid buf copy in amsud deaggregation (default)>
+	drvdbg=<bit mask of driver debug message control>
+	dev_cap_mask=<Bit mask of the device capability>
+	This load parameter is uses to configure device features support
+	Usage:
+		dev_cap_mask=<value to be configured>
+		<BIT0-BIT15> : Represents features supported
+		<BIT16>: Indicates support for 11AX
+		<BIT17>: Indicates support for 6G
+	Example:
+		To disable 11AX and 6G support: dev_cap_mask=0xfffcffff
 
-	  bootup_cal_ctrl=0|1 <disable boot time config default | enable boot time config>
-	  ps_mode=0|1|2 <use MLAN default | enable IEEE PS mode | disable IEEE PS mode>
-	  sched_scan=0|1 <disable sched_scan | enable sched_scan default>
-	  max_tx_buf=2048|4096|8192 <maximum AMSDU Tx buffer size>
-	  pm_keep_power=1|0 <PM keep power in suspend (default) | PM no power in suspend>
-	  shutdown_hs=1|0 <Enable HS when shutdown | No HS when shutdown (default)>
-	  cfg_11d=0|1|2 <use MLAN default | enable 11d | disable 11d>
-	  dts_enable=0|1 <Disable DTS | Enable DTS (default)>
-	  fw_name = <FW file name>
+	mac_addr=xx:xx:xx:xx:xx:xx <override the MAC address (in hex)>
+	auto_ds=0|1|2 <use MLAN default | enable auto deepsleep | disable auto deepsleep>
+	ext_scan=0|1|2 <use MLAN default | Enable Extended Scan| Enable Enhanced Extended Scan>
+	p2a_scan=0|1|2 <MLAN default | Enable passive to active scan for DFS channel | Disable passive to active scan for DFS channel>
+	scan_chan_gap=x <Time gap between two scans in milliseconds when connected to AP (max value 500ms)>
+	net_rx=0|1 <use netif_rx/netif_rx_ni in rx | use netif_receive_skb in rx (default)>
+	amsdu_deaggr=0|1 <buf copy in amsud deaggregation | avoid buf copy in amsud deaggregation (default)>
+	bootup_cal_ctrl=0|1 <disable boot time config default | enable boot time config>
+	ps_mode=0|1|2 <use MLAN default | enable IEEE PS mode | disable IEEE PS mode>
+	sched_scan=0|1 <disable sched_scan | enable sched_scan default>
+	max_tx_buf=2048|4096|8192 <maximum AMSDU Tx buffer size>
+	pm_keep_power=1|0 <PM keep power in suspend (default) | PM no power in suspend>
+	shutdown_hs=1|0 <Enable HS when shutdown | No HS when shutdown (default)>
+	cfg_11d=0|1|2 <use MLAN default | enable 11d | disable 11d>
+	dts_enable=0|1 <Disable DTS | Enable DTS (default)>
+	fw_name = <FW file name>
 		e.g. copy pcieuart9098_combo_v1.bin to firmware directory, fw_name=nxp/pcieuart9098_combo_v1.bin
-	  hw_name = <hardware name>
-	  reg_work=0|1 <Disable register work queue| Enable register work queue>
-	  hw_test=0|1 <Disable hardware test (default) | Enable hardware test>
-	  fw_serial=0|1 <support parallel download FW | support serial download FW (default)>
-	  req_fw_nowait=0|1 <use request_firmware API (default) | use request_firmware_nowait API>
-      dfs53cfg=0|1|2 <use Fw Default | New W53 | Old W53>
-	  mcs32=0|1 <disable HT MCS32 support | enable HT MCS32 (default)>
-	  SD8887: antcfg=0|1|2|0xffff <default | Tx/Rx antenna 1 | Tx/Rx antenna 2 | enable antenna diversity>
-	  SD8897/SD8997: antcfg=0x11|0x13|0x33 <Bit0:Rx Path A, Bit1:Rx Path B, Bit 4:Tx Path A, Bit 5:Tx Path B>
-	  slew_rate: Slew Rate Control value = 0|1|2|3 (0 is the slowest slew rate and 03 has the highest slew rate (default))
-	  init_cfg=<init config (MAC addresses, registers etc.) file name>
+	hw_name = <hardware name>
+	reg_work=0|1 <Disable register work queue| Enable register work queue>
+	hw_test=0|1 <Disable hardware test (default) | Enable hardware test>
+	fw_serial=0|1 <support parallel download FW | support serial download FW (default)>
+	req_fw_nowait=0|1 <use request_firmware API (default) | use request_firmware_nowait API>
+	dfs53cfg=0|1|2 <use Fw Default | New W53 | Old W53>
+	mcs32=0|1 <disable HT MCS32 support | enable HT MCS32 (default)>
+	For 9097/9098/IW624/AW693: antcfg=0x101|0x303|.. <Bit0: Tx/Rx Path A for 2G, Bit1: Tx/Rx Path B for 2G, Bit8: Tx/Rx Path A for 5G, Bit9: Tx/Rx Path B for 5G>
+		For AW693, it's recommended to use mod_para configuration file for antcfg as MAC1 supports 2x2 and MAC2 supports only 1x1.
+	For 8897/8997: antcfg=0x11|0x13|0x33 <Bit0:Rx Path A, Bit1:Rx Path B, Bit 4:Tx Path A, Bit 5:Tx Path B>
+	For others: antcfg=0|1|2|0xffff <default | Tx/Rx antenna 1 | Tx/Rx antenna 2 | enable antenna diversity>
+	slew_rate: Slew Rate Control value = 0|1|2|3 (0 is the slowest slew rate and 03 has the highest slew rate (default))
+	init_cfg=<init config (MAC addresses, registers etc.) file name>
 		e.g. copy init_cfg.conf to firmware directory, init_cfg=nxp/init_cfg.conf
-	  cal_data_cfg=<CAL data config file name>
+	cal_data_cfg=<CAL data config file name>
 		e.g. copy cal_data.conf to firmware directory, cal_data_cfg=nxp/cal_data.conf
-          Note: Loading driver with 8887 must include correct cal_data_cfg parameter.
-	 dpd_data_cfg=<DPD data config file name>
-	   e.g. copy dpd_data.conf to firmware directory, dpd_data_cfg=nxp/dpd_data.conf
-	  txpwrlimit_cfg=<Tx power limit config file name>
+		Note: Loading driver with 8887 must include correct cal_data_cfg parameter.
+	dpd_data_cfg=<DPD data config file name>
+		e.g. copy dpd_data.conf to firmware directory, dpd_data_cfg=nxp/dpd_data.conf
+	txpwrlimit_cfg=<Tx power limit config file name>
 		e.g. copy txpwrlimit_cfg_set.conf to firmware directory, txpwrlimit_cfg=nxp/txpwrlimit_cfg_set.conf
 		txpwrlimit_cfg_set.conf file should be the binary format file generate by mlanutl application
-
-      cntry_txpwr=0|1|2
+	cntry_txpwr=0|1|2
                   0: Disable setting tx power table of country (default)
                   1: Enable setting tx power table of country
                   2: Enable setting rgpower table of country
-	  init_hostcmd_cfg=<init hostcmd config file name>
+	init_hostcmd_cfg=<init hostcmd config file name>
 		e.g. copy init_hostcmd_cfg.conf to firmware directory, init_hostcmd_cfg=nxp/init_hostcmd_cfg.conf
-	  band_steer_cfg=<band steer config file name>
+	band_steer_cfg=<band steer config file name>
 		e.g. generate bscfg.conf by band_steer_cfg.conf, then copy bscfg.conf to firmware directory, band_steer_cfg=nxp/bscfg.conf
-	  sdio_rx_aggr=1|0 <Enable SDIO rx aggr (default) | Disable SDIO rx aggr>
-	  cfg80211_wext=<bit mask of CFG80211 and WEXT control>
+	sdio_rx_aggr=1|0 <Enable SDIO rx aggr (default) | Disable SDIO rx aggr>
+	cfg80211_wext=<bit mask of CFG80211 and WEXT control>
 		Bit 0: STA WEXT
 		Bit 1: uAP WEXT
 		Bit 2: STA CFG80211
 		Bit 3: uAP CFG80211
-	  cfg80211_drcs=1|0 <Enable DRCS support (default) | Disable DRCS support>
-	  reg_alpha2=<Regulatory alpha2 (default NULL)>
-	  skip_fwdnld=0|1 <enable FW download support (default) | disable FW download support>
-	  wq_sched_prio: Priority for work queue
-	  wq_sched_policy: Scheduling policy for work queue
+	cfg80211_drcs=1|0 <Enable DRCS support (default) | Disable DRCS support>
+	skip_fwdnld=0|1 <enable FW download support (default) | disable FW download support>
+	wq_sched_prio: Priority for work queue
+	wq_sched_policy: Scheduling policy for work queue
 		(0: SCHED_NORMAL, 1: SCHED_FIFO, 2: SCHED_RR, 3: SCHED_BATCH, 5: SCHED_IDLE)
 		Please note that, both wq_sched_prio and wq_sched_policy should be provided
 		as module parameters. If wq_sched_policy is (0, 3 or 5), then wq_sched_prio
 		must be 0. wq_sched_prio should be 1 to 99 otherwise.
-	  rx_work=0|1|2 <default | Enable rx_work_queue | Disable rx_work_queue>
-	  pcie_int_mode=0|1 <Legacy mode, MSI mode (default)>
-      ring_size=32|64|128|256|512 <adma ring size for 9097/9098>
-	  aggrctrl=1|0 <enable Tx aggr | disable Tx aggr>
-	  usb_aggr=0|1|2 <use MLAN default (disabled) | enable USB aggr | disable USB aggr>
-	  low_power_mode_enable=0|1 <disable low power mode (default)| enable low power mode>
+	rx_work=0|1|2 <default (enabled for multi-core) | Enable rx_work_queue | Disable rx_work_queue>
+	tx_work=0|1 <Disable tx_work_queue | Enable tx_work_queue (default on iMX)>
+	tx_skb_clone=0|1 <Disable tx_skb_clone | Enable tx_skb_clone (default on iMX)>
+	pmqos=0|1 <Disable pmqos | Enable pmqos (default on iMX)>
+	rps=0|x <Disables rps (default) | bit0-bit4 (0x1-0xf) Enables rps on specific cpu>
+	intmode=0|1 <SDIO Interrupt Mode (default) | GPIO Interrupt Mode>
+	gpiopin=0|x <GPIO pin number when intmode=1 (default 0, HW mapped intr on GPIO-21)>
+	pcie_int_mode=0|1 <Legacy mode, MSI mode (default)>
+	ring_size=32|64|128|256|512 <adma ring size for 9097/9098>
+	aggrctrl=1|0 <enable Tx aggr | disable Tx aggr>
+	usb_aggr=0|1|2 <use MLAN default (disabled) | enable USB aggr | disable USB aggr>
+	low_power_mode_enable=0|1 <disable low power mode (default)| enable low power mode>
 	  When low power mode is enabled, the output power will be clipped at ~+10dBm and the
 	  expected PA current is expected to be in the 80-90 mA range for b/g/n modes
 	wakelock_timeout=<set wakelock_timeout value (ms)>
@@ -139,7 +162,7 @@
 	hs_wake_interval=<Host sleep wakeup interval,it will round to nearest multiple dtim*beacon_period in fw>
 	disconnect_on_suspend=0|1 <Disable disconnect wifi on suspend (default) | Enable disconnect wifi on suspend>
 	hs_mimo_switch=0|1 <Disable dynamic MIMO-SISO switch during host sleep (default) | Enable dynamic MIMO-SISO switch during host sleep>
-    hs_auto_arp=0|1 <disable hs_auto_arp (default) | enable hs_auto_arp>
+	hs_auto_arp=0|1 <disable hs_auto_arp (default) | enable hs_auto_arp>
 	gtk_rekey_offload=0|1|2 <disable gtk_rekey_offload|enable gtk_rekey_offload (default) | enable gtk_rekey_offload in suspend mode only>
 	napi=0|1 <disable napi | enable napi>
 	fixed_beacon_buffer=0|1 <allocate default buffer size (default) | allocate max buffer size>
@@ -152,24 +175,39 @@
 	  Bit15~Bit8:Channel time for channel index1;
 	  Bit7~Bit0:mode for channel index1; 0|1 <PM1 | Null2Self>
 	roamoffload_in_hs=0|1 <always enable fw roaming (default) | enable fw roaming only when host suspend>
-	uap_max_sta: Maximum number of STA for UAP/GO (default 0, max 64)
-
+	uap_max_sta: Maximum number of STA for UAP/GO (default 0, max STA number for UAP/GO supported in FW)
+	wacp_mode=0|1|2 <disable WACP (default) | WACP mode 1 | WACP mode 2>
+	dfs_offload=0|1 <disable dfs offload (default) | enable dfs offload>
+	indrstcfg=x <high byte: GPIO pin number (255 default); low byte: IR mode (0: disable, 1: out-of-band, 2: in band)>
 	auto_fw_reload=0|1|3 <disable|enable PCIE FLR|enable PCIE InBand Reset (default)>
 	auto_fw_reload=0|1 <disable|enable InBand Reset (default)>
-
-    dmcs=0|1 <disable (default)|enable dynamic mapping)>
-
+	dmcs=0|1|2 <firmware default (default) | enable dynamic mapping | disable dynamic mapping>
 	host_mlme=0|1 <Operate in non-host_mlme mode | Operate in host_mlme mode (default)>
-	for supplicant/authenticator running on host side, WPA3 support is available only in host_mlme mode
-	for chipset 89xx FP-92, 90xx and later, host_mlme restricted to 1
-	country_ie_ignore=0|1 <Follow countryIE from AP and beacon hint enable (default) | Ignore countryIE from AP and beacon hint disable>
-	beacon_hints=0|1 <enable beacon hints(default) | disable beacon hints>
+		for supplicant/authenticator running on host side, WPA3 support is available only in host_mlme mode
+		for chipset 89xx FP-92, 90xx and later, host_mlme restricted to 1
+	disable_regd_by_driver=0|1 <reg domain set by driver enable | reg domain set by driver disable (default)>
+	reg_alpha2=<Regulatory alpha2 (default NULL)>
+	country_ie_ignore=0|1 <Follow countryIE from AP and beacon hint enable | Ignore countryIE from AP and beacon hint disable (default)>
+	beacon_hints=0|1 <enable beacon hints | disable beacon hints (default)>
+	mon_filter=x <Bit6:TX frames excluding control; Bit5:non-bss beacons; Bit3:unicast destined non-promiscuous frames only; Bit2:data frames; Bit1:control frames; Bit0:management frames>
 	edmac_ctrl=0|1 <Disable edmac EU adaptivity (default) | Enable edmac EU adaptivity>
-
 	chan_track=0|1 <restore channel tracking parameters(default) | set channel tracking new parameters> for 9098 only
 	keep_previous_scan=0|1, <Flush previous scan result before start scan | Keep previous scan result(default)>
 	auto_11ax=0|1, <disable auto_11ax | enable auto_11ax(default)>
-
+	dual_nb=0|1, <default combo FW name - single narrowband (default) | default combo FW name - dual narrowband>
+	fw_data_cfg=0|x <disable configuration for custom Fw data(default) | set configuration for custom Fw data>
+		Configurations for fw_data_cfg:
+		Bit 0: Configuration for Fw remapping addr
+		Bit 1: Configuration for USB endpoint
+		BIT 2: Configuration for DPD current optimizations
+	mclient_scheduling=0|1 <disable multi-client scheduling | enable multi-client scheduling (default)>
+	tx_budget=xxx <airtime tx budget for multi-client scheduling in usec, 0 - disable, 2600 - default>
+	reject_addba_req=0(default)|1|2|3 <set the conditions of rejecting addba request>
+		The conditions are:
+		Bit 0 : 1   -- reject the addba request when host sleep activated
+		Bit 1 : 1   -- reject the addba request when FW auto re-connect enabled
+		               this bit is only used with STA BSS
+		others      -- reserved
 
 	Note: On some platforms (e.g. PXA910/920) double quotation marks ("") need to used
 	for module parameters.
@@ -409,7 +447,7 @@
 
     Set Tx Power
 	This command will set power only if caldata is already loaded in the FW.
-	Power       (0 to 24 dBm)
+	Power       (-15 to 24 dBm)
 	Modulation  (0: CCK, 1:OFDM, 2:MCS)
 	Path ID     (0: PathA, 1:PathB, 2:PathA+B)
 	echo "tx_power=16 2 0" > /proc/mwlan/adapterX/config
@@ -459,13 +497,13 @@
 	GreenField Mode       (0:disable, 1:enable)
 	STBC                  (0:disable, 1:enable)
 	Signal Bw             (0: 20Mhz, 1: 40Mhz, 4:80Mhz, -1: Set to default)
-	NumPkt                (Set to default value -1)
-	MaxPktExt             (Set to default value -1)
-	BeamChange            (Set to default value -1)
-	DCM                   (Set to default value -1)
-	Doppler               (Set to default value -1)
-	MidamblePeriod        (Set to default value -1)
-	QNum                  (Set to default value  1)
+	NumPkt                (-1:Set to default value, 1 to 0xfffffffe to specify number of packaets to send)
+	MaxPktExt             (0|8|16us, -1:Set to default Value 2)
+	BeamChange            (0|1, -1:Set to default Value 1)
+	DCM                   (0|1, -1:Set to default Value 0)
+	Doppler               (0|1, -1:Set to default Value 0)
+	MidamblePeriod        (10|20, -1:Set to default Value 0)
+	QNum                  (0-12|17-20, -1:Set to default Value if 11ax QNum:17 else QNum:0)
 	BSSID                 (xx:xx:xx:xx:xx:xx)
 
 	Example: To start Tx frame with duty cycle, first stop any ongoing Tx
@@ -474,6 +512,40 @@
 	echo "tx_frame=1 7 0xAAA 0x100 1 20 0 0 0 0 0 0 0 0 -1 -1 -1 -1 -1 -1 -1 05:43:3f:c4:51" > /proc/mwlan/adapterX/config
 
     Configure Trigger Frame
+    	Start                 	(0|1, 0:disable, 1:enable)
+    	standalone HETB			(0|1,  0:disable, 1:enable)
+		Frame Control Type		(1: Control frame)
+		Frame Control Sub-Type	(2: Trigger frame)
+		Duration				(0x156C , Max Duration time)
+		TriggerType				(0: Basic Trigger Frame)
+		UlLen					(UL Length)
+		MoreTF					(0|1, 0:FALSE, 1:TRUE)
+		CS Required				(0|1, 0:FALSE, 1:TRUE)
+		UL_bandwidth			(0: 20Mhz, 1: 40Mhz, 2:80Mhz, 3:80+80 MHz|160MHz -1:Set to default value)
+		LTF Type				(0: 1xLTF+1.6usGI, 1: 2xLTF+0.8usGI, 2: 2xLTF+1.6usGI, 3: 4xLTF+3.2usGI)
+		LTF Mode				(0|1, 0: Single stream pilots, 1: Mask LTF sequence of each spatial stream)
+		LTF symbol				(Number of LTF Symbols)
+		UL STBC					(0|1, 0:STBC encoding disable, 1:STBC encoding disable)
+		LDPC ESS				(0|1, 0:LDPC ESS disable, 1:LDPC ESS enable)
+		ApTxPwr					(0-61, 0-60:Values 0-61 maps to -20 dBm to 40 dBm)
+		PreFecPadFct			(1-4, a-factor)
+		Disambing				(0|1, 0:Set to Default)
+		Spatial Reuse			(65535 Default Value)
+		Doppler					(0|1, 0:disable, 1:enable)
+		HE SIG2					(0x1FF Default value)
+		AID12					(any 12 bit value)
+		RUAllocReg				(RU index, any 8 bit value)
+		RUAlloc					(0|1, 0: RU allocated is primary 80Mhz, 1: non-primary 80MHz)
+		Coding Type				(0|1, 0: BCC,1: LDPC)
+		UlMCS				    (Valid MCS Value)
+		UL DCM					(0|1, 0:disable, 1:enable)
+		SSAlloc					(Spatial streams, BITS[0-2]:Number of spatial streams BITS[3-5]:Starting spatial stream)
+		Target RSSI ID			(0-90, 0-90:Values 0-90 map to -100dBm to -20dBm)
+		MPDU MU SF				(0:Multiplier=1, 1:Multiplier=2 , 2:Multiplier=4, 3:Multiplier=8)
+		TID_AL					(0:Set to default Value)
+		AC_PL					(0|1, 0:disable, 1:enable)
+		Pref_AC				    (0:AC_VO, 1:AC_V1, 2:AC_BE, 3:AC_BK)
+
     Example: To configure Trigger frame:
     echo "trigger_frame=1 0 1 2 5484 0 256 0 0 2 1 0 0 0 1 60 1 0 65535 0 511 5 0 67 0 0 0 0 90 0 0 0 0"  > /proc/mwlan/adapter0/config
 
@@ -512,20 +584,20 @@
         Bit 0   -- Tx Path A or Tx/Rx Path A if [n] is not provided
         Bit 1   -- Tx Path B or Tx/Rx Path B if [n] is not provided
         Bit 0-1 -- Tx Path A+B or Tx/Rx Path A+B if [n] is not provided
-        For 9097/9098/IW624, LOW BYTE for 2G setting
+        For 9097/9098/IW624/AW693, LOW BYTE for 2G setting
         Bit 8   -- Tx Path A or Tx/Rx Path A if [n] is not provided
         Bit 9   -- Tx Path B or Tx/Rx Path B if [n] is not provided
         Bit 8-9 -- Tx Path A+B or Tx/Rx Path A+B if [n] is not provided
-        For 9097/9098/IW624, HIGH BYTE for 5G setting
+        For 9097/9098/IW624/AW693, HIGH BYTE for 5G setting
     where value of n is:
         Bit 0   -- Rx Path A
         Bit 1   -- Rx Path B
         Bit 0-1 -- Rx Path A+B
-        For 9097/9098/IW624, LOW BYTE for 2G setting
+        For 9097/9098/IW624/AW693, LOW BYTE for 2G setting
         Bit 8   -- Rx Path A
         Bit 8   -- Rx Path B
         Bit 8-9 -- Rx Path A+B
-        For 9097/9098/IW624, HIGH BYTE for 5G setting
+        For 9097/9098/IW624/AW693, HIGH BYTE for 5G setting
     The Tx path setting (m) is used for both Tx and Rx if Rx path (n) is not provided.
 
     Examples:
diff --git a/mlan/mlan_11ax.c b/mlan/mlan_11ax.c
index cc3374f..44732b7 100644
--- a/mlan/mlan_11ax.c
+++ b/mlan/mlan_11ax.c
@@ -561,8 +561,10 @@ void wlan_update_11ax_cap(mlan_adapter *pmadapter,
 			    (t_u8 *)pmadapter->hw_2g_he_cap,
 			    pmadapter->hw_2g_hecap_len);
 	} else {
-		pmadapter->fw_bands |= BAND_AAX;
-		pmadapter->config_bands |= BAND_AAX;
+		if (pmadapter->fw_bands & BAND_A) {
+			pmadapter->fw_bands |= BAND_AAX;
+			pmadapter->config_bands |= BAND_AAX;
+		}
 		pmadapter->hw_hecap_len =
 			hw_he_cap->len + sizeof(MrvlIEtypesHeader_t);
 		memcpy_ext(pmadapter, pmadapter->hw_he_cap, (t_u8 *)hw_he_cap,
@@ -876,6 +878,7 @@ mlan_status wlan_11ax_ioctl_cmd(pmlan_adapter pmadapter,
 	t_u16 cmd_action = 0;
 	mlan_ds_11ax_llde_pkt_filter_cmd *llde_pkt_filter = MNULL;
 	int mlan_ds_11ax_cmd_cfg_header = 0;
+	t_u8 null_mac_addr[MLAN_MAC_ADDR_LENGTH] = {0};
 
 	ENTER();
 
@@ -907,13 +910,41 @@ mlan_status wlan_11ax_ioctl_cmd(pmlan_adapter pmadapter,
 		pmadapter->llde_packet_type = llde_pkt_filter->packet_type;
 		pmadapter->llde_device_filter = llde_pkt_filter->device_filter;
 
-		memcpy_ext(pmadapter, pmadapter->llde_macfilter1,
-			   &llde_pkt_filter->macfilter1, MLAN_MAC_ADDR_LENGTH,
-			   MLAN_MAC_ADDR_LENGTH);
+		/* reset old entries */
+		pmadapter->llde_totalMacFilters = 0;
+		// coverity[bad_memset: SUPPRESS]
+		memset(pmadapter, (t_u8 *)&pmadapter->llde_macfilters, 0,
+		       MAX_MAC_FILTER_ENTRIES * MLAN_MAC_ADDR_LENGTH);
 
-		memcpy_ext(pmadapter, pmadapter->llde_macfilter2,
-			   &llde_pkt_filter->macfilter2, MLAN_MAC_ADDR_LENGTH,
-			   MLAN_MAC_ADDR_LENGTH);
+		/* copy valid mac adresses only */
+		if (memcmp(pmadapter, &llde_pkt_filter->macfilter1,
+			   &null_mac_addr, MLAN_MAC_ADDR_LENGTH) != 0) {
+			pmadapter->llde_totalMacFilters++;
+			memcpy_ext(pmadapter,
+				   &pmadapter->llde_macfilters
+					    [0 * MLAN_MAC_ADDR_LENGTH],
+				   &llde_pkt_filter->macfilter1,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+
+			if (memcmp(pmadapter, &llde_pkt_filter->macfilter2,
+				   &null_mac_addr, MLAN_MAC_ADDR_LENGTH) != 0) {
+				pmadapter->llde_totalMacFilters++;
+				memcpy_ext(pmadapter,
+					   &pmadapter->llde_macfilters
+						    [1 * MLAN_MAC_ADDR_LENGTH],
+					   &llde_pkt_filter->macfilter2,
+					   MLAN_MAC_ADDR_LENGTH,
+					   MLAN_MAC_ADDR_LENGTH);
+			}
+		} else if (memcmp(pmadapter, &llde_pkt_filter->macfilter2,
+				  &null_mac_addr, MLAN_MAC_ADDR_LENGTH) != 0) {
+			pmadapter->llde_totalMacFilters++;
+			memcpy_ext(pmadapter,
+				   &pmadapter->llde_macfilters
+					    [0 * MLAN_MAC_ADDR_LENGTH],
+				   &llde_pkt_filter->macfilter2,
+				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+		}
 
 		/* remove llde packet filter parameters from buffer which will
 		 * be passed to fimrware */
@@ -1186,6 +1217,9 @@ mlan_status wlan_cmd_twt_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
 			ds_twtcfg->param.twt_setup.twt_mantissa);
 		twt_setup_params->twt_request =
 			ds_twtcfg->param.twt_setup.twt_request;
+		twt_setup_params->bcnMiss_threshold = wlan_cpu_to_le16(
+			ds_twtcfg->param.twt_setup.bcnMiss_threshold);
+
 		cmd->size += sizeof(hostcmd_twtcfg->param.twt_setup);
 		break;
 	case MLAN_11AX_TWT_TEARDOWN_SUBID:
diff --git a/mlan/mlan_11d.c b/mlan/mlan_11d.c
index b1bed8d..a48bed0 100644
--- a/mlan/mlan_11d.c
+++ b/mlan/mlan_11d.c
@@ -36,16 +36,8 @@ Change log:
 ********************************************************/
 
 #ifdef STA_SUPPORT
-/** Region code mapping */
-typedef struct _region_code_mapping {
-	/** Region */
-	t_u8 region[COUNTRY_CODE_LEN];
-	/** Code */
-	t_u8 code;
-} region_code_mapping_t;
-
 /** Region code mapping table */
-static region_code_mapping_t region_code_mapping[] = {
+region_code_mapping_t region_code_mapping[] = {
 	{"US ", 0x10}, /* US FCC      */
 	{"CA ", 0x20}, /* IC Canada   */
 	{"SG ", 0x10}, /* Singapore   */
@@ -115,6 +107,7 @@ static chan_freq_power_t channel_freq_power_UN_AJ[] = {
 	{132, 5660, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
 	{136, 5680, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
 	{140, 5700, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
+	{144, 5720, TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
 	{149, 5745, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
 	{153, 5765, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
 	{157, 5785, TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
@@ -145,7 +138,7 @@ static chan_freq_power_t channel_freq_power_UN_AJ[] = {
  *
  *  @return             Region string
  */
-static t_u8 *wlan_11d_code_2_region(pmlan_adapter pmadapter, t_u8 code)
+t_u8 *wlan_11d_code_2_region(pmlan_adapter pmadapter, t_u8 code)
 {
 	t_u8 i;
 
diff --git a/mlan/mlan_11h.c b/mlan/mlan_11h.c
index 1728b64..c7b3a9a 100644
--- a/mlan/mlan_11h.c
+++ b/mlan/mlan_11h.c
@@ -1673,7 +1673,7 @@ static t_bool wlan_11h_is_slave_on_dfs_chan(mlan_private *priv)
  *  @return        MTRUE-dfs_master and dfs_slave interface on same DFS channel
  *
  */
-t_u8 static wlan_11h_check_dfs_channel(mlan_adapter *pmadapter)
+static t_u8 wlan_11h_check_dfs_channel(mlan_adapter *pmadapter)
 {
 	mlan_private *priv_master = MNULL;
 	mlan_private *priv_slave = MNULL;
@@ -1709,7 +1709,7 @@ t_u8 static wlan_11h_check_dfs_channel(mlan_adapter *pmadapter)
  *
  *  @return      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
  */
-mlan_status static wlan_11h_disable_dfs(mlan_private *priv, t_void *pioctl_buf)
+static mlan_status wlan_11h_disable_dfs(mlan_private *priv, t_void *pioctl_buf)
 {
 	t_u32 enable = 0;
 	mlan_status ret = MLAN_STATUS_SUCCESS;
@@ -3146,6 +3146,7 @@ mlan_status wlan_11h_ioctl_dfs_chan_report(mlan_private *priv,
 	LEAVE();
 	return ret;
 }
+
 /**
  *  @brief Check if channel is under NOP (Non-Occupancy Period)
  *  If so, the channel should not be used until the period expires.
diff --git a/mlan/mlan_11h.h b/mlan/mlan_11h.h
index 8876d1a..337b6f9 100644
--- a/mlan/mlan_11h.h
+++ b/mlan/mlan_11h.h
@@ -4,7 +4,7 @@
  *  function declarations of 802.11h
  *
  *
- *  Copyright 2008-2021 NXP
+ *  Copyright 2008-2024 NXP
  *
  *  This software file (the File) is distributed by NXP
  *  under the terms of the GNU General Public License Version 2, June 1991
diff --git a/mlan/mlan_11n.c b/mlan/mlan_11n.c
index 8ea305f..45eea94 100644
--- a/mlan/mlan_11n.c
+++ b/mlan/mlan_11n.c
@@ -33,6 +33,7 @@ Change log:
 #include "mlan_wmm.h"
 #include "mlan_11n.h"
 #include "mlan_11ac.h"
+#include "mlan_11ax.h"
 
 /********************************************************
 			Local Variables
@@ -510,7 +511,12 @@ static mlan_status wlan_11n_ioctl_addba_param(pmlan_adapter pmadapter,
 		cfg->param.addba_param.rxamsdu = pmpriv->add_ba_param.rx_amsdu;
 	} else {
 		timeout = pmpriv->add_ba_param.timeout;
-		pmpriv->add_ba_param.timeout = cfg->param.addba_param.timeout;
+		if (pmadapter->tx_ba_timeout_support) {
+			pmpriv->add_ba_param.timeout =
+				cfg->param.addba_param.timeout;
+		} else {
+			pmpriv->add_ba_param.timeout = 0;
+		}
 		pmpriv->add_ba_param.tx_win_size =
 			cfg->param.addba_param.txwinsize;
 
@@ -1624,8 +1630,9 @@ void wlan_show_dot11ndevcap(pmlan_adapter pmadapter, t_u32 cap)
 	PRINTM(MINFO, "GET_HW_SPEC: LDPC coded packet receive %s\n",
 	       (ISSUPP_RXLDPC(cap) ? "supported" : "not supported"));
 
-	PRINTM(MINFO, "GET_HW_SPEC: Number of Tx BA streams supported = %d\n",
-	       ISSUPP_GETTXBASTREAM(cap));
+	PRINTM(MINFO,
+	       "GET_HW_SPEC: Number of Tx BA streams supported = %d/%d\n",
+	       ISSUPP_GETTXBASTREAM(cap), wlan_get_bastream_limit(pmadapter));
 	PRINTM(MINFO, "GET_HW_SPEC: 40 Mhz channel width %s\n",
 	       (ISSUPP_CHANWIDTH40(cap) ? "supported" : "not supported"));
 	PRINTM(MINFO, "GET_HW_SPEC: 20 Mhz channel width %s\n",
@@ -2620,6 +2627,8 @@ int wlan_cmd_append_11n_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
 			RESET_EXTCAP_EXT_CHANNEL_SWITCH(pext_cap->ext_cap);
 		else
 			SET_EXTCAP_EXT_CHANNEL_SWITCH(pext_cap->ext_cap);
+		if (wlan_check_11ax_twt_supported(pmpriv, pbss_desc))
+			SET_EXTCAP_TWT_REQ(pext_cap->ext_cap);
 
 		HEXDUMP("Extended Capabilities IE", (t_u8 *)pext_cap,
 			sizeof(MrvlIETypes_ExtCap_t));
@@ -3140,7 +3149,7 @@ int wlan_get_txbastream_tbl(mlan_private *priv, tx_ba_stream_tbl *buf)
 		LEAVE();
 		return count;
 	}
-	bastream_max = ISSUPP_GETTXBASTREAM(priv->adapter->hw_dot_11n_dev_cap);
+	bastream_max = wlan_get_bastream_limit(priv->adapter);
 	if (bastream_max == 0)
 		bastream_max = MLAN_MAX_TX_BASTREAM_DEFAULT;
 
diff --git a/mlan/mlan_11n.h b/mlan/mlan_11n.h
index 58427b3..483985f 100644
--- a/mlan/mlan_11n.h
+++ b/mlan/mlan_11n.h
@@ -297,7 +297,7 @@ static INLINE t_u8 wlan_is_amsdu_allowed(mlan_private *priv, raListTbl *ptr,
 #ifdef UAP_SUPPORT
 	sta_node *sta_ptr = MNULL;
 #endif
-	if (priv->amsdu_disable)
+	if (priv->amsdu_disable || !ptr->max_amsdu)
 		return MFALSE;
 #ifdef UAP_SUPPORT
 	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
@@ -323,6 +323,23 @@ static INLINE t_u8 wlan_is_amsdu_allowed(mlan_private *priv, raListTbl *ptr,
 		       MFALSE;
 }
 
+/**
+ *  @brief This function gets max number of BA stream supported
+ *
+ *  @param pmadapter  A pointer to mlan_adapter
+ *
+ *  @return           number of BA streams
+ */
+static INLINE t_u32 wlan_get_bastream_limit(mlan_adapter *pmadapter)
+{
+	t_u32 bastreams = ISSUPP_GETTXBASTREAM(pmadapter->hw_dot_11n_dev_cap);
+
+	if (pmadapter->mclient_tx_supported)
+		return pmadapter->tx_ba_stream_limit;
+
+	return bastreams;
+}
+
 /**
  *  @brief This function checks whether a BA stream is available or not
  *
@@ -342,7 +359,7 @@ static INLINE t_u8 wlan_is_bastream_avail(mlan_private *priv)
 			bastream_num += wlan_wmm_list_len(
 				(pmlan_list_head)&pmpriv->tx_ba_stream_tbl_ptr);
 	}
-	bastream_max = ISSUPP_GETTXBASTREAM(priv->adapter->hw_dot_11n_dev_cap);
+	bastream_max = wlan_get_bastream_limit(priv->adapter);
 	if (bastream_max == 0)
 		bastream_max = MLAN_MAX_TX_BASTREAM_DEFAULT;
 	return (bastream_num < bastream_max) ? MTRUE : MFALSE;
diff --git a/mlan/mlan_11n_aggr.c b/mlan/mlan_11n_aggr.c
index e1925d4..857ee54 100644
--- a/mlan/mlan_11n_aggr.c
+++ b/mlan/mlan_11n_aggr.c
@@ -187,6 +187,9 @@ static t_u16 wlan_form_amsdu_txpd(mlan_private *priv, mlan_buffer *pmbuf,
 
 	head_ptr = pmbuf->pbuf + pmbuf->data_offset - Tx_PD_SIZEOF(pmadapter) -
 		   priv->intf_hr_len;
+	/*making data buffer 8 ytes aligned for increasing TP with PCIE Scatter
+	 * Gather*/
+	head_ptr = (t_u8 *)((t_ptr)head_ptr & ~((t_ptr)(8 - 1)));
 	ptx_pd = (TxPD *)(head_ptr + priv->intf_hr_len);
 	// coverity[bad_memset:SUPPRESS]
 	memset(pmadapter, ptx_pd, 0, Tx_PD_SIZEOF(pmadapter));
@@ -675,6 +678,8 @@ static int wlan_send_amsdu_subframe_list(mlan_private *priv,
 		goto exit;
 	}
 
+	wlan_wmm_consume_mpdu_budget(pra_list);
+
 	while (pmbuf_src &&
 	       ((pkt_size + (pmbuf_src->data_len + LLC_SNAP_LEN) + headroom) <=
 		max_amsdu_size) &&
@@ -683,6 +688,7 @@ static int wlan_send_amsdu_subframe_list(mlan_private *priv,
 			(pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
 							&pra_list->buf_head,
 							MNULL, MNULL);
+		wlan_wmm_consume_byte_budget(pra_list, pmbuf_src);
 		/* Collects TP statistics */
 		if (pmadapter->tp_state_on &&
 		    (pkt_size > Tx_PD_SIZEOF(pmadapter)))
@@ -728,7 +734,13 @@ static int wlan_send_amsdu_subframe_list(mlan_private *priv,
 
 	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
 					      priv->wmm.ra_list_spinlock);
-
+	if (!pmbuf_last) {
+		PRINTM(MERROR,
+		       "SG_AGGR ERROR: pkt_size=%d max_msdu_count=%d max_amsdu_size=%d msdu_in_tx_amsdu_cnt=%d\n",
+		       pkt_size, max_msdu_count, max_amsdu_size,
+		       msdu_in_tx_amsdu_cnt);
+		goto exit;
+	}
 	/* Last AMSDU packet does not need padding */
 	pkt_size -= pad;
 	pmbuf_last->data_len -= pad;
@@ -758,9 +770,8 @@ static int wlan_send_amsdu_subframe_list(mlan_private *priv,
 			priv->wmm.packets_out[ptrindex]++;
 			priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list;
 		}
-		pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
-			pmadapter->bssprio_tbl[priv->bss_priority]
-				.bssprio_cur->pnext;
+		wlan_advance_bss_on_pkt_push(
+			pmadapter, &pmadapter->bssprio_tbl[priv->bss_priority]);
 		pmadapter->callbacks.moal_spin_unlock(
 			pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
 	}
@@ -865,12 +876,15 @@ int wlan_11n_aggregate_pkt(mlan_private *priv, raListTbl *pra_list,
 		goto exit;
 	}
 
+	wlan_wmm_consume_mpdu_budget(pra_list);
+
 	while (pmbuf_src && ((pkt_size + (pmbuf_src->data_len + LLC_SNAP_LEN) +
 			      headroom) <= max_amsdu_size)) {
 		pmbuf_src =
 			(pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
 							&pra_list->buf_head,
 							MNULL, MNULL);
+		wlan_wmm_consume_byte_budget(pra_list, pmbuf_src);
 		/* Collects TP statistics */
 		if (pmadapter->tp_state_on &&
 		    (pkt_size > Tx_PD_SIZEOF(pmadapter)))
@@ -1011,9 +1025,10 @@ int wlan_11n_aggregate_pkt(mlan_private *priv, raListTbl *pra_list,
 			priv->wmm.packets_out[ptrindex]++;
 			priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list;
 		}
-		pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
-			pmadapter->bssprio_tbl[priv->bss_priority]
-				.bssprio_cur->pnext;
+
+		wlan_advance_bss_on_pkt_push(
+			pmadapter, &pmadapter->bssprio_tbl[priv->bss_priority]);
+
 		pmadapter->callbacks.moal_spin_unlock(
 			pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
 	}
diff --git a/mlan/mlan_cfp.c b/mlan/mlan_cfp.c
index 0fdb12b..aaf9e91 100644
--- a/mlan/mlan_cfp.c
+++ b/mlan/mlan_cfp.c
@@ -83,6 +83,7 @@ static country_code_mapping_t country_code_mapping[] = {
 	{"KR", 0x30, 0x30}, /* Republic Of Korea */
 	{"JP", 0xFF, 0x40}, /* Japan       */
 	{"CN", 0x30, 0x50}, /* China       */
+	{"TW", 0x30, 0x30}, /* TW support  */
 	{"BR", 0x01, 0x09}, /* Brazil      */
 	{"RU", 0x30, 0x0f}, /* Russia      */
 	{"IN", 0x10, 0x06}, /* India       */
@@ -3232,8 +3233,9 @@ static void wlan_sort_cfp_otp_table(mlan_adapter *pmadapter)
  */
 static void wlan_set_otp_cfp_max_tx_pwr(mlan_adapter *pmadapter, t_bool is6g)
 {
-	t_u8 i, j;
+	t_u8 i, j, k, n;
 	t_u8 rows, cols, max = 0;
+	t_u8 bonded_chan_count = 0;
 
 	if (!pmadapter->otp_region)
 		return;
@@ -3243,20 +3245,49 @@ static void wlan_set_otp_cfp_max_tx_pwr(mlan_adapter *pmadapter, t_bool is6g)
 		cols = pmadapter->tx_power_table_bg_cols;
 		if (pmadapter->tx_power_table_bg_size < (rows * cols))
 			goto table_a;
+		max = 0;
 		for (i = 0; i < rows; i++) {
-			max = 0;
 			if ((pmadapter->cfp_otp_bg + i)->dynamic.flags &
 			    NXP_CHANNEL_DISABLED)
 				continue;
-			/* get the max value among all mod group for this
-			 * channel */
-			for (j = 1; j < cols; j++)
+
+			/* Get the max value among all mod groups for this chan
+			 */
+			for (j = 1; j < cols; j++) {
 				max = MAX(
 					max,
 					pmadapter->tx_power_table_bg[i * cols +
 								     j]);
+			}
 
-			(pmadapter->cfp_otp_bg + i)->max_tx_power = max;
+			bonded_chan_count++;
+			/* As the BG band allows overlapping 40MHz
+			 * bonded groups, keep comparing the max value
+			 * with the next consecutive 40Mhz channel, if
+			 * all of below 4 cases are true:
+			 *   1. this is not the last row
+			 *   2. this channel suports 40 MHz
+			 *   3. the next channel also supports 40MHz
+			 *   4. the next channel is not disabled
+			 */
+			if ((i < (rows - 1)) &&
+			    (!((pmadapter->cfp_otp_bg + i)->dynamic.flags &
+			       NXP_CHANNEL_NOHT40)) &&
+			    (!((pmadapter->cfp_otp_bg + i + 1)->dynamic.flags &
+			       NXP_CHANNEL_NOHT40)) &&
+			    (!((pmadapter->cfp_otp_bg + i + 1)->dynamic.flags &
+			       NXP_CHANNEL_DISABLED))) {
+				continue;
+			}
+			/* Apply the max power value to all channels in this
+			 * bonded group
+			 */
+			for (k = 0; k < bonded_chan_count; k++) {
+				(pmadapter->cfp_otp_bg + i - k)->max_tx_power =
+					max;
+			}
+			max = 0;
+			bonded_chan_count = 0;
 		}
 	}
 table_a:
@@ -3265,19 +3296,62 @@ table_a:
 		cols = pmadapter->tx_power_table_a_cols;
 		if (pmadapter->tx_power_table_a_size < (rows * cols))
 			return;
+		max = 0;
+		bonded_chan_count = 0;
 		for (i = 0; i < rows; i++) {
-			max = 0;
 			if ((pmadapter->cfp_otp_a + i)->dynamic.flags &
 			    NXP_CHANNEL_DISABLED)
 				continue;
-			/* get the max value among all mod group for this
-			 * channel */
+
+			/* The 5G cfp table is sorted based on the channel num
+			 * and may contain 4G and 5.9G channels. As the cfp
+			 * table index may not match the 5G powertable channel
+			 * index, get the corresponding channel row from
+			 * powertable
+			 */
+			n = 0;
+			while (n < pmadapter->tx_power_table_a_rows) {
+				if (pmadapter->tx_power_table_a[n * cols] ==
+				    (pmadapter->cfp_otp_a + i)->channel)
+					break;
+				n++;
+			}
+			/* Get the max value among all mod groups for this chan
+			 */
 			for (j = 1; j < cols; j++)
 				max = MAX(max,
-					  pmadapter->tx_power_table_a[i * cols +
+					  pmadapter->tx_power_table_a[n * cols +
 								      j]);
 
-			(pmadapter->cfp_otp_a + i)->max_tx_power = max;
+			bonded_chan_count++;
+
+			if ((i < (rows - 1)) &&
+			    !((pmadapter->cfp_otp_a + i + 1)->dynamic.flags &
+			      NXP_CHANNEL_DISABLED)) {
+				/* Compare the max power value with the next
+				 * chan in this bonded group, unless this is the
+				 * last or the next one is disabled
+				 */
+				if (!((pmadapter->cfp_otp_a + i)->dynamic.flags &
+				      NXP_CHANNEL_NOHT80)) {
+					if (bonded_chan_count < 4)
+						continue;
+				} else if (!((pmadapter->cfp_otp_a + i)
+						     ->dynamic.flags &
+					     NXP_CHANNEL_NOHT40)) {
+					if (bonded_chan_count < 2)
+						continue;
+				}
+			}
+
+			/* Apply the max power value to all channels in this
+			 * bonded group
+			 */
+			for (k = 0; k < bonded_chan_count; k++)
+				(pmadapter->cfp_otp_a + i - k)->max_tx_power =
+					max;
+			max = 0;
+			bonded_chan_count = 0;
 		}
 	}
 }
@@ -3375,12 +3449,15 @@ void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
 					break;
 				}
 			}
-			for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
-				if (cfp_table_A[i].code ==
-				    pmadapter->otp_region->region_code) {
-					max_tx_pwr_a = (cfp_table_A[i].cfp)
-							       ->max_tx_power;
-					break;
+			if (pmadapter->fw_bands & BAND_A) {
+				for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
+					if (cfp_table_A[i].code ==
+					    pmadapter->otp_region->region_code) {
+						max_tx_pwr_a =
+							(cfp_table_A[i].cfp)
+								->max_tx_power;
+						break;
+					}
 				}
 			}
 			PRINTM(MCMND,
@@ -3481,6 +3558,12 @@ void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
 					       ->dynamic.flags);
 				data++;
 			}
+			if (!(pmadapter->fw_bands & BAND_A)) {
+				pmadapter->tx_power_table_a_rows = 0;
+				pmadapter->tx_power_table_a_cols = 0;
+				break;
+			}
+
 			ret = pcb->moal_malloc(
 				pmadapter->pmoal_handle,
 				pmadapter->tx_power_table_a_rows *
@@ -3564,6 +3647,12 @@ void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
 				   data, i, i);
 			pmadapter->tx_power_table_bg_size = i;
 			data += i;
+			if (!(pmadapter->fw_bands & BAND_A)) {
+				pmadapter->tx_power_table_a_rows = 0;
+				pmadapter->tx_power_table_a_cols = 0;
+				break;
+			}
+
 			i = 0;
 			while ((i < pmadapter->tx_power_table_a_rows *
 					    pmadapter->tx_power_table_a_cols) &&
@@ -3592,16 +3681,19 @@ void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
 				((power_table_attr_t *)data)->rows_2g;
 			pmadapter->tx_power_table_bg_cols =
 				((power_table_attr_t *)data)->cols_2g;
-			pmadapter->tx_power_table_a_rows =
-				((power_table_attr_t *)data)->rows_5g;
-			pmadapter->tx_power_table_a_cols =
-				((power_table_attr_t *)data)->cols_5g;
-			PRINTM(MCMD_D,
-			       "OTP region: bg_row=%d,bg_cols=%d a_row=%d, a_cols=%d\n",
+			PRINTM(MCMD_D, "OTP region: bg_row=%d,bg_cols=%d\n",
 			       pmadapter->tx_power_table_bg_rows,
-			       pmadapter->tx_power_table_bg_cols,
-			       pmadapter->tx_power_table_a_rows,
-			       pmadapter->tx_power_table_a_cols);
+			       pmadapter->tx_power_table_bg_cols);
+			if (pmadapter->fw_bands & BAND_A) {
+				pmadapter->tx_power_table_a_rows =
+					((power_table_attr_t *)data)->rows_5g;
+				pmadapter->tx_power_table_a_cols =
+					((power_table_attr_t *)data)->cols_5g;
+				PRINTM(MCMD_D,
+				       "OTP region: a_row=%d, a_cols=%d\n",
+				       pmadapter->tx_power_table_a_rows,
+				       pmadapter->tx_power_table_a_cols);
+			}
 			break;
 		default:
 			break;
@@ -3612,8 +3704,6 @@ void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
 	if (!pmadapter->cfp_otp_bg || !pmadapter->tx_power_table_bg)
 		goto out;
 
-	wlan_set_otp_cfp_max_tx_pwr(pmadapter, MFALSE);
-
 	/* Set remaining flags for BG */
 	rows = pmadapter->tx_power_table_bg_rows;
 	cols = pmadapter->tx_power_table_bg_cols;
@@ -3637,6 +3727,7 @@ void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
 	}
 	if (pmadapter->cfp_otp_a)
 		wlan_sort_cfp_otp_table(pmadapter);
+	wlan_set_otp_cfp_max_tx_pwr(pmadapter, MFALSE);
 out:
 	LEAVE();
 }
@@ -3735,7 +3826,8 @@ mlan_status wlan_get_cfpinfo(pmlan_adapter pmadapter,
 	t_u8 cfp_code_a = pmadapter->region_code;
 	t_u8 cfp_code_bg = pmadapter->region_code;
 	t_u32 len = 0, size = 0;
-	t_u8 *req_buf, *tmp;
+	t_u8 *req_buf;
+	mlan_cfpinfo c = {0};
 	mlan_status ret = MLAN_STATUS_SUCCESS;
 
 	ENTER();
@@ -3755,33 +3847,29 @@ mlan_status wlan_get_cfpinfo(pmlan_adapter pmadapter,
 	/* Calculate the total response size required to return region,
 	 * country codes, cfp tables and power tables
 	 */
-	size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
-	/* Add size to store region, country and environment codes */
-	size += sizeof(t_u32);
-	if (pmadapter->cfp_code_bg)
-		cfp_code_bg = pmadapter->cfp_code_bg;
-
+	size = sizeof(mlan_cfpinfo);
 	/* Get cfp table and its size corresponding to the region code */
-	cfp_bg = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
-					   BAND_G | BAND_B, &cfp_no_bg);
-	size += cfp_no_bg * sizeof(chan_freq_power_t);
-	if (pmadapter->cfp_code_a)
-		cfp_code_a = pmadapter->cfp_code_a;
-	cfp_a = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
-					  &cfp_no_a);
-	size += cfp_no_a * sizeof(chan_freq_power_t);
-	if (pmadapter->otp_region)
-		size += sizeof(pmadapter->otp_region->environment);
-
-	/* Get power table size */
-	if (pmadapter->tx_power_table_bg) {
+	if (pmadapter->fw_bands & (BAND_B | BAND_G)) {
+		if (pmadapter->cfp_code_bg)
+			cfp_code_bg = pmadapter->cfp_code_bg;
+		cfp_bg = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
+						   BAND_G | BAND_B, &cfp_no_bg);
+		size += cfp_no_bg * sizeof(chan_freq_power_t);
+		c.is2g_present = 1;
+		c.rows_2g = cfp_no_bg;
+		c.cols_2g = pmadapter->tx_power_table_bg_cols;
 		size += pmadapter->tx_power_table_bg_size;
-		/* Add size to store table size, rows and cols */
-		size += 3 * sizeof(t_u32);
 	}
-	if (pmadapter->tx_power_table_a) {
+	if (pmadapter->fw_bands & BAND_A) {
+		if (pmadapter->cfp_code_a)
+			cfp_code_a = pmadapter->cfp_code_a;
+		cfp_a = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
+						  &cfp_no_a);
+		size += cfp_no_a * sizeof(chan_freq_power_t);
+		c.is5g_present = 1;
+		c.rows_5g = cfp_no_a;
+		c.cols_5g = pmadapter->tx_power_table_a_cols;
 		size += pmadapter->tx_power_table_a_size;
-		size += 3 * sizeof(t_u32);
 	}
 	/* Check information buffer length of MLAN IOCTL */
 	if (pioctl_req->buf_len < size) {
@@ -3792,90 +3880,52 @@ mlan_status wlan_get_cfpinfo(pmlan_adapter pmadapter,
 		ret = MLAN_STATUS_RESOURCE;
 		goto out;
 	}
-	/* Copy the total size of region code, country code and environment
-	 * in first four bytes of the IOCTL request buffer and then copy
-	 * codes respectively in following bytes
-	 */
+
 	req_buf = (t_u8 *)pioctl_req->pbuf;
-	size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
+
+	/* Copy the nss, region code, country code and environment */
+	if (IS_STREAM_2X2(pmadapter->feature_control))
+		c.nss = 2;
+	else if (IS_CARDAW693(pmadapter->card_type) && !pmadapter->second_mac)
+		c.nss = 2;
+	else
+		c.nss = 1;
+	c.region_code = (t_u8)pmadapter->region_code;
+	c.country_code[0] = pmadapter->country_code[0];
+	c.country_code[1] = pmadapter->country_code[1];
 	if (pmadapter->otp_region)
-		size += sizeof(pmadapter->otp_region->environment);
-	tmp = (t_u8 *)&size;
-	memcpy_ext(pmadapter, req_buf, tmp, sizeof(size), sizeof(size));
-	len += sizeof(size);
-	memcpy_ext(pmadapter, req_buf + len, &pmadapter->region_code,
-		   sizeof(pmadapter->region_code),
-		   sizeof(pmadapter->region_code));
-	len += sizeof(pmadapter->region_code);
-	memcpy_ext(pmadapter, req_buf + len, &pmadapter->country_code,
-		   sizeof(pmadapter->country_code),
-		   sizeof(pmadapter->country_code));
-	len += sizeof(pmadapter->country_code);
-	if (pmadapter->otp_region) {
-		memcpy_ext(pmadapter, req_buf + len,
-			   &pmadapter->otp_region->environment,
-			   sizeof(pmadapter->otp_region->environment),
-			   sizeof(pmadapter->otp_region->environment));
-		len += sizeof(pmadapter->otp_region->environment);
+		c.environment = pmadapter->otp_region->environment;
+	/* copy the mlan_cfpinfo struct at the start of req_buf */
+	memcpy_ext(pmadapter, req_buf, &c, sizeof(mlan_cfpinfo),
+		   sizeof(mlan_cfpinfo));
+	len += sizeof(mlan_cfpinfo);
+
+	/* copy cfp tables */
+	if (cfp_bg) {
+		size = cfp_no_bg * sizeof(chan_freq_power_t);
+		memcpy_ext(pmadapter, req_buf + len, cfp_bg, size, size);
+		len += size;
+	}
+	if (cfp_a) {
+		size = cfp_no_a * sizeof(chan_freq_power_t);
+		memcpy_ext(pmadapter, req_buf + len, cfp_a, size, size);
+		len += size;
+	}
+	/* copy power tables */
+	if (pmadapter->tx_power_table_bg) {
+		memcpy_ext(pmadapter, req_buf + len,
+			   pmadapter->tx_power_table_bg,
+			   pmadapter->tx_power_table_bg_size,
+			   pmadapter->tx_power_table_bg_size);
+		len += pmadapter->tx_power_table_bg_size;
+	}
+	if (pmadapter->tx_power_table_a) {
+		memcpy_ext(pmadapter, req_buf + len,
+			   pmadapter->tx_power_table_a,
+			   pmadapter->tx_power_table_a_size,
+			   pmadapter->tx_power_table_a_size);
+		len += pmadapter->tx_power_table_a_size;
 	}
-	/* copy the cfp table size followed by the entire table */
-	if (!cfp_bg)
-		goto out;
-	size = cfp_no_bg * sizeof(chan_freq_power_t);
-	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
-	len += sizeof(size);
-	memcpy_ext(pmadapter, req_buf + len, cfp_bg, size, size);
-	len += size;
-	if (!cfp_a)
-		goto out;
-	size = cfp_no_a * sizeof(chan_freq_power_t);
-	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
-	len += sizeof(size);
-	memcpy_ext(pmadapter, req_buf + len, cfp_a, size, size);
-	len += size;
-	/* Copy the size of the power table, number of rows, number of cols
-	 * and the entire power table
-	 */
-	if (!pmadapter->tx_power_table_bg)
-		goto out;
-	size = pmadapter->tx_power_table_bg_size;
-	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
-	len += sizeof(size);
-
-	/* No. of rows */
-	size = pmadapter->tx_power_table_bg_rows;
-	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
-	len += sizeof(size);
-
-	/* No. of cols */
-	size = pmadapter->tx_power_table_bg_size /
-	       pmadapter->tx_power_table_bg_rows;
-	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
-	len += sizeof(size);
-	memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_bg,
-		   pmadapter->tx_power_table_bg_size,
-		   pmadapter->tx_power_table_bg_size);
-	len += pmadapter->tx_power_table_bg_size;
-	if (!pmadapter->tx_power_table_a)
-		goto out;
-	size = pmadapter->tx_power_table_a_size;
-	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
-	len += sizeof(size);
-
-	/* No. of rows */
-	size = pmadapter->tx_power_table_a_rows;
-	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
-	len += sizeof(size);
-
-	/* No. of cols */
-	size = pmadapter->tx_power_table_a_size /
-	       pmadapter->tx_power_table_a_rows;
-	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
-	len += sizeof(size);
-	memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_a,
-		   pmadapter->tx_power_table_a_size,
-		   pmadapter->tx_power_table_a_size);
-	len += pmadapter->tx_power_table_a_size;
 out:
 	if (pioctl_req)
 		pioctl_req->data_read_written = len;
diff --git a/mlan/mlan_cmdevt.c b/mlan/mlan_cmdevt.c
index 4eef939..49c645e 100644
--- a/mlan/mlan_cmdevt.c
+++ b/mlan/mlan_cmdevt.c
@@ -1365,12 +1365,6 @@ static mlan_status wlan_dnld_cmd_to_fw(mlan_private *pmpriv,
 	     pcmd->command == HostCmd_CMD_802_11_DISASSOCIATE))
 		wlan_clean_txrx(pmpriv);
 
-	if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA &&
-	    pmpriv->media_connected &&
-	    (pcmd->command == HostCmd_CMD_802_11_DEAUTHENTICATE ||
-	     pcmd->command == HostCmd_CMD_802_11_DISASSOCIATE))
-		wlan_clean_txrx(pmpriv);
-
 	PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
 	PRINTM_NETINTF(MCMND, pmpriv);
 	PRINTM(MCMND,
@@ -1894,7 +1888,49 @@ t_void wlan_release_cmd_lock(mlan_adapter *pmadapter)
 	LEAVE();
 	return;
 }
+#ifdef USB
+/**
+ *  @brief This function requests a lock on Rx event.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+t_void wlan_request_event_lock(mlan_adapter *pmadapter)
+{
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
 
+	ENTER();
+
+	/* Call MOAL spin lock callback function */
+	pcb->moal_spin_lock(pmadapter->pmoal_handle,
+			    pmadapter->pmlan_usb_event_lock);
+
+	LEAVE();
+	return;
+}
+
+/**
+ *  @brief This function releases a lock on Rx event.
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             N/A
+ */
+t_void wlan_release_event_lock(mlan_adapter *pmadapter)
+{
+	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
+
+	ENTER();
+
+	/* Call MOAL spin unlock callback function */
+	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
+			      pmadapter->pmlan_usb_event_lock);
+
+	LEAVE();
+	return;
+}
+#endif
 /**
  *  @brief This function prepare the command before sending to firmware.
  *
@@ -2209,6 +2245,7 @@ done:
 	return ret;
 }
 
+#if defined(SDIO) || defined(PCIE)
 /**
  *  @brief This function handles the command error in pre_asleep state
  *
@@ -2226,20 +2263,12 @@ static void wlan_handle_cmd_error_in_pre_aleep(mlan_adapter *pmadapter,
 	pcmd_node = pmadapter->curr_cmd;
 	pmadapter->curr_cmd = MNULL;
 	if (pcmd_node) {
-#ifdef USB
-		if (IS_USB(pmadapter->card_type)) {
-			pcmd_node->cmdbuf->data_offset += MLAN_TYPE_LEN;
-			pcmd_node->cmdbuf->data_len -= MLAN_TYPE_LEN;
-		}
-#endif
-#if defined(SDIO) || defined(PCIE)
 		if (!IS_USB(pmadapter->card_type)) {
 			pcmd_node->cmdbuf->data_offset +=
 				pmadapter->ops.intf_header_len;
 			pcmd_node->cmdbuf->data_len -=
 				pmadapter->ops.intf_header_len;
 		}
-#endif
 		if (pcmd_node->respbuf) {
 			pmadapter->ops.cmdrsp_complete(pmadapter,
 						       pcmd_node->respbuf,
@@ -2251,6 +2280,7 @@ static void wlan_handle_cmd_error_in_pre_aleep(mlan_adapter *pmadapter,
 	wlan_release_cmd_lock(pmadapter);
 	LEAVE();
 }
+#endif
 
 /**
  *  @brief This function handles the command response
@@ -2403,26 +2433,29 @@ mlan_status wlan_process_cmdresp(mlan_adapter *pmadapter)
 	}
 
 	if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
-		if (pmadapter->curr_cmd &&
+#if defined(SDIO) || defined(PCIE)
+		if (!IS_USB(pmadapter->card_type) && pmadapter->curr_cmd &&
 		    cmdresp_result == HostCmd_RESULT_PRE_ASLEEP) {
 			wlan_handle_cmd_error_in_pre_aleep(pmadapter,
 							   cmdresp_no);
 			ret = MLAN_STATUS_FAILURE;
 			goto done;
 		}
+#endif
 		pmadapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
 		if ((cmdresp_result == HostCmd_RESULT_OK) &&
 		    (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
 			ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
 	} else {
-		if (pmadapter->curr_cmd &&
+#if defined(SDIO) || defined(PCIE)
+		if (!IS_USB(pmadapter->card_type) && pmadapter->curr_cmd &&
 		    cmdresp_result == HostCmd_RESULT_PRE_ASLEEP) {
 			wlan_handle_cmd_error_in_pre_aleep(pmadapter,
 							   cmdresp_no);
 			ret = MLAN_STATUS_FAILURE;
 			goto done;
 		}
-
+#endif
 		/* handle response */
 		ret = pmpriv->ops.process_cmdresp(pmpriv, cmdresp_no, resp,
 						  pioctl_buf);
@@ -4356,6 +4389,102 @@ mlan_status wlan_ret_802_11_tx_rate_query(pmlan_private pmpriv,
 	return MLAN_STATUS_SUCCESS;
 }
 
+/**
+ * @brief This function prepares command of fw_wakeup_method.
+ *
+ * @param pmpriv       A pointer to mlan_private structure
+ * @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ * @param cmd_action   The action: GET or SET
+ * @param pdata_buf    A pointer to data buffer
+ *
+ * @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_802_11_fw_wakeup_method(pmlan_private pmpriv,
+					     HostCmd_DS_COMMAND *cmd,
+					     t_u16 cmd_action, t_u16 *pdata_buf)
+{
+	HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &cmd->params.fwwakeupmethod;
+	mlan_fw_wakeup_params *fw_wakeup_params = MNULL;
+	MrvlIEtypes_WakeupSourceGPIO_t *tlv =
+		(MrvlIEtypes_WakeupSourceGPIO_t *)(t_u8 *)fwwm->tlv_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_FW_WAKE_METHOD);
+	cmd->size = sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) + S_DS_GEN;
+	fwwm->action = wlan_cpu_to_le16(cmd_action);
+	switch (cmd_action) {
+	case HostCmd_ACT_GEN_SET:
+		fw_wakeup_params = (mlan_fw_wakeup_params *)pdata_buf;
+		fwwm->method = wlan_cpu_to_le16(fw_wakeup_params->method);
+
+		if (fw_wakeup_params->method == WAKEUP_FW_THRU_GPIO) {
+			cmd->size += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
+			tlv->header.type = wlan_cpu_to_le16(
+				TLV_TYPE_HS_WAKEUP_SOURCE_GPIO);
+			tlv->header.len = wlan_cpu_to_le16(
+				sizeof(MrvlIEtypes_WakeupSourceGPIO_t) -
+				sizeof(MrvlIEtypesHeader_t));
+			tlv->ind_gpio = (t_u8)fw_wakeup_params->gpio_pin;
+		}
+
+		break;
+	case HostCmd_ACT_GEN_GET:
+	default:
+		fwwm->method = wlan_cpu_to_le16(WAKEUP_FW_UNCHANGED);
+		break;
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of fw_wakeup_method
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_fw_wakeup_method(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *resp,
+				      mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &resp->params.fwwakeupmethod;
+	t_u16 action;
+	MrvlIEtypes_WakeupSourceGPIO_t *gpio_tlv =
+		(MrvlIEtypes_WakeupSourceGPIO_t *)(t_u8 *)fwwm->tlv_buf;
+	mlan_ds_pm_cfg *pmcfg = MNULL;
+
+	ENTER();
+
+	action = wlan_le16_to_cpu(fwwm->action);
+
+	pmpriv->adapter->fw_wakeup_method = wlan_le16_to_cpu(fwwm->method);
+	pmpriv->adapter->fw_wakeup_gpio_pin = 0;
+
+	if ((resp->size -
+	     (sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) + S_DS_GEN)) ==
+	    sizeof(MrvlIEtypes_WakeupSourceGPIO_t)) {
+		pmpriv->adapter->fw_wakeup_gpio_pin = gpio_tlv->ind_gpio;
+	}
+	PRINTM(MCMND, "FW wakeup method=%d, gpio=%d\n",
+	       pmpriv->adapter->fw_wakeup_method,
+	       pmpriv->adapter->fw_wakeup_gpio_pin);
+
+	if (pioctl_buf) {
+		pmcfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
+		pmcfg->param.fw_wakeup_params.method =
+			pmpriv->adapter->fw_wakeup_method;
+		pmcfg->param.fw_wakeup_params.gpio_pin =
+			pmpriv->adapter->fw_wakeup_gpio_pin;
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
 /**
  * @brief This function prepares command of robustcoex.
  *
@@ -4956,6 +5085,38 @@ mlan_status wlan_ret_tx_rate_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 	return ret;
 }
 
+/**
+ *  @brief  This function prepares command of func_init.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_func_init(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd)
+{
+	HostCmd_DS_FUNC_INIT *func_init = &cmd->params.func_init;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	MrvlIEtypes_boot_time_cfg_t *pboot_time_tlv = MNULL;
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_FUNC_INIT);
+	cmd->size = S_DS_GEN + sizeof(MrvlIEtypes_boot_time_cfg_t);
+	pboot_time_tlv = (MrvlIEtypes_boot_time_cfg_t *)func_init->tlv_buf;
+	pboot_time_tlv->type = wlan_cpu_to_le16(TLV_TYPE_BOOT_TIME_CFG);
+	pboot_time_tlv->len =
+		wlan_cpu_to_le16(sizeof(MrvlIEtypes_boot_time_cfg_t) -
+				 sizeof(MrvlIEtypesHeader_t));
+	if (pmadapter->init_para.bootup_cal_ctrl == 1) {
+		pboot_time_tlv->enable = MTRUE;
+	} else {
+		pboot_time_tlv->enable = MFALSE;
+	}
+	cmd->size = wlan_cpu_to_le16(cmd->size);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
 /**
  *  @brief  This function issues adapter specific commands
  *          to initialize firmware
@@ -5076,6 +5237,17 @@ mlan_status wlan_adapter_init_cmd(pmlan_adapter pmadapter)
 	pmpriv_sta = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA);
 #endif
 
+	/* Get fw wakeup method */
+	if (pmpriv) {
+		ret = wlan_prepare_cmd(pmpriv,
+				       HostCmd_CMD_802_11_FW_WAKE_METHOD,
+				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
+		if (ret) {
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
 #ifdef SDIO
 #endif
 
@@ -5139,6 +5311,17 @@ mlan_status wlan_adapter_init_cmd(pmlan_adapter pmadapter)
 		mlan_ds_misc_mapping_policy dmcs_policy;
 		dmcs_policy.subcmd = 0;
 		dmcs_policy.mapping_policy = pmadapter->init_para.dmcs;
+
+		if (pmadapter->init_para.dmcs == 2)
+			dmcs_policy.mapping_policy = 0;
+		else {
+			dmcs_policy.mapping_policy = pmadapter->init_para.dmcs;
+			if ((pmadapter->init_para.dmcs == 1) &&
+			    (pmadapter->init_para.pref_dbc == 2))
+				dmcs_policy.mapping_policy = 2;
+			else
+				dmcs_policy.mapping_policy = 1;
+		}
 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DMCS_CONFIG,
 				       HostCmd_ACT_GEN_SET, 0, (t_void *)MNULL,
 				       &dmcs_policy);
@@ -6228,6 +6411,75 @@ mlan_status wlan_ret_mac_control(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 	return MLAN_STATUS_SUCCESS;
 }
 
+/**
+ *  @brief This function handles multi-client scheduling capabilites from FW
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param tlv          A pointer ti TLV payload from FW
+ *  @param tlv_len      length of TLV data pointed by tlv
+ *
+ *  @return             N/A
+ */
+static void wlan_setup_mclient_caps(mlan_private *pmpriv,
+				    mlan_adapter *pmadapter, void *tlv,
+				    t_u16 tlv_len)
+{
+	MrvlIEtypes_MclientFwCaps_t caps = {0};
+
+	memcpy_ext(pmadapter, &caps, tlv, sizeof(caps), tlv_len);
+
+	PRINTM(MMSG, "mclient caps: tx_ba_stream_limit %u, tx_mpdu_pps %u %u",
+	       wlan_le32_to_cpu(caps.tx_ba_stream_limit),
+	       wlan_le32_to_cpu(caps.tx_mpdu_no_amsdu_pps),
+	       wlan_le32_to_cpu(caps.tx_mpdu_with_amsdu_pps));
+
+	pmadapter->mclient_tx_supported =
+		pmadapter->init_para.mclient_scheduling;
+	pmadapter->tx_ba_stream_limit =
+		wlan_le32_to_cpu(caps.tx_ba_stream_limit);
+	pmadapter->tx_mpdu_with_amsdu_pps =
+		wlan_le32_to_cpu(caps.tx_mpdu_with_amsdu_pps);
+	pmadapter->tx_mpdu_no_amsdu_pps =
+		wlan_le32_to_cpu(caps.tx_mpdu_no_amsdu_pps);
+
+	if (pmadapter->mclient_tx_supported)
+		pmadapter->tx_ba_timeout_support = caps.tx_ba_timeout_support;
+	else
+		pmadapter->tx_ba_timeout_support = 1;
+
+	if (!pmadapter->tx_ba_timeout_support) {
+		t_u32 i;
+
+		for (i = 0; i < NELEMENTS(pmadapter->priv); ++i) {
+			mlan_private *mlan = pmadapter->priv[i];
+
+			if (mlan)
+				mlan->add_ba_param.timeout = 0;
+		}
+	}
+
+	wlan_cmd_mclient_scheduling_enable(pmpriv,
+					   pmadapter->mclient_tx_supported);
+}
+
+/**
+ *  @brief This function updates firmware extended caps
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *
+ *  @return             none
+ */
+static void wlan_update_fw_ext_cap(mlan_adapter *pmadapter)
+{
+	if (!(pmadapter->init_para.dev_cap_mask & MBIT(16)))
+		pmadapter->fw_cap_ext &= ~FW_CAPINFO_EXT_802_11AX;
+	if (!(pmadapter->init_para.dev_cap_mask & MBIT(17)))
+		pmadapter->fw_cap_ext &= ~FW_CAPINFO_EXT_6G;
+}
+
+#define DISABLE_5G_MASK (1U << 10)
+
 /**
  *  @brief This function handles the command response of get_hw_spec
  *
@@ -6256,11 +6508,18 @@ mlan_status wlan_ret_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 	MrvlIEtypes_fw_cap_info_t *fw_cap_tlv = MNULL;
 
 	MrvlIEtypes_Secure_Boot_Uuid_t *sb_uuid_tlv = MNULL;
+	t_u32 feature_mask = 0;
 
 	ENTER();
 
 	pmadapter->fw_cap_info = wlan_le32_to_cpu(hw_spec->fw_cap_info);
-	pmadapter->fw_cap_info &= pmadapter->init_para.dev_cap_mask;
+	/* read feature list from lower 16-bytes only */
+	feature_mask =
+		0xffff0000 | (pmadapter->init_para.dev_cap_mask & 0xffff);
+	if (!(feature_mask & DISABLE_5G_MASK)) {
+		feature_mask &= ~(1 << 13);
+	}
+	pmadapter->fw_cap_info &= feature_mask;
 
 	PRINTM(MMSG, "fw_cap_info=0x%x, dev_cap_mask=0x%x\n",
 	       wlan_le32_to_cpu(hw_spec->fw_cap_info),
@@ -6404,6 +6663,12 @@ mlan_status wlan_ret_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 		pmadapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
 
 	pmadapter->region_code = wlan_le16_to_cpu(hw_spec->region_code);
+#ifdef STA_SUPPORT
+	/* Set country code */
+	memcpy(pmadapter, pmadapter->country_code,
+	       wlan_11d_code_2_region(pmadapter, (t_u8)pmadapter->region_code),
+	       COUNTRY_CODE_LEN - 1);
+#endif
 	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
 		/* Use the region code to search for the index */
 		if (pmadapter->region_code == region_code_index[i])
@@ -6540,10 +6805,10 @@ mlan_status wlan_ret_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 			fw_cap_tlv = (MrvlIEtypes_fw_cap_info_t *)tlv;
 			pmadapter->fw_cap_info =
 				wlan_le32_to_cpu(fw_cap_tlv->fw_cap_info);
-			pmadapter->fw_cap_info &=
-				pmadapter->init_para.dev_cap_mask;
+			pmadapter->fw_cap_info &= feature_mask;
 			pmadapter->fw_cap_ext =
 				wlan_le32_to_cpu(fw_cap_tlv->fw_cap_ext);
+			wlan_update_fw_ext_cap(pmadapter);
 			PRINTM(MCMND, "fw_cap_info=0x%x fw_cap_ext=0x%x\n",
 			       pmadapter->fw_cap_info, pmadapter->fw_cap_ext);
 			break;
@@ -6554,6 +6819,10 @@ mlan_status wlan_ret_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 			PRINTM(MMSG, "uuid: %016llx%016llx\n",
 			       pmadapter->uuid_lo, pmadapter->uuid_hi);
 			break;
+		case TLV_TYPE_MCLIENT_FW_CAPS:
+			wlan_setup_mclient_caps(pmpriv, pmadapter, tlv,
+						tlv_len);
+			break;
 		default:
 			break;
 		}
@@ -7562,10 +7831,16 @@ mlan_status wlan_ret_802_11_rf_antenna(pmlan_private pmpriv,
 	defined(PCIE9097) || defined(SD9097) || defined(USB9097) ||            \
 	defined(SDIW624) || defined(SDAW693) || defined(PCIEAW693) ||          \
 	defined(PCIEIW624) || defined(USBIW624)
-		if (IS_CARD9098(pmadapter->card_type) ||
-		    IS_CARDIW624(pmadapter->card_type) ||
-		    IS_CARDAW693(pmadapter->card_type) ||
-		    IS_CARD9097(pmadapter->card_type)) {
+		if (IS_CARDAW693(pmadapter->card_type) &&
+		    (tx_ant_mode == RF_ANTENNA_AUTO)) {
+			PRINTM(MCMND,
+			       "user_htstream=0x%x, tx_antenna=0x%x rx_antenna=0x%x\n",
+			       pmadapter->user_htstream, tx_ant_mode,
+			       rx_ant_mode);
+		} else if (IS_CARD9098(pmadapter->card_type) ||
+			   IS_CARDIW624(pmadapter->card_type) ||
+			   IS_CARDAW693(pmadapter->card_type) ||
+			   IS_CARD9097(pmadapter->card_type)) {
 			tx_ant_mode &= 0x0303;
 			rx_ant_mode &= 0x0303;
 			/** 2G antcfg TX */
@@ -8717,6 +8992,50 @@ mlan_status wlan_ret_get_tsf(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 	return MLAN_STATUS_SUCCESS;
 }
 
+/**
+ *  @brief This function prepares command of chan region cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_chan_region_cfg(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				     t_void *pdata_buf)
+{
+	HostCmd_DS_CHAN_REGION_CFG *reg = MNULL;
+	mlan_ds_chan_attr *ca = (mlan_ds_chan_attr *)pdata_buf;
+	MrvlIEtypesHeader_t *tlv = MNULL;
+	t_u32 buf_size = 0;
+
+	ENTER();
+
+	reg = (HostCmd_DS_CHAN_REGION_CFG *)&cmd->params.reg_cfg;
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CHAN_REGION_CFG);
+	cmd->size =
+		wlan_cpu_to_le16(sizeof(HostCmd_DS_CHAN_REGION_CFG) + S_DS_GEN);
+	reg->action = wlan_cpu_to_le16(cmd_action);
+
+	buf_size = MRVDRV_SIZE_OF_CMD_BUFFER - cmd->size;
+	if (ca && (cmd_action == HostCmd_ACT_GEN_SET)) {
+		tlv = (MrvlIEtypesHeader_t *)&reg->tlv_buffer;
+		tlv->type = wlan_cpu_to_le16(TLV_TYPE_CHAN_ATTR_CFG);
+		ca->data_len =
+			MIN(ca->data_len, MIN(sizeof(ca->chan_attr), buf_size));
+		tlv->len = wlan_cpu_to_le16(ca->data_len);
+		memcpy_ext(pmpriv->adapter,
+			   (t_u8 *)tlv + sizeof(MrvlIEtypesHeader_t),
+			   (t_u8 *)ca->chan_attr, ca->data_len, buf_size);
+		cmd->size += wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
+					      ca->data_len);
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
 /**
  *  @brief This function handles the command response of chan_region_cfg
  *
@@ -8749,16 +9068,20 @@ mlan_status wlan_ret_chan_region_cfg(pmlan_private pmpriv,
 
 	action = wlan_le16_to_cpu(reg->action);
 	if (action != HostCmd_ACT_GEN_GET) {
-		ret = MLAN_STATUS_FAILURE;
 		goto done;
 	}
 
-	tlv_buf = (t_u8 *)reg + sizeof(*reg);
+	tlv_buf = (t_u8 *)&resp->params.reg_cfg.tlv_buffer;
+
 	if (resp->size > (S_DS_GEN + sizeof(*reg))) {
 		tlv_buf_left = resp->size - S_DS_GEN - sizeof(*reg);
 	} else {
 		PRINTM(MERROR, "Region size calculation ERROR.\n");
 	}
+	if (!tlv_buf || !tlv_buf_left) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
 
 	/* Add FW cfp tables and region info */
 	wlan_add_fw_cfp_tables(pmpriv, tlv_buf, tlv_buf_left);
@@ -10379,7 +10702,7 @@ mlan_status wlan_ret_set_get_low_power_mode_cfg(pmlan_private pmpriv,
 }
 /**
  *  @brief This function handles the command response of
- *  packet aggregation
+ *  CHAN_TRPC setting
  *
  *  @param pmpriv       A pointer to mlan_private structure
  *  @param resp         A pointer to HostCmd_DS_COMMAND
@@ -10572,6 +10895,122 @@ mlan_status wlan_ret_range_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 	return MLAN_STATUS_SUCCESS;
 }
 
+/**
+ *  @brief This function prepares command of TSP config.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_tsp_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+				t_u16 cmd_action, t_void *pdata_buf)
+{
+	HostCmd_DS_TSP_CFG *tsp_config = &cmd->params.tsp_cfg;
+	mlan_ds_tsp_cfg *cfg = (mlan_ds_tsp_cfg *)pdata_buf;
+	t_u8 rfu = 0;
+	t_u8 rpath = 0;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TSP_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_TSP_CFG) + S_DS_GEN);
+	tsp_config->action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		tsp_config->enable = wlan_cpu_to_le16(cfg->enable);
+		if (tsp_config->enable == 0) {
+			cmd->size = wlan_cpu_to_le16(
+				sizeof(tsp_config->action) +
+				sizeof(tsp_config->enable) + S_DS_GEN);
+		} else {
+			tsp_config->backoff = wlan_cpu_to_le32(cfg->backoff);
+			tsp_config->high_thrshld =
+				wlan_cpu_to_le32(cfg->high_thrshld);
+			tsp_config->low_thrshld =
+				wlan_cpu_to_le32(cfg->low_thrshld);
+			tsp_config->reg_cau_val =
+				wlan_cpu_to_le32(cfg->reg_cau_val);
+			tsp_config->duty_cyc_step =
+				wlan_cpu_to_le32(cfg->duty_cyc_step);
+			tsp_config->duty_cyc_min =
+				wlan_cpu_to_le32(cfg->duty_cyc_min);
+			tsp_config->high_thrshld_temp =
+				wlan_cpu_to_le32(cfg->high_thrshld_temp);
+			tsp_config->low_thrshld_temp =
+				wlan_cpu_to_le32(cfg->low_thrshld_temp);
+
+			for (rfu = 0; rfu < MAX_RFUS; rfu++) {
+				for (rpath = 0; rpath < MAX_PATHS; rpath++) {
+					tsp_config->reg_rfu_val
+						[rfu][rpath] = wlan_cpu_to_le32(
+						cfg->reg_rfu_temp[rfu][rpath]);
+				}
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of TSP config.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND structure
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req buf
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_tsp_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+				mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_TSP_CFG *tsp_config = &resp->params.tsp_cfg;
+	mlan_ds_misc_cfg *cfg = MNULL;
+	t_u8 rfu = 0;
+	t_u8 rpath = 0;
+	ENTER();
+	if (pioctl_buf) {
+		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+
+		if (wlan_le16_to_cpu(tsp_config->action) ==
+		    HostCmd_ACT_GEN_GET) {
+			cfg->param.tsp_cfg.enable =
+				wlan_le16_to_cpu(tsp_config->enable);
+			cfg->param.tsp_cfg.backoff =
+				wlan_le32_to_cpu(tsp_config->backoff);
+			cfg->param.tsp_cfg.high_thrshld =
+				wlan_le32_to_cpu(tsp_config->high_thrshld);
+			cfg->param.tsp_cfg.low_thrshld =
+				wlan_le32_to_cpu(tsp_config->low_thrshld);
+			cfg->param.tsp_cfg.reg_cau_val =
+				wlan_le32_to_cpu(tsp_config->reg_cau_val);
+			cfg->param.tsp_cfg.duty_cyc_step =
+				wlan_le32_to_cpu(tsp_config->duty_cyc_step);
+			cfg->param.tsp_cfg.duty_cyc_min =
+				wlan_le32_to_cpu(tsp_config->duty_cyc_min);
+			cfg->param.tsp_cfg.high_thrshld_temp =
+				wlan_le32_to_cpu(tsp_config->high_thrshld_temp);
+			cfg->param.tsp_cfg.low_thrshld_temp =
+				wlan_le32_to_cpu(tsp_config->low_thrshld_temp);
+
+			for (rfu = 0; rfu < MAX_RFUS; rfu++) {
+				for (rpath = 0; rpath < MAX_PATHS; rpath++) {
+					cfg->param.tsp_cfg
+						.reg_rfu_temp[rfu][rpath] =
+						wlan_le32_to_cpu(
+							tsp_config->reg_rfu_val
+								[rfu][rpath]);
+				}
+			}
+		}
+	}
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
 /**
  *  @brief This function prepares command of TX_FRAME
  *
@@ -10729,3 +11168,119 @@ mlan_status wlan_cmd_edmac_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
 	LEAVE();
 	return MLAN_STATUS_SUCCESS;
 }
+
+/**
+ *  @brief This function send command to FW to configure multi-client scheduling
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param enable      Enable/Disable multi-client scheduling
+ *
+ *  @return            MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_mclient_scheduling_enable(pmlan_private pmpriv,
+					       t_bool enable)
+{
+	HostCmd_MCLIENT_SCHEDULE_CFG cfg;
+
+	memset(pmpriv->adapter, &cfg, 0xff, sizeof(cfg));
+
+	cfg.action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+	cfg.mclient_enable = !!enable;
+	cfg.ps_mode_change_report = !!enable;
+
+	return wlan_prepare_cmd(pmpriv, HostCmd_CMD_MCLIENT_SCHEDULE_CFG,
+				HostCmd_ACT_GEN_SET, 0, MNULL, &cfg);
+}
+
+/**
+ *  @brief This function prepares command to configure multi-client scheduling
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action  Action: GET or SET
+ *  @param pdata_buf   A pointer to data buffer
+ *
+ *  @return            MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_mclient_scheduling_cfg(pmlan_private pmpriv,
+					    HostCmd_DS_COMMAND *cmd,
+					    t_u16 cmd_action, t_pvoid pdata_buf)
+{
+	HostCmd_MCLIENT_SCHEDULE_CFG *req = pdata_buf;
+	HostCmd_MCLIENT_SCHEDULE_CFG *mclient_cfg = &cmd->params.mclient_cfg;
+	const t_u16 cmd_size = sizeof(*mclient_cfg);
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MCLIENT_SCHEDULE_CFG);
+	cmd->size = wlan_cpu_to_le16(cmd_size + S_DS_GEN);
+
+	memcpy_ext(pmpriv->adapter, mclient_cfg, req, cmd_size, cmd_size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command to query TX rate
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action  Action: GET or SET
+ *  @param pdata_buf   A pointer to data buffer
+ *
+ *  @return            MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_sta_tx_rate_req(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				     t_pvoid pdata_buf)
+{
+	HostCmd_CMD_802_11_STA_TX_RATE *req = pdata_buf;
+	HostCmd_CMD_802_11_STA_TX_RATE *sta_tx_rate_req =
+		&cmd->params.sta_rx_rate;
+	const t_u16 cmd_size = MIN(sizeof(req->entry),
+				   (sizeof(req->entry[0]) * req->num_entries));
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_PEER_TX_RATE_QUERY);
+	cmd->size = wlan_cpu_to_le16(cmd_size + S_DS_GEN);
+
+	memcpy_ext(pmpriv->adapter, sta_tx_rate_req, req, cmd_size, cmd_size);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles HostCmd_CMD_PEER_TX_RATE_QUERY command response
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param resp        A pointer to command response
+ *  @param pioctl_buf  A pointer to mlan_ioctl_req structure
+ *
+ *  @return            MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_sta_tx_rate(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+				 mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_CMD_802_11_STA_TX_RATE *info = &resp->params.sta_rx_rate;
+	int i;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	const t_s32 entry_size = sizeof(info->entry[0]);
+	t_s32 size = resp->size - S_DS_GEN;
+
+	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
+					    pmpriv->wmm.ra_list_spinlock);
+
+	for (i = 0; i < NELEMENTS(info->entry) && size >= entry_size;
+	     i++, size -= entry_size) {
+		wlan_wmm_update_sta_tx_rate(pmpriv, info->entry[i].sta_mac,
+					    &info->entry[i].rate);
+	}
+
+	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
+					      pmpriv->wmm.ra_list_spinlock);
+
+	return MLAN_STATUS_SUCCESS;
+}
diff --git a/mlan/mlan_decl.h b/mlan/mlan_decl.h
index c55d7e0..d1367d6 100644
--- a/mlan/mlan_decl.h
+++ b/mlan/mlan_decl.h
@@ -206,6 +206,8 @@ typedef t_s32 t_sval;
 #define MLAN_RATE_INDEX_MCS4 4
 /** Rate index for MCS 7 */
 #define MLAN_RATE_INDEX_MCS7 7
+/** Rate index for MCS 8 */
+#define MLAN_RATE_INDEX_MCS8 8
 /** Rate index for MCS 9 */
 #define MLAN_RATE_INDEX_MCS9 9
 /** Rate index for MCS11 */
@@ -395,14 +397,17 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_TYPE_IW624 0x0b
 /** Black bird card type */
 #define CARD_TYPE_AW693 0x0c
-/** IW615 card type */
-#define CARD_TYPE_IW615 0x0d
+/** IW610 card type */
+#define CARD_TYPE_IW610 0x0d
 
 /** 9098 A0 reverion num */
 #define CHIP_9098_REV_A0 1
 #define CHIP_9098_REV_A1 2
 /** 9097 CHIP REV */
 #define CHIP_9097_REV_B0 1
+/** Blackbird reverion num */
+#define CHIP_AW693_REV_A0 1
+#define CHIP_AW693_REV_A1 2
 
 #define INTF_MASK 0xff
 #define CARD_TYPE_MASK 0xff
@@ -432,8 +437,8 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_TYPE_SDIW624 (CARD_TYPE_IW624 | (INTF_SD << 8))
 /** SD_IW624 card type */
 #define CARD_TYPE_SDAW693 (CARD_TYPE_AW693 | (INTF_SD << 8))
-/** SD_IW615 card type */
-#define CARD_TYPE_SDIW615 (CARD_TYPE_IW615 | (INTF_SD << 8))
+/** SD_IW610 card type */
+#define CARD_TYPE_SDIW610 (CARD_TYPE_IW610 | (INTF_SD << 8))
 
 #define IS_SD8887(ct) (CARD_TYPE_SD8887 == (ct))
 #define IS_SD8897(ct) (CARD_TYPE_SD8897 == (ct))
@@ -447,7 +452,7 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define IS_SD8801(ct) (CARD_TYPE_SD8801 == (ct))
 #define IS_SDIW624(ct) (CARD_TYPE_SDIW624 == (ct))
 #define IS_SDAW693(ct) (CARD_TYPE_SDAW693 == (ct))
-#define IS_SDIW615(ct) (CARD_TYPE_SDIW615 == (ct))
+#define IS_SDIW610(ct) (CARD_TYPE_SDIW610 == (ct))
 
 /** SD8887 Card */
 #define CARD_SD8887 "SD8887"
@@ -473,8 +478,8 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_SDIW624 "SDIW624"
 /** SDAW693 Card */
 #define CARD_SDAW693 "SDAW693"
-/** SDIW615 Card */
-#define CARD_SDIW615 "SDIW615"
+/** SDIW610 Card */
+#define CARD_SDIW610 "SDIW610"
 #endif
 
 #ifdef PCIE
@@ -533,8 +538,8 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_TYPE_USB9097 (CARD_TYPE_9097 | (INTF_USB << 8))
 /** USBIW624 card type */
 #define CARD_TYPE_USBIW624 (CARD_TYPE_IW624 | (INTF_USB << 8))
-/** USBIW615 card type */
-#define CARD_TYPE_USBIW615 (CARD_TYPE_IW615 | (INTF_USB << 8))
+/** USBIW610 card type */
+#define CARD_TYPE_USBIW610 (CARD_TYPE_IW610 | (INTF_USB << 8))
 
 #define IS_USB8801(ct) (CARD_TYPE_USB8801 == (ct))
 #define IS_USB8897(ct) (CARD_TYPE_USB8897 == (ct))
@@ -543,7 +548,7 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define IS_USB9098(ct) (CARD_TYPE_USB9098 == (ct))
 #define IS_USB9097(ct) (CARD_TYPE_USB9097 == (ct))
 #define IS_USBIW624(ct) (CARD_TYPE_USBIW624 == (ct))
-#define IS_USBIW615(ct) (CARD_TYPE_USBIW615 == (ct))
+#define IS_USBIW610(ct) (CARD_TYPE_USBIW610 == (ct))
 
 /** USB8801 Card */
 #define CARD_USB8801 "USB8801"
@@ -559,14 +564,15 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_USB9097 "USBIW620"
 /** USBIW624 Card */
 #define CARD_USBIW624 "USBIW624"
-/** USBIW615 Card */
-#define CARD_USBIW615 "USBIW615"
+/** USBIW610 Card */
+#define CARD_USBIW610 "USBIW610"
 #endif
 
 #define IS_CARD8801(ct) (CARD_TYPE_8801 == ((ct)&0xf))
 #define IS_CARD8887(ct) (CARD_TYPE_8887 == ((ct)&0xf))
 #define IS_CARD8897(ct) (CARD_TYPE_8897 == ((ct)&0xf))
 #define IS_CARD8977(ct) (CARD_TYPE_8977 == ((ct)&0xf))
+#define IS_CARD8978(ct) (CARD_TYPE_8978 == ((ct)&0xf))
 #define IS_CARD8997(ct) (CARD_TYPE_8997 == ((ct)&0xf))
 #define IS_CARD8987(ct) (CARD_TYPE_8987 == ((ct)&0xf))
 #define IS_CARD9098(ct) (CARD_TYPE_9098 == ((ct)&0xf))
@@ -574,7 +580,7 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define IS_CARD9177(ct) (CARD_TYPE_9177 == ((ct)&0xf))
 #define IS_CARDIW624(ct) (CARD_TYPE_IW624 == ((ct)&0xf))
 #define IS_CARDAW693(ct) (CARD_TYPE_AW693 == ((ct)&0xf))
-#define IS_CARDIW615(ct) (CARD_TYPE_IW615 == ((ct)&0xf))
+#define IS_CARDIW610(ct) (CARD_TYPE_IW610 == ((ct)&0xf))
 
 typedef struct _card_type_entry {
 	t_u16 card_type;
@@ -648,6 +654,8 @@ typedef enum {
 
 #define MLAN_BUF_FLAG_MC_AGGR_PKT MBIT(17)
 
+#define MLAN_BUF_FLAG_TCP_PKT MBIT(18)
+
 #define MLAN_BUF_FLAG_LLDE_PKT_FILTER MBIT(19)
 
 #ifdef DEBUG_LEVEL1
@@ -660,8 +668,8 @@ typedef enum {
 #define MEVENT MBIT(5)
 #define MINTR MBIT(6)
 #define MIOCTL MBIT(7)
-
 #define MREG_D MBIT(9)
+#define MREG MBIT(10)
 
 #define MMPA_D MBIT(15)
 #define MDAT_D MBIT(16)
@@ -670,7 +678,7 @@ typedef enum {
 #define MFW_D MBIT(19)
 #define MIF_D MBIT(20)
 #define MFWDP_D MBIT(21)
-
+#define MSCH_D MBIT(22)
 #define MENTRY MBIT(28)
 #define MWARN MBIT(29)
 #define MINFO MBIT(30)
@@ -1630,7 +1638,7 @@ typedef MLAN_PACK_START struct _tdls_each_link_status {
 	/** Key Length */
 	t_u8 key_length;
 	/** actual key */
-	t_u8 key[1];
+	t_u8 key[];
 } MLAN_PACK_END tdls_each_link_status;
 
 /** TDLS configuration data */
@@ -1757,7 +1765,7 @@ typedef MLAN_PACK_START struct _tdls_all_config {
 			/** number of links */
 			t_u8 active_links;
 			/** structure for link status */
-			tdls_each_link_status link_stats[1];
+			tdls_each_link_status link_stats[];
 		} MLAN_PACK_END tdls_link_status_resp;
 
 	} u;
@@ -2596,6 +2604,7 @@ typedef struct _mlan_callbacks {
 				     t_u8 antenna);
 	t_void (*moal_updata_peer_signal)(t_void *pmoal, t_u32 bss_index,
 					  t_u8 *peer_addr, t_s8 snr, t_s8 nflr);
+	mlan_status (*moal_get_host_time_ns)(t_u64 *time);
 	t_u64 (*moal_do_div)(t_u64 num, t_u32 base);
 	void (*moal_tp_accounting)(t_void *pmoal, t_void *buf,
 				   t_u32 drop_point);
@@ -2694,6 +2703,8 @@ typedef struct _mlan_device {
 #endif
 	/** Auto deep sleep */
 	t_u32 auto_ds;
+	/** Boot Time Config */
+	t_u32 bootup_cal_ctrl;
 	/** IEEE PS mode */
 	t_u32 ps_mode;
 	/** Max Tx buffer size */
@@ -2745,6 +2756,8 @@ typedef struct _mlan_device {
 	t_u8 uap_max_sta;
 	/** wacp mode */
 	t_u8 wacp_mode;
+	/** custom Fw data */
+	t_u32 fw_data_cfg;
 	/** drv mode */
 	t_u32 drv_mode;
 	/** dfs w53 cfg */
@@ -2763,8 +2776,12 @@ typedef struct _mlan_device {
 	t_u32 antcfg;
 	/** dmcs */
 	t_u8 dmcs;
+	t_u8 pref_dbc;
 	t_u32 reject_addba_req;
 
+	t_u32 max_tx_pending;
+	t_u16 tx_budget;
+	t_u8 mclient_scheduling;
 } mlan_device, *pmlan_device;
 
 /** MLAN API function prototype */
diff --git a/mlan/mlan_event_ids.h b/mlan/mlan_event_ids.h
index 074e787..3808778 100644
--- a/mlan/mlan_event_ids.h
+++ b/mlan/mlan_event_ids.h
@@ -209,5 +209,9 @@ ENUM_ELEMENT(EVENT_DUMMY_HOST_WAKEUP_SIGNAL, 0x0001),
 	/** Event ID: Bulk Tx status */
 	ENUM_ELEMENT(EVENT_TX_STATUS_BULK_REPORT, 0x00A2),
 
+	/** Event ID: peer's power save mode change */
+	ENUM_ELEMENT(EVENT_PEER_PS_MODE_CHANGE, 0x00A3),
+
+	ENUM_ELEMENT(EVENT_CHAN_SWITCH_TO_6G_BLOCK, 0x00A4),
 	/* Always keep this last */
 	ENUM_ELEMENT_LAST(__HostEvent_Last)
diff --git a/mlan/mlan_fw.h b/mlan/mlan_fw.h
index 7c623b4..6ce0451 100644
--- a/mlan/mlan_fw.h
+++ b/mlan/mlan_fw.h
@@ -156,6 +156,30 @@ extern t_u8 SupportedRates_BG[BG_SUPPORTED_RATES];
 extern t_u8 SupportedRates_A[A_SUPPORTED_RATES];
 extern t_u8 SupportedRates_N[N_SUPPORTED_RATES];
 
+#define MAX_FW_DATA_BLOCK 8
+#if defined(USB8978) || defined(SD8978)
+/** Fw custom data */
+#define FW_DATA_FW_REMAP_CONFIG_LEN 44
+extern t_u8 fw_data_fw_remap_config[FW_DATA_FW_REMAP_CONFIG_LEN];
+#endif
+#if defined(USB8978)
+#define FW_DATA_USB_BULK_EP_LEN 36
+extern t_u8 fw_data_usb_bulk_ep[FW_DATA_USB_BULK_EP_LEN];
+#endif
+#if defined(USB8978) || defined(SD8978)
+#define FW_DATA_DPD_CURRENT_OPT_LEN 36
+extern t_u8 fw_data_dpd_current_opt[FW_DATA_DPD_CURRENT_OPT_LEN];
+#endif
+
+/** Firmware wakeup method : Unchanged */
+#define WAKEUP_FW_UNCHANGED 0
+/** Firmware wakeup method : Through interface */
+#define WAKEUP_FW_THRU_INTERFACE 1
+/** Firmware wakeup method : Through GPIO*/
+#define WAKEUP_FW_THRU_GPIO 2
+/** Default value of GPIO */
+#define DEF_WAKEUP_FW_GPIO 0
+
 /** Default auto deep sleep mode */
 #define DEFAULT_AUTO_DS_MODE MTRUE
 /** Default power save mode */
@@ -820,12 +844,15 @@ typedef enum _WLAN_802_11_WEP_STATUS {
 #define MOD_CLASS_HT 0x08
 /** Modulation class for VHT Rates */
 #define MOD_CLASS_VHT 0x09
-/** HT bandwidth 20 MHz */
-#define HT_BW_20 0
-/** HT bandwidth 40 MHz */
-#define HT_BW_40 1
-/** HT bandwidth 80 MHz */
-#define HT_BW_80 2
+/** Modulation class for HE Rates */
+#define MOD_CLASS_HE 0x0A
+
+/** HT/VHT/HE bandwidth 20 MHz */
+#define BW_20 0
+/** HT/VHT/HE bandwidth 40 MHz */
+#define BW_40 1
+/** HT/VHT/HE bandwidth 80 MHz */
+#define BW_80 2
 
 /** Firmware Host Command ID Constants */
 
@@ -1154,6 +1181,7 @@ typedef enum _ENH_PS_MODES {
 #define HostCmd_ACT_GEN_REMOVE 0x0004
 /** General purpose action : Reset */
 #define HostCmd_ACT_GEN_RESET 0x0005
+
 /** Host command action : Set Rx */
 #define HostCmd_ACT_SET_RX 0x0001
 /** Host command action : Set Tx */
@@ -2474,6 +2502,16 @@ typedef MLAN_PACK_START struct _filter_entry {
 	t_u32 ipv4_addr;
 } MLAN_PACK_END filter_entry;
 
+#define NUM_EVT_MASK_BITMAP 10
+typedef struct _HostCmd_DS_EVENT_MASK_CFG {
+	/** Get / Set action*/
+	t_u8 action;
+	/** feature enabled or disabled */
+	t_u8 enabled;
+	/** Bit map of the masked events. 1 - masked, 0 - allowed */
+	t_u32 events_bitmap[NUM_EVT_MASK_BITMAP];
+} MLAN_PACK_END HostCmd_DS_EVENT_MASK_CFG;
+
 typedef MLAN_PACK_START struct _HostCmd_DS_MEF_CFG {
 	/** Criteria */
 	t_u32 criteria;
@@ -3192,6 +3230,8 @@ typedef MLAN_PACK_START struct _HostCmd_DS_802_11_GET_LOG {
 	t_u32 gdma_abort_cnt;
 	/** Rx Reset MAC Count */
 	t_u32 g_reset_rx_mac_cnt;
+	/** SDMA FSM stuck Count*/
+	t_u32 SdmaStuckCnt;
 	// Ownership error counters
 	/*Error Ownership error count*/
 	t_u32 dwCtlErrCnt;
@@ -3521,6 +3561,15 @@ typedef MLAN_PACK_START struct _HostCmd_DS_802_11_HS_CFG_ENH {
 	} params;
 } MLAN_PACK_END HostCmd_DS_802_11_HS_CFG_ENH;
 
+/** HostCmd_CMD_802_11_FW_WAKE_METHOD */
+typedef MLAN_PACK_START struct _HostCmd_DS_802_11_FW_WAKEUP_METHOD {
+	/** Action */
+	t_u16 action;
+	/** Method */
+	t_u16 method;
+	t_u8 tlv_buf[];
+} MLAN_PACK_END HostCmd_DS_802_11_FW_WAKEUP_METHOD;
+
 /** HostCmd_CMD_802_11_ROBUSTCOEX */
 typedef MLAN_PACK_START struct _HostCmd_DS_802_11_ROBUSTCOEX {
 	/** Action */
@@ -3723,6 +3772,25 @@ typedef MLAN_PACK_START struct _HostCmd_DS_TX_RATE_CFG {
 	t_u8 tlv_buf[];
 } MLAN_PACK_END HostCmd_DS_TX_RATE_CFG;
 
+/** HostCmd_DS_FUNC_INIT */
+typedef MLAN_PACK_START struct _HostCmd_DS_FUNC_INIT {
+	/* MrvlIEtypes_boot_time_cfg_t */
+	t_u8 tlv_buf[0];
+} MLAN_PACK_END HostCmd_DS_FUNC_INIT;
+
+/** BootTimeCfg TLV */
+typedef MLAN_PACK_START struct _MrvlIEtypes_boot_time_cfg_t {
+	/** Header type */
+	t_u16 type;
+	/** Header length */
+	t_u16 len;
+	/* enable: 1: enable boot time optimization 0: disable boot time
+	 * optimization */
+	t_u8 enable;
+	/* reserved */
+	t_u8 reserve[3];
+} MLAN_PACK_END MrvlIEtypes_boot_time_cfg_t, *pMrvlIEtypes_boot_time_cfg_t;
+
 /** Power_Group_t */
 typedef MLAN_PACK_START struct _Power_Group_t {
 	/** Modulation Class */
@@ -3925,6 +3993,31 @@ typedef MLAN_PACK_START struct _HostCmd_DS_CROSS_CHIP_SYNCH {
 	t_u32 init_tsf_high;
 } MLAN_PACK_END HostCmd_DS_CROSS_CHIP_SYNCH;
 
+typedef MLAN_PACK_START struct _HostCmd_DS_TSP_CFG {
+	/** TSP config action 0-GET, 1-SET */
+	t_u16 action;
+	/** TSP enable/disable tsp algothrim */
+	t_u16 enable;
+	/** TSP config power backoff */
+	t_s32 backoff;
+	/** TSP config high threshold */
+	t_s32 high_thrshld;
+	/** TSP config low threshold */
+	t_s32 low_thrshld;
+	/** TSP config DUTY_CYC_STEP */
+	t_s32 duty_cyc_step;
+	/** TSP config DUTY_CYC_MIN */
+	t_s32 duty_cyc_min;
+	/** TSP config HIGH_THRESHOLD_TEMP */
+	t_s32 high_thrshld_temp;
+	/** TSP config LOW_THRESHOLD_TEMP */
+	t_s32 low_thrshld_temp;
+	/** TSP CAU TSEN read value */
+	t_s32 reg_cau_val;
+	/** TSP RFU read values */
+	t_s32 reg_rfu_val[MAX_RFUS][MAX_PATHS];
+} MLAN_PACK_END HostCmd_DS_TSP_CFG;
+
 MLAN_PACK_START struct coalesce_filt_field_param {
 	t_u8 operation;
 	t_u8 operand_len;
@@ -4444,8 +4537,8 @@ typedef struct MLAN_PACK_START _hostcmd_twt_setup {
 	t_u8 twt_request;
 	/** TWT Setup State. Set to 0 by driver, filled by FW in response*/
 	t_u8 twt_setup_state;
-	/** Reserved, set to 0. */
-	t_u8 reserved[2];
+	/** TWT link lost timeout threshold */
+	t_u16 bcnMiss_threshold;
 } MLAN_PACK_END hostcmd_twt_setup, *phostcmd_twt_setup;
 
 /** Type definition of hostcmd_twt_teardown */
@@ -5164,6 +5257,8 @@ typedef MLAN_PACK_START struct _HostCmd_DS_VERSION_EXT {
 typedef MLAN_PACK_START struct _HostCmd_DS_CHAN_REGION_CFG {
 	/** Action */
 	t_u16 action;
+	/** TLV buffer */
+	t_u8 tlv_buffer[1];
 } MLAN_PACK_END HostCmd_DS_CHAN_REGION_CFG;
 
 /** HostCmd_DS_REGION_POWER_CFG */
@@ -6745,6 +6840,20 @@ typedef MLAN_PACK_START struct _dual_desc_buf {
 	t_u64 paddr;
 } MLAN_PACK_END adma_dual_desc_buf, *padma_dual_desc_buf;
 
+/** PCIE ADMA configuration */
+typedef MLAN_PACK_START struct _HostCmd_DS_PCIE_ADMA_INIT {
+	/* tx adma ring size */
+	t_u16 tx_ring_size;
+	/* rx adma ring size */
+	t_u16 rx_ring_size;
+	/* event adma ring size */
+	t_u16 evt_ring_size;
+	/* interrupt mode: 0-legacy 1-msi 2-msix */
+	t_u8 int_mode;
+	/** reserved */
+	t_u8 reserved;
+} HostCmd_DS_PCIE_ADMA_INIT;
+
 #if defined(PCIE8997) || defined(PCIE8897)
 /** PCIE ring buffer description for DATA */
 typedef MLAN_PACK_START struct _mlan_pcie_data_buf {
@@ -7296,6 +7405,52 @@ typedef MLAN_PACK_START struct _HostCmd_DS_EDMAC_CFG {
 	t_u32 ed_bitmap_txq_lock;
 } MLAN_PACK_END HostCmd_DS_EDMAC_CFG;
 
+/* Auth, Assoc Timeout configuration: HostCmd_DS_AUTH_ASSOC_TIMEOUT_CFG */
+typedef MLAN_PACK_START struct _HostCmd_DS_AUTH_ASSOC_TIMEOUT_CFG {
+	/** Action */
+	t_u16 action;
+	/** auth timeout */
+	t_u16 auth_timeout;
+	/** Auth retry timeout if received ack */
+	t_u16 auth_retry_timeout_if_ack;
+	/** Auth retry timeout if ack is not received */
+	t_u16 auth_retry_timeout_if_no_ack;
+	/** assoc timeout */
+	t_u16 assoc_timeout;
+	/** reassoc timeout */
+	t_u16 reassoc_timeout;
+	/** assoc/reassoc frame retry timeout if ack received */
+	t_u16 retry_timeout;
+} MLAN_PACK_END HostCmd_DS_AUTH_ASSOC_TIMEOUT_CFG;
+
+/* maximum number of STAs HostCmd_CMD_802_11_STA_TX_RATE can have */
+enum { MAX_STA_IN_TX_RATE_REQ = 32 };
+
+/** HostCmd_CMD_802_11_STA_TX_RATE */
+typedef MLAN_PACK_START struct _HostCmd_CMD_802_11_STA_TX_RATE {
+	struct {
+		/** STA`s MAC */
+		t_u8 sta_mac[MLAN_MAC_ADDR_LENGTH];
+		/** TX rate */
+		HostCmd_TX_RATE_QUERY rate;
+	} entry[MAX_STA_IN_TX_RATE_REQ];
+
+	/** actual number of entries in array */
+	t_u16 num_entries;
+} HostCmd_CMD_802_11_STA_TX_RATE;
+
+/** HostCmd_MCLIENT_SCHEDULE_CFG */
+typedef MLAN_PACK_START struct _HostCmd_MCLIENT_SCHEDULE_CFG {
+	/** action - get/set */
+	t_u16 action;
+
+	/** enable multi-client scheduliing */
+	t_u8 mclient_enable;
+
+	/** enable PS mode change reporting */
+	t_u8 ps_mode_change_report;
+} HostCmd_MCLIENT_SCHEDULE_CFG;
+
 /** HostCmd_DS_COMMAND */
 typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND {
 	/** Command Header : Command */
@@ -7353,9 +7508,12 @@ typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND {
 		/** RF antenna */
 		HostCmd_DS_802_11_RF_ANTENNA antenna;
 
+		/** Function Init */
+		HostCmd_DS_FUNC_INIT func_init;
 		/** Enhanced power save command */
 		HostCmd_DS_802_11_PS_MODE_ENH psmode_enh;
 		HostCmd_DS_802_11_HS_CFG_ENH opt_hs_cfg;
+		HostCmd_DS_802_11_FW_WAKEUP_METHOD fwwakeupmethod;
 		/** Scan */
 		HostCmd_DS_802_11_SCAN scan;
 		/** Extended Scan */
@@ -7487,6 +7645,9 @@ typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND {
 #if defined(PCIE8997) || defined(PCIE8897)
 		HostCmd_DS_PCIE_HOST_BUF_DETAILS pcie_host_spec;
 #endif
+#endif
+#if defined(PCIE)
+		HostCmd_DS_PCIE_ADMA_INIT pcie_adma_config;
 #endif
 		HostCmd_DS_REMAIN_ON_CHANNEL remain_on_chan;
 #ifdef WIFI_DIRECT_SUPPORT
@@ -7564,6 +7725,7 @@ typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND {
 		struct mfg_Cmd_HE_TBTx_t mfg_he_power;
 		mfg_Cmd_IEEEtypes_CtlBasicTrigHdr_t mfg_tx_trigger_config;
 		mfg_cmd_otp_mac_addr_rd_wr_t mfg_otp_mac_addr_rd_wr;
+		mfg_cmd_otp_cal_data_rd_wr_t mfg_otp_cal_data_rd_wr;
 		HostCmd_DS_CMD_ARB_CONFIG arb_cfg;
 		HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG dot11mc_unassoc_ftm_cfg;
 		HostCmd_DS_HAL_PHY_CFG hal_phy_cfg_params;
@@ -7572,15 +7734,21 @@ typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND {
 		HostCmd_DS_STATS stats;
 		HostCmd_DS_GET_CH_LOAD ch_load;
 		HostCmd_DS_CROSS_CHIP_SYNCH cross_chip_synch;
+		HostCmd_DS_TSP_CFG tsp_cfg;
 		HostCmd_DS_80211_TX_FRAME tx_frame;
 
 		HostCmd_DS_EDMAC_CFG ed_mac_cfg;
 		HostCmd_gpio_cfg_ops gpio_cfg_ops;
 
+		HostCmd_CMD_802_11_STA_TX_RATE sta_rx_rate;
+		HostCmd_MCLIENT_SCHEDULE_CFG mclient_cfg;
+
 		/** WMM HOST ADDTS */
 		HostCmd_DS_WMM_HOST_ADDTS_REQ host_add_ts;
 		/** WMM HOST DELTS */
 		HostCmd_DS_WMM_HOST_DELTS_REQ host_del_ts;
+		/** Auth, (Re)Assoc timeout configuration */
+		HostCmd_DS_AUTH_ASSOC_TIMEOUT_CFG auth_assoc_cfg;
 	} params;
 } MLAN_PACK_END HostCmd_DS_COMMAND, *pHostCmd_DS_COMMAND;
 
@@ -7617,6 +7785,11 @@ typedef MLAN_PACK_START struct _MrvlIEtypes_Secure_Boot_Uuid_t {
 	t_u64 uuid_hi;
 } MLAN_PACK_END MrvlIEtypes_Secure_Boot_Uuid_t;
 
+typedef MLAN_PACK_START struct _MrvlIEtypes_PsStaStatus_t {
+	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
+	t_u8 sleep;
+} MLAN_PACK_END MrvlIEtypes_PsStaStatus_t;
+
 /** req host side download vdll block */
 #define VDLL_IND_TYPE_REQ 0
 /** notify vdll start offset in firmware image */
@@ -7642,6 +7815,36 @@ typedef MLAN_PACK_START struct _vdll_ind {
 	t_u16 block_len;
 } MLAN_PACK_END vdll_ind, *pvdll_ind;
 
+typedef MLAN_PACK_START struct _MrvlIEtypes_MclientFwCaps_t {
+	/** Header */
+	MrvlIEtypesHeader_t header;
+
+	/* max number of supported TX BA streams */
+	t_u32 tx_ba_stream_limit;
+
+	/* estimated FW MPDU PPS performance */
+	t_u32 tx_mpdu_with_amsdu_pps;
+	t_u32 tx_mpdu_no_amsdu_pps;
+
+	/* timeout support for TX BA */
+	t_u8 tx_ba_timeout_support;
+
+	t_u8 __padding[3];
+} MLAN_PACK_END MrvlIEtypes_MclientFwCaps_t;
+
+/** Fw custom data structure */
+typedef struct MLAN_PACK_START _fw_data_t {
+	t_u8 *fw_data_buffer;
+	t_u8 fw_data_buffer_len;
+} MLAN_PACK_END fw_data_t;
+
+typedef enum _BLOCK_6G_CHAN_SWITCH_REASON {
+	BLOCK_6G_CHAN_SWITCH_REASON_MMH = 1,
+	BLOCK_6G_CHAN_SWITCH_REASON_MMH_STA = 2,
+	BLOCK_6G_CHAN_SWITCH_REASON_STA_MMH = 3,
+	BLOCK_6G_CHAN_SWITCH_REASON_STA_RX_ECSA = 4,
+} BLOCK_6G_CHAN_SWITCH_REASON;
+
 #ifdef PRAGMA_PACK
 #pragma pack(pop)
 #endif
diff --git a/mlan/mlan_hostcmd_ids.h b/mlan/mlan_hostcmd_ids.h
index e7c7f39..29fc354 100644
--- a/mlan/mlan_hostcmd_ids.h
+++ b/mlan/mlan_hostcmd_ids.h
@@ -126,6 +126,8 @@ ENUM_ELEMENT(HostCmd_CMD_GET_HW_SPEC, 0x0003),
 	/** Host Command ID : 802.11 get status */
 	ENUM_ELEMENT(HostCmd_CMD_WMM_GET_STATUS, 0x0071),
 
+	/** Host Command ID : 802.11 firmware wakeup method */
+	ENUM_ELEMENT(HostCmd_CMD_802_11_FW_WAKE_METHOD, 0x0074),
 	/** Host Command ID : 802.11 subscribe event */
 	ENUM_ELEMENT(HostCmd_CMD_802_11_SUBSCRIBE_EVENT, 0x0075),
 
@@ -262,6 +264,8 @@ ENUM_ELEMENT(HostCmd_CMD_GET_HW_SPEC, 0x0003),
 	/** Host Command ID: CROSS CHIP SYNCH */
 	ENUM_ELEMENT(HostCmd_CMD_CROSS_CHIP_SYNCH, 0x027d),
 
+	ENUM_ELEMENT(HostCmd_CMD_TSP_CFG, 0x0280),
+
 	/** Host Command ID : TDLS configuration */
 	ENUM_ELEMENT(HostCmd_CMD_TDLS_CONFIG, 0x0100),
 	/** Host Command ID : TDLS operation */
@@ -457,10 +461,21 @@ ENUM_ELEMENT(HostCmd_CMD_GET_HW_SPEC, 0x0003),
 	/** Host Command ID: PCIE ADMA INIT */
 	ENUM_ELEMENT(HostCmd_CMD_PCIE_ADMA_INIT, 0x0284),
 
+	/** Host Command ID: query of current TX rate to the peer */
+	ENUM_ELEMENT(HostCmd_CMD_PEER_TX_RATE_QUERY, 0x0285),
+
+	/** Host Command ID: multi-client TX scheduling configuration */
+	ENUM_ELEMENT(HostCmd_CMD_MCLIENT_SCHEDULE_CFG, 0x0286),
+
 	/** Host Command ID : WMM HOST ADDTS req */
 	ENUM_ELEMENT(HostCmd_CMD_WMM_HOST_ADDTS_REQ, 0x0287),
 	/** Host Command ID : WMM HOST DELTS req */
 	ENUM_ELEMENT(HostCmd_CMD_WMM_HOST_DELTS_REQ, 0x0288),
 
+	/** Host Command ID : Auth, Assoc timeout configuration */
+	ENUM_ELEMENT(HostCmd_CMD_AUTH_ASSOC_TIMEOUT_CFG, 0x0289),
+
+	/** Host Command ID : HS Event masking configuration */
+	ENUM_ELEMENT(HostCmd_CMD_HS_EVENT_MASK, 0x028a),
 	/* Always keep this last */
 	ENUM_ELEMENT_LAST(__HostCmd_CMD_Last)
diff --git a/mlan/mlan_ieee.h b/mlan/mlan_ieee.h
index c4cf1e8..30a9184 100644
--- a/mlan/mlan_ieee.h
+++ b/mlan/mlan_ieee.h
@@ -71,6 +71,9 @@ typedef enum _WLAN_802_11_NETWORK_TYPE {
 typedef enum _IEEEtypes_Ext_ElementId_e {
 	HE_CAPABILITY = 35,
 	HE_OPERATION = 36,
+	MU_EDCA_PARAM_SET = 38,
+	MBSSID_CONFIG = 55,
+	NON_INHERITANCE = 56,
 	HE_6G_CAPABILITY = 59
 } IEEEtypes_Ext_ElementId_e;
 
@@ -260,7 +263,7 @@ typedef MLAN_PACK_START struct _IEEEtypes_FastBssTransElement_t {
 	/** SNonce */
 	t_u8 s_nonce[32];
 	/** sub element */
-	t_u8 sub_element[1];
+	t_u8 sub_element[];
 } MLAN_PACK_END IEEEtypes_FastBssTransElement_t;
 
 /*Category for FT*/
@@ -547,7 +550,7 @@ typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t {
 	/** Association ID */
 	IEEEtypes_AId_t a_id;
 	/** IE data buffer */
-	t_u8 ie_buffer[1];
+	t_u8 ie_buffer[];
 } MLAN_PACK_END IEEEtypes_AssocRsp_t, *pIEEEtypes_AssocRsp_t;
 
 /** 802.11 supported rates */
@@ -985,7 +988,7 @@ typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoSet_t {
 	/** Country code */
 	t_u8 country_code[COUNTRY_CODE_LEN];
 	/** Set of subbands */
-	IEEEtypes_SubbandSet_t sub_band[1];
+	IEEEtypes_SubbandSet_t sub_band[];
 } MLAN_PACK_END IEEEtypes_CountryInfoSet_t, *pIEEEtypes_CountryInfoSet_t;
 
 /** Data structure for Country IE full set */
@@ -1151,6 +1154,18 @@ typedef MLAN_PACK_START struct _IEEEtypes_MultiBSSID_t {
 	/** Optional Subelement data*/
 	t_u8 sub_elem_data[];
 } MLAN_PACK_END IEEEtypes_MultiBSSID_t, *pIEEEtypes_MultiBSSID_t;
+
+/** Multi BSSID Configuration IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MBSSID_Config_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Element id extension */
+	t_u8 ext_id;
+	/** BSSID Count */
+	t_u8 bssid_cnt;
+	/** Full Set Rx Periodicity */
+	t_u8 fs_rx_periodicity;
+} MLAN_PACK_END IEEEtypes_MBSSID_Config_t, *pIEEEtypes_MBSSID_Config_t;
 /** 20/40 BSS Coexistence IE */
 typedef MLAN_PACK_START struct _IEEEtypes_2040BSSCo_t {
 	/** Generic IE header */
@@ -1466,6 +1481,32 @@ typedef MLAN_PACK_START struct _IEEEtypes_HeOp_t {
 	t_u8 option[9];
 } MLAN_PACK_END IEEEtypes_HeOp_t;
 
+/** MU EDCA Parameter Set */
+typedef MLAN_PACK_START struct _IEEEtypes_MUEDCAParamSet_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Extended Tag */
+	t_u8 ext_tag;
+	/** QOS Information */
+	t_u8 qos_info;
+	/** MUAC BE Paramter Record */
+	t_u8 muac_be[3];
+	/** MUAC BK Paramter Record */
+	t_u8 muac_bk[3];
+	/** MUAC VI Paramter Record */
+	t_u8 muac_vi[3];
+	/** MUAC VO Paramter Record */
+	t_u8 muac_vo[3];
+} MLAN_PACK_END IEEEtypes_MUEDCAParamSet_t, *pIEEEtypes_MUEDCAParamSet_t;
+
+/** IEEE format IE */
+typedef MLAN_PACK_START struct _IEEEtypes_Element_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** IE data */
+	t_u8 data[];
+} MLAN_PACK_END IEEEtypes_Element_t, *pIEEEtypes_Element_t;
+
 /** default channel switch count */
 #define DEF_CHAN_SWITCH_COUNT 5
 
@@ -2094,6 +2135,10 @@ typedef struct _BSSDescriptor_t {
 	t_u8 multi_bssid_ap;
 	/** the mac address of multi-bssid AP */
 	mlan_802_11_mac_addr multi_bssid_ap_addr;
+	/** Multi BSSID Configuration IE */
+	IEEEtypes_MBSSID_Config_t *pmbssid_config;
+	/** Multi BSSID Configuration IE offset */
+	t_u16 mbssid_config_offset;
 	/** 20/40 BSS Coexistence IE */
 	IEEEtypes_2040BSSCo_t *pbss_co_2040;
 	/** 20/40 BSS Coexistence Offset */
@@ -2174,7 +2219,10 @@ typedef struct _BSSDescriptor_t {
 	IEEEtypes_MobilityDomain_t *pmd_ie;
 	/** Mobility domain IE offset in the beacon buffer */
 	t_u16 md_offset;
-
+	/** MU EDCA Parameter IE */
+	IEEEtypes_MUEDCAParamSet_t *pmuedca_ie;
+	/** MU EDCA Parameter IE offset */
+	t_u16 muedca_offset;
 	/** Pointer to the returned scan response */
 	t_u8 *pbeacon_buf;
 	/** Length of the stored scan response */
diff --git a/mlan/mlan_init.c b/mlan/mlan_init.c
index 3787b1c..3f606e7 100644
--- a/mlan/mlan_init.c
+++ b/mlan/mlan_init.c
@@ -776,6 +776,8 @@ t_void wlan_init_adapter(pmlan_adapter pmadapter)
 	pmadapter->local_listen_interval = 0; /* default value in firmware will
 						 be used */
 #endif /* STA_SUPPORT */
+	pmadapter->fw_wakeup_method = WAKEUP_FW_UNCHANGED;
+	pmadapter->fw_wakeup_gpio_pin = DEF_WAKEUP_FW_GPIO;
 
 	pmadapter->is_deep_sleep = MFALSE;
 	pmadapter->idle_time = DEEP_SLEEP_IDLE_TIME;
@@ -1038,6 +1040,28 @@ mlan_status wlan_init_priv_lock_list(pmlan_adapter pmadapter, t_u8 start_index)
 					MTRUE,
 					priv->adapter->callbacks.moal_init_lock);
 			}
+			util_init_list_head(
+				pmadapter->pmoal_handle, &priv->wmm.all_stas,
+				MTRUE, pmadapter->callbacks.moal_init_lock);
+			util_init_list_head(
+				pmadapter->pmoal_handle,
+				&priv->wmm.pending_stas, MTRUE,
+				pmadapter->callbacks.moal_init_lock);
+			util_init_list_head(
+				pmadapter->pmoal_handle,
+				&priv->wmm.active_stas.list, MTRUE,
+				pmadapter->callbacks.moal_init_lock);
+			for (j = 0; j < NELEMENTS(priv->wmm.pending_txq); ++j) {
+				util_init_list_head(
+					pmadapter->pmoal_handle,
+					&priv->wmm.pending_txq[j], MTRUE,
+					pmadapter->callbacks.moal_init_lock);
+			}
+			priv->wmm.selected_ra_list = MNULL;
+			pcb->moal_get_host_time_ns(
+				&priv->wmm.active_stas.next_update);
+			pcb->moal_get_host_time_ns(&priv->wmm.next_rate_update);
+			priv->wmm.is_rate_update_pending = MFALSE;
 			util_init_list_head(
 				(t_void *)pmadapter->pmoal_handle,
 				&priv->tx_ba_stream_tbl_ptr, MTRUE,
@@ -1156,6 +1180,16 @@ mlan_status wlan_init_lock_list(pmlan_adapter pmadapter)
 		goto error;
 	}
 #endif
+#ifdef USB
+	if (IS_USB(pmadapter->card_type)) {
+		if (pcb->moal_init_lock(pmadapter->pmoal_handle,
+					&pmadapter->pmlan_usb_event_lock) !=
+		    MLAN_STATUS_SUCCESS) {
+			ret = MLAN_STATUS_FAILURE;
+			goto error;
+		}
+	}
+#endif
 #if defined(USB)
 	if (IS_USB(pmadapter->card_type)) {
 		for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
@@ -1258,6 +1292,11 @@ t_void wlan_free_lock_list(pmlan_adapter pmadapter)
 		pcb->moal_free_lock(pmadapter->pmoal_handle,
 				    pmadapter->pmlan_pcie_lock);
 #endif
+#ifdef USB
+	if (IS_USB(pmadapter->card_type) && pmadapter->pmlan_usb_event_lock)
+		pcb->moal_free_lock(pmadapter->pmoal_handle,
+				    pmadapter->pmlan_usb_event_lock);
+#endif
 #if defined(USB)
 	if (IS_USB(pmadapter->card_type)) {
 		for (i = 0; i < MAX_USB_TX_PORT_NUM; i++) {
@@ -1343,6 +1382,24 @@ t_void wlan_free_lock_list(pmlan_adapter pmadapter)
 					(t_void *)priv->adapter->pmoal_handle,
 					&priv->wmm.tid_tbl_ptr[j].ra_list,
 					priv->adapter->callbacks.moal_free_lock);
+			util_free_list_head(
+				(t_void *)priv->adapter->pmoal_handle,
+				&priv->wmm.all_stas,
+				priv->adapter->callbacks.moal_free_lock);
+			util_free_list_head(
+				(t_void *)priv->adapter->pmoal_handle,
+				&priv->wmm.pending_stas,
+				priv->adapter->callbacks.moal_free_lock);
+			util_free_list_head(
+				(t_void *)priv->adapter->pmoal_handle,
+				&priv->wmm.active_stas.list,
+				priv->adapter->callbacks.moal_free_lock);
+			for (j = 0; j < NELEMENTS(priv->wmm.pending_txq); ++j) {
+				util_free_list_head(
+					(t_void *)priv->adapter->pmoal_handle,
+					&priv->wmm.pending_txq[j],
+					priv->adapter->callbacks.moal_free_lock);
+			}
 			util_free_list_head(
 				(t_void *)priv->adapter->pmoal_handle,
 				&priv->tx_ba_stream_tbl_ptr,
@@ -1597,7 +1654,7 @@ static void wlan_update_hw_spec(pmlan_adapter pmadapter)
 			pmadapter->fw_bands |= BAND_GAX;
 			pmadapter->config_bands |= BAND_GAX;
 		}
-		if (pmadapter->hw_hecap_len) {
+		if ((pmadapter->fw_bands & BAND_A) && pmadapter->hw_hecap_len) {
 			pmadapter->fw_bands |= BAND_AAX;
 			pmadapter->config_bands |= BAND_AAX;
 		}
@@ -1741,6 +1798,14 @@ t_void wlan_free_adapter(pmlan_adapter pmadapter)
 		return;
 	}
 
+#ifdef PCIE
+	if (IS_PCIE(pmadapter->card_type)) {
+		/* Free ssu dma buffer just in case  */
+		wlan_free_ssu_pcie_buf(pmadapter);
+		/* Free PCIE ring buffers */
+		wlan_free_pcie_ring_buf(pmadapter);
+	}
+#endif
 	wlan_cancel_all_pending_cmd(pmadapter, MTRUE);
 	/* Free command buffer */
 	PRINTM(MINFO, "Free Command buffer\n");
@@ -1844,15 +1909,6 @@ t_void wlan_free_adapter(pmlan_adapter pmadapter)
 	wlan_free_mlan_buffer(pmadapter, pmadapter->psleep_cfm);
 	pmadapter->psleep_cfm = MNULL;
 
-#ifdef PCIE
-	if (IS_PCIE(pmadapter->card_type)) {
-		/* Free ssu dma buffer just in case  */
-		wlan_free_ssu_pcie_buf(pmadapter);
-		/* Free PCIE ring buffers */
-		wlan_free_pcie_ring_buf(pmadapter);
-	}
-#endif
-
 	/* Free timers */
 	wlan_free_timer(pmadapter);
 
diff --git a/mlan/mlan_ioctl.h b/mlan/mlan_ioctl.h
index bfb383f..38518c6 100644
--- a/mlan/mlan_ioctl.h
+++ b/mlan/mlan_ioctl.h
@@ -164,6 +164,7 @@ enum _mlan_ioctl_req_id {
 	MLAN_OID_PM_CFG_DEEP_SLEEP = 0x00090004,
 	MLAN_OID_PM_CFG_SLEEP_PD = 0x00090005,
 	MLAN_OID_PM_CFG_PS_CFG = 0x00090006,
+	MLAN_OID_PM_CFG_FW_WAKEUP_METHOD = 0x00090007,
 	MLAN_OID_PM_CFG_SLEEP_PARAMS = 0x00090008,
 #ifdef UAP_SUPPORT
 	MLAN_OID_PM_CFG_PS_MODE = 0x00090009,
@@ -375,6 +376,7 @@ enum _mlan_ioctl_req_id {
 	MLAN_OID_MISC_CROSS_CHIP_SYNCH = 0x0020008B,
 	MLAN_OID_MISC_RF_TEST_CONFIG_TRIGGER_FRAME = 0x0020008C,
 	MLAN_OID_MISC_OFDM_DESENSE_CFG = 0x0020008D,
+	MLAN_OID_MISC_TSP_CFG = 0x002008C,
 	MLAN_OID_MISC_REORDER_FLUSH_TIME = 0x0020008F,
 	MLAN_OID_MISC_NAV_MITIGATION = 0x00200090,
 	MLAN_OID_MISC_LED_CONFIG = 0x00200091,
@@ -383,6 +385,8 @@ enum _mlan_ioctl_req_id {
 	MLAN_OID_MISC_GPIO_CFG = 0x00200094,
 	MLAN_OID_MISC_REGION_POWER_CFG = 0x00200095,
 	MLAN_OID_MISC_OTP_MAC_RD_WR = 0x00200097,
+	MLAN_OID_MISC_OTP_CAL_DATA_RD_WR = 0x00200098,
+	MLAN_OID_MISC_AUTH_ASSOC_TIMEOUT_CONFIG = 0x00200099,
 };
 
 /** Sub command size */
@@ -519,7 +523,7 @@ typedef struct {
 	 * Buffer marker for multiple wlan_ioctl_get_scan_table_entry
 	 * structures. Each struct is padded to the nearest 32 bit boundary.
 	 */
-	t_u8 scan_table_entry_buf[1];
+	t_u8 scan_table_entry_buf[];
 } wlan_ioctl_get_scan_table_info;
 
 /**
@@ -576,7 +580,7 @@ typedef struct _mlan_user_scan {
 	/** Length of scan_cfg_buf */
 	t_u32 scan_cfg_len;
 	/** Buffer of scan config */
-	t_u8 scan_cfg_buf[1];
+	t_u8 scan_cfg_buf[];
 } mlan_user_scan, *pmlan_user_scan;
 
 /** Type definition of mlan_scan_req */
@@ -1763,6 +1767,8 @@ typedef struct _mlan_ds_get_stats {
 	t_u32 gdma_abort_cnt;
 	/** Rx Reset MAC Count */
 	t_u32 g_reset_rx_mac_cnt;
+	/** SDMA FSM stuck Count*/
+	t_u32 SdmaStuckCnt;
 	// Ownership error counters
 	/*Error Ownership error count*/
 	t_u32 dwCtlErrCnt;
@@ -3395,6 +3401,15 @@ typedef struct _mlan_ds_hs_wakeup_reason {
 	t_u16 hs_wakeup_reason;
 } mlan_ds_hs_wakeup_reason;
 
+/** Type definition of mlan_fw_wakeup_params for
+ * MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+typedef struct _mlan_fw_wakeup_params {
+	/** FW wakeup method */
+	t_u16 method;
+	/** GPIO pin NO.*/
+	t_u8 gpio_pin;
+} mlan_fw_wakeup_params, *pmlan_fw_wakeup_params;
+
 /** Type definition of mlan_ds_ps_cfg for MLAN_OID_PM_CFG_PS_CFG */
 typedef struct _mlan_ds_bcn_timeout {
 	/** Beacon miss timeout period window */
@@ -3425,6 +3440,8 @@ typedef struct _mlan_ds_pm_cfg {
 		t_u32 sleep_period;
 		/** PS configuration parameters for MLAN_OID_PM_CFG_PS_CFG */
 		mlan_ds_ps_cfg ps_cfg;
+		/** FW wakeup method for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+		mlan_fw_wakeup_params fw_wakeup_params;
 		/** PS configuration parameters for MLAN_OID_PM_CFG_SLEEP_PARAMS
 		 */
 		mlan_ds_sleep_params sleep_params;
@@ -4177,6 +4194,9 @@ typedef struct _mlan_ds_11ax_rutxpwr_cmd {
 	/** column,row are 3 for every subband table,however column are 7 for FC
 	 * and 6 for other SOCs */
 	t_u8 col;
+	/** row are 3 for every subband table,total row for MAC1 is 12 and MAC2
+	 * id 3 ( consider only 2G support */
+	t_u8 row;
 	/**ru tx data */
 	t_s8 rutxSubPwr[89];
 } mlan_ds_11ax_rutxpwr_cmd, *pmlan_ds_11ax_rutxpwr_cmd;
@@ -4264,6 +4284,8 @@ typedef struct MLAN_PACK_START _mlan_ds_twt_setup {
 	t_u16 twt_mantissa;
 	/** TWT Request Type, 0: REQUEST_TWT, 1: SUGGEST_TWT*/
 	t_u8 twt_request;
+	/** TWT link lost timeout threshold */
+	t_u16 bcnMiss_threshold;
 } MLAN_PACK_END mlan_ds_twt_setup, *pmlan_ds_twt_setup;
 
 /** Type definition of mlan_ds_twt_teardown for MLAN_OID_11AX_TWT_CFG */
@@ -4415,14 +4437,14 @@ enum _mlan_reg_type {
 	defined(PCIE9097) || defined(USB9097) || defined(SDIW624) ||           \
 	defined(SDAW693) || defined(PCIEAW693) || defined(PCIEIW624) ||        \
 	defined(USBIW624) || defined(SD9097) || defined(SD9177) ||             \
-	defined(SDIW615) || defined(USBIW615)
+	defined(SDIW610) || defined(USBIW610)
 	MLAN_REG_CIU = 8,
 #endif
 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
 	defined(PCIE9097) || defined(USB9097) || defined(SDIW624) ||           \
 	defined(SDAW693) || defined(PCIEAW693) || defined(PCIEIW624) ||        \
-	defined(USBIW624) || defined(SD9097) || defined(SDIW615) ||            \
-	defined(USBIW615)
+	defined(USBIW624) || defined(SD9097) || defined(SDIW610) ||            \
+	defined(USBIW610)
 	MLAN_REG_MAC2 = 0x81,
 	MLAN_REG_BBP2 = 0x82,
 	MLAN_REG_RF2 = 0x83,
@@ -5659,7 +5681,7 @@ typedef MLAN_PACK_START struct _mlan_ds_misc_tx_rx_histogram {
 	/** Size of Tx/Rx info */
 	t_u16 size;
 	/** Store Tx/Rx info */
-	t_u8 value[1];
+	t_u8 value[];
 } MLAN_PACK_END mlan_ds_misc_tx_rx_histogram;
 
 #define RX_PKT_INFO MBIT(1)
@@ -5917,6 +5939,7 @@ typedef struct _mlan_ds_misc_chan_trpc_cfg {
 #define MFG_CMD_CONFIG_MAC_HE_TB_TX 0x110A
 #define MFG_CMD_CONFIG_TRIGGER_FRAME 0x110C
 #define MFG_CMD_OTP_MAC_ADD 0x108C
+#define MFG_CMD_OTP_CAL_DATA 0x121A
 
 /** MFG CMD generic cfg */
 struct MLAN_PACK_START mfg_cmd_generic_cfg {
@@ -6227,6 +6250,24 @@ typedef MLAN_PACK_START struct _mfg_cmd_otp_mac_addr_rd_wr_t {
 	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
 } MLAN_PACK_END mfg_cmd_otp_mac_addr_rd_wr_t;
 
+#define CAL_DATA_LEN 1400
+typedef MLAN_PACK_START struct _mfg_cmd_otp_cal_data_rd_wr_t {
+	/** MFG command code */
+	t_u32 mfg_cmd;
+	/** Action */
+	t_u16 action;
+	/** Device ID */
+	t_u16 device_id;
+	/** MFG Error code */
+	t_u32 error;
+	/** CAL Data write status */
+	t_u32 cal_data_status;
+	/** CAL Data Length*/
+	t_u32 cal_data_len;
+	/** Destination MAC Address */
+	t_u8 cal_data[CAL_DATA_LEN];
+} MLAN_PACK_END mfg_cmd_otp_cal_data_rd_wr_t;
+
 typedef struct _mlan_ds_misc_chnrgpwr_cfg {
 	/** length */
 	t_u16 length;
@@ -6244,6 +6285,22 @@ typedef struct _mlan_ds_misc_cfp_tbl {
 	chan_freq_power_t cfp_tbl[];
 } mlan_ds_misc_cfp_tbl;
 
+/** channel attribute */
+typedef struct _chan_attr {
+	/** channel number */
+	t_u8 channel;
+	/** channel flags */
+	t_u8 flags;
+} chan_attr_t;
+
+/** channel flags table */
+typedef struct _mlan_ds_chan_attr {
+	/** Data length */
+	t_u16 data_len;
+	/** Data */
+	chan_attr_t chan_attr[MLAN_MAX_CHANNEL_NUM];
+} MLAN_PACK_END mlan_ds_chan_attr;
+
 /** mlan_ds_mc_aggr_cfg for MLAN_OID_MISC_MC_AGGR_CFG */
 typedef struct _mlan_ds_mc_aggr_cfg {
 	/** action */
@@ -6301,6 +6358,33 @@ typedef struct _mlan_ds_cross_chip_synch {
 	t_u32 init_tsf_high;
 } mlan_ds_cross_chip_synch;
 
+#define MAX_RFUS 2
+#define MAX_PATHS 2
+typedef struct _mlan_ds_tsp_cfg {
+	/** TSP config action 0-GET, 1-SET */
+	t_u16 action;
+	/** TSP enable/disable tsp algothrim */
+	t_u16 enable;
+	/** TSP config power backoff */
+	t_s32 backoff;
+	/** TSP config high threshold */
+	t_s32 high_thrshld;
+	/** TSP config low threshold */
+	t_s32 low_thrshld;
+	/** TSP config DUTY_CYC_STEP */
+	t_s32 duty_cyc_step;
+	/** TSP config DUTY_CYC_MIN */
+	t_s32 duty_cyc_min;
+	/** TSP config HIGH_THRESHOLD_TEMP */
+	t_s32 high_thrshld_temp;
+	/** TSP config LOW_THRESHOLD_TEMP */
+	t_s32 low_thrshld_temp;
+	/** TSP CAU TSEN register */
+	t_s32 reg_cau_val;
+	/** TSP RFU registers */
+	t_s32 reg_rfu_temp[MAX_RFUS][MAX_PATHS];
+} MLAN_PACK_END mlan_ds_tsp_cfg;
+
 typedef struct _mlan_ds_reorder_flush_time {
 	/** AC BK/BE_flush time*/
 	t_u16 flush_time_ac_be_bk;
@@ -6322,6 +6406,36 @@ typedef struct _mlan_ds_ed_mac_cfg {
 	t_u32 ed_bitmap_txq_lock;
 } mlan_ds_ed_mac_cfg;
 
+/** valid range for mlan_ds_auth_assoc_timeout_cfg */
+#define AUTH_TIMEOUT_MIN 500
+#define AUTH_TIMEOUT_MAX 2400
+#define AUTH_RETRY_TIMEOUT_ACK_MIN 50
+#define AUTH_RETRY_TIMEOUT_ACK_MAX 300
+#define AUTH_RETRY_TIMEOUT_NO_ACK_MIN 40
+#define AUTH_RETRY_TIMEOUT_NO_ACK_MAX 80
+#define ASSOC_TIMEOUT_MIN 200
+#define ASSOC_TIMEOUT_MAX 1500
+#define REASSOC_TIMEOUT_MIN 100
+#define REASSOC_TIMEOUT_MAX 1500
+#define ASSOC_RETRY_TIMEOUT_MIN 50
+#define ASSOC_RETRY_TIMEOUT_MAX 150
+
+/** Auth Assoc timeout configuration parameters */
+typedef struct _mlan_ds_auth_assoc_timeout_cfg {
+	/** auth timeout */
+	t_u16 auth_timeout;
+	/** Auth retry timeout if received ack */
+	t_u16 auth_retry_timeout_if_ack;
+	/** Auth retry timeout if ack is not received */
+	t_u16 auth_retry_timeout_if_no_ack;
+	/** assoc timeout */
+	t_u16 assoc_timeout;
+	/** reassoc timeout */
+	t_u16 reassoc_timeout;
+	/** assoc/reassoc frame retry timeout if ack received */
+	t_u16 retry_timeout;
+} mlan_ds_auth_assoc_timeout_cfg;
+
 /** Type definition of mlan_ds_misc_cfg for MLAN_IOCTL_MISC_CFG */
 typedef struct _mlan_ds_misc_cfg {
 	/** Sub-command */
@@ -6469,6 +6583,7 @@ typedef struct _mlan_ds_misc_cfg {
 		mlan_ds_misc_cck_desense_cfg cck_desense_cfg;
 		mlan_ds_misc_chan_trpc_cfg trpc_cfg;
 		mlan_ds_misc_chnrgpwr_cfg rgchnpwr_cfg;
+		mlan_ds_chan_attr chan_attr_cfg;
 
 		mlan_ds_band_steer_cfg band_steer_cfg;
 		mlan_ds_beacon_stuck_param_cfg beacon_stuck_cfg;
@@ -6478,6 +6593,7 @@ typedef struct _mlan_ds_misc_cfg {
 		struct mfg_Cmd_HE_TBTx_t mfg_he_power;
 		mfg_Cmd_IEEEtypes_CtlBasicTrigHdr_t mfg_tx_trigger_config;
 		mfg_cmd_otp_mac_addr_rd_wr_t mfg_otp_mac_addr_rd_wr;
+		mfg_cmd_otp_cal_data_rd_wr_t mfg_otp_cal_data_rd_wr;
 		mlan_ds_misc_arb_cfg arb_cfg;
 		mlan_ds_misc_cfp_tbl cfp;
 		t_u8 range_ext_mode;
@@ -6493,12 +6609,32 @@ typedef struct _mlan_ds_misc_cfg {
 		t_u32 ips_ctrl;
 		mlan_ds_ch_load ch_load;
 		mlan_ds_cross_chip_synch cross_chip_synch;
+		mlan_ds_tsp_cfg tsp_cfg;
 		mlan_ds_reorder_flush_time flush_time;
 		mlan_ds_ed_mac_cfg edmac_cfg;
 		mlan_ds_gpio_cfg_ops gpio_cfg_ops;
+		mlan_ds_auth_assoc_timeout_cfg auth_assoc_cfg;
 	} param;
 } mlan_ds_misc_cfg, *pmlan_ds_misc_cfg;
 
+typedef struct _mlan_cfpinfo {
+	t_u8 nss : 2;
+	t_u8 is2g_present : 1;
+	t_u8 is5g_present : 1;
+	t_u8 is6g_present : 1;
+	t_u8 reserved : 3;
+	t_u8 rows_2g;
+	t_u8 cols_2g;
+	t_u8 rows_5g;
+	t_u8 cols_5g;
+	t_u8 rows_6g;
+	t_u8 cols_6g;
+	t_u8 region_code;
+	t_u8 environment;
+	t_u8 country_code[2];
+	t_u16 action;
+} mlan_cfpinfo;
+
 /** Hotspot status enable */
 #define HOTSPOT_ENABLED MBIT(0)
 /** Hotspot status disable */
diff --git a/mlan/mlan_main.h b/mlan/mlan_main.h
index 48aeaf2..2e41d37 100644
--- a/mlan/mlan_main.h
+++ b/mlan/mlan_main.h
@@ -156,6 +156,12 @@ extern t_u32 mlan_drvdbg;
 			print_callback(MNULL, MMSG, msg);                      \
 	} while (0)
 
+#define PRINTM_MSCH_D(msg...)                                                  \
+	do {                                                                   \
+		if ((mlan_drvdbg & MSCH_D) && (print_callback))                \
+			print_callback(MNULL, MSCH_D, msg);                    \
+	} while (0)
+
 #define PRINTM(level, msg...) PRINTM_##level((char *)msg)
 
 /** Log debug message */
@@ -571,7 +577,7 @@ extern t_void (*assert_callback)(t_void *pmoal_handle, t_u32 cond);
 #if defined(SD8887) || defined(SD8997) || defined(SD8977) ||                   \
 	defined(SD8987) || defined(SD9098) || defined(SD9097) ||               \
 	defined(SDAW693) || defined(SDIW624) || defined(SD8978) ||             \
-	defined(SD9177) || defined(SDIW615)
+	defined(SD9177) || defined(SDIW610)
 #define MAX_MP_REGS 196
 #else
 /* upto 0xB7 */
@@ -621,6 +627,11 @@ extern t_void (*assert_callback)(t_void *pmoal_handle, t_u32 cond);
 /** scan GAP value is optional */
 #define GAP_FLAG_OPTIONAL MBIT(15)
 
+/** max numbe of mac filters allowed in llde list */
+#define MAX_MAC_FILTER_ENTRIES 2
+/** max numbe of iPhone devices allowed in llde list */
+#define MAX_IPHONE_FILTER_ENTRIES 2
+
 /** Info for debug purpose */
 typedef struct _wlan_dbg {
 	/** Number of host to card command failures */
@@ -787,6 +798,11 @@ struct _raListTbl {
 	t_u8 is_tdls_link;
 	/** tx_pause flag */
 	t_u8 tx_pause;
+
+	t_u8 tid;
+	t_u8 queue;
+	struct wmm_sta_table *sta;
+	mlan_linked_list pending_txq_entry;
 };
 
 /** TID table */
@@ -810,6 +826,45 @@ typedef struct _tidTbl {
 /** Max driver packet delay in msec */
 #define WMM_DRV_DELAY_MAX 510
 
+struct wmm_sta_table {
+	mlan_linked_list all_stas_entry;
+	mlan_linked_list pending_stas_entry;
+	mlan_linked_list active_sta_entry;
+
+	t_u8 ra[MLAN_MAC_ADDR_LENGTH];
+	t_bool ps_sleep;
+
+	raListTbl *ra_lists[MAX_NUM_TID];
+
+	struct {
+		t_u16 time_budget_init_us;
+		t_u32 mpdu_with_amsdu_pps_cap;
+		t_u32 mpdu_no_amsdu_pps_cap;
+		t_u32 byte_budget_init;
+		t_u32 mpdu_with_amsdu_budget_init;
+		t_u32 mpdu_no_amsdu_budget_init;
+		t_u32 phy_rate_kbps;
+		t_u32 queue_packets;
+		t_s32 bytes[MAX_NUM_TID];
+		t_s32 mpdus[MAX_NUM_TID];
+	} budget;
+};
+
+typedef struct mlan_wmm_param {
+	t_u8 ecwmin;
+	;
+	t_u8 ecwmax;
+	t_u8 aifsn;
+} mlan_wmm_param;
+
+typedef struct mlan_wmm_contention {
+	mlan_wmm_param param;
+	t_u8 ecw;
+	t_bool move_cw_on_lost;
+	t_u16 remaining_aifs;
+	t_u16 remaining_backoff;
+} mlan_wmm_contention;
+
 /** Struct of WMM DESC */
 typedef struct _wmm_desc {
 	/** TID table */
@@ -840,6 +895,24 @@ typedef struct _wmm_desc {
 	mlan_scalar tx_pkts_queued;
 	/** Tracks highest priority with a packet queued */
 	mlan_scalar highest_queued_prio;
+
+	mlan_list_head all_stas; /* struct wmm_sta_table */
+
+	mlan_list_head pending_stas; /* struct wmm_sta_table */
+
+	struct {
+		mlan_list_head list; /* STAs that had some TX traffic since last
+					tracking period, struct wmm_sta_table */
+		t_u32 n_stas;
+		t_u64 next_update;
+	} active_stas;
+
+	mlan_list_head pending_txq[MAX_AC_QUEUES];
+	mlan_wmm_contention txq_contention[MAX_AC_QUEUES];
+	raListTbl *selected_ra_list;
+	t_u64 next_rate_update;
+	t_bool is_rate_update_pending;
+
 } wmm_desc_t;
 
 /** Security structure */
@@ -1517,6 +1590,9 @@ typedef enum _tdlsStatus_e {
 /** station node */
 typedef struct _sta_node sta_node, *psta_node;
 
+#define VENDOR_OUI_LEN 4
+#define MAX_VENDOR_OUI_NUM 10
+
 /** station node*/
 struct _sta_node {
 	/** previous node */
@@ -1591,6 +1667,10 @@ struct _sta_node {
 	t_u16 aid;
 	/** apple device based on OUI in assoc req */
 	t_u8 is_apple_sta;
+	/** vendor oui list */
+	t_u8 vendor_oui[VENDOR_OUI_LEN * MAX_VENDOR_OUI_NUM];
+	/** vendor OUI count */
+	t_u8 vendor_oui_count;
 };
 
 /** 802.11h State information kept in the 'mlan_adapter' driver structure */
@@ -1916,6 +1996,8 @@ typedef struct _mlan_init_para {
 #endif
 	/** Auto deep sleep */
 	t_u32 auto_ds;
+	/** Boot Time Config */
+	t_u32 bootup_cal_ctrl;
 	/** IEEE PS mode */
 	t_u32 ps_mode;
 	/** Max Tx buffer size */
@@ -1938,6 +2020,8 @@ typedef struct _mlan_init_para {
 	t_u8 uap_max_sta;
 	/** wacp mode */
 	t_u8 wacp_mode;
+	/** custom Fw data */
+	t_u32 fw_data_cfg;
 	/** dfs w53 cfg */
 	t_u8 dfs53cfg;
 	/** dfs_offload */
@@ -1952,6 +2036,11 @@ typedef struct _mlan_init_para {
 	t_u32 antcfg;
 	/** dmcs*/
 	t_u8 dmcs;
+	/** pref_dbc*/
+	t_u8 pref_dbc;
+	t_u32 max_tx_pending;
+	t_u16 tx_budget;
+	t_u8 mclient_scheduling;
 	t_u32 reject_addba_req;
 } mlan_init_para, *pmlan_init_para;
 
@@ -2378,6 +2467,7 @@ struct _mlan_adapter {
 	t_void *pmlan_lock;
 	/** main_proc_lock for main_process */
 	t_void *pmain_proc_lock;
+	mlan_private *selected_mlan_bss;
 #ifdef PCIE
 	/** rx data lock to synchronize wlan_pcie_process_recv_data */
 	t_void *pmlan_rx_lock;
@@ -2702,6 +2792,8 @@ struct _mlan_adapter {
 	t_u8 rx_data_ep;
 	/** Tx data endpoint address */
 	t_u8 tx_data_ep;
+	/** mlan_lock for rx event */
+	t_void *pmlan_usb_event_lock;
 #endif
 	/** Multi channel status */
 	t_u8 mc_status;
@@ -2746,6 +2838,10 @@ struct _mlan_adapter {
 	/** Beacon miss timeout */
 	t_u16 bcn_miss_time_out;
 
+	/** Firmware wakeup method */
+	t_u16 fw_wakeup_method;
+	/** Firmware wakeup GPIO pin */
+	t_u8 fw_wakeup_gpio_pin;
 	/** Deep Sleep flag */
 	t_u8 is_deep_sleep;
 	/** Idle time */
@@ -2932,14 +3028,90 @@ struct _mlan_adapter {
 	t_u16 flush_time_ac_vi_vo;
 	/** remain_on_channel flag */
 	t_u8 remain_on_channel;
+
+	t_u8 mclient_tx_supported;
+	t_u8 tx_ba_timeout_support;
+	t_u32 tx_ba_stream_limit;
+	t_u32 tx_mpdu_with_amsdu_pps;
+	t_u32 tx_mpdu_no_amsdu_pps;
+
+	struct {
+		raListTbl *ra_list;
+		t_u32 pushed_pkg;
+	} ra_list_tracing;
+	/** LLDE enable/disable */
 	t_u8 llde_enabled;
+	/** LLDE modes 0 - default; 1 - carplay; 2 - gameplay; 3 - sound bar, 4
+	 * � validation, 5- event driven */
 	t_u8 llde_mode;
+	/** high priority data packet type. 0: All traffic, 1: ping, 2: TCP ACK,
+	 * 4: TCP Data, 8: UDP */
 	t_u8 llde_packet_type;
+	/** 0: no preference, 1: iphone  */
 	t_u8 llde_device_filter;
-	t_u8 llde_macfilter1[MLAN_MAC_ADDR_LENGTH];
-	t_u8 llde_macfilter2[MLAN_MAC_ADDR_LENGTH];
+	/** total iPhone devices allowed in list */
+	t_u8 llde_totalIPhones;
+	/** total other devices as defined in llde.conf */
+	t_u8 llde_totalMacFilters;
+	/** mac filter list as defined in llde.conf file */
+	t_u8 llde_macfilters[MAX_MAC_FILTER_ENTRIES * MLAN_MAC_ADDR_LENGTH];
+	/** iPhone device list */
+	t_u8 llde_iphonefilters[MAX_IPHONE_FILTER_ENTRIES *
+				MLAN_MAC_ADDR_LENGTH];
 };
 
+/** IPv4 ARP request header */
+typedef MLAN_PACK_START struct {
+	/** Hardware type */
+	t_u16 Htype;
+	/** Protocol type */
+	t_u16 Ptype;
+	/** Hardware address length */
+	t_u8 addr_len;
+	/** Protocol address length */
+	t_u8 proto_len;
+	/** Operation code */
+	t_u16 op_code;
+	/** Source mac address */
+	t_u8 sender_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Sender IP address */
+	t_u8 sender_ip[4];
+	/** Destination mac address */
+	t_u8 target_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Destination IP address */
+	t_u8 target_ip[4];
+} MLAN_PACK_END IPv4_ARP_t;
+
+/** IPv6 Nadv packet header */
+typedef MLAN_PACK_START struct {
+	/** IP protocol version */
+	t_u8 version;
+	/** flow label */
+	t_u8 flow_lab[3];
+	/** Payload length */
+	t_u16 payload_len;
+	/** Next header type */
+	t_u8 next_hdr;
+	/** Hot limit */
+	t_u8 hop_limit;
+	/** Source address */
+	t_u8 src_addr[16];
+	/** Destination address */
+	t_u8 dst_addr[16];
+	/** ICMP type */
+	t_u8 icmp_type;
+	/** IPv6 Code */
+	t_u8 ipv6_code;
+	/** IPv6 Checksum */
+	t_u16 ipv6_checksum;
+	/** Flags */
+	t_u32 flags;
+	/** Target address */
+	t_u8 taget_addr[16];
+	/** Reserved */
+	t_u8 rev[8];
+} MLAN_PACK_END IPv6_Nadv_t;
+
 /** Check if stream 2X2 enabled */
 #define IS_STREAM_2X2(x) ((x)&FEATURE_CTRL_STREAM_2X2)
 /** Check if DFS support enabled */
@@ -2979,6 +3151,18 @@ struct _mlan_adapter {
 #define MLAN_TCP_ACK_OFFSET 24
 #define MLAN_TCP_ACK_HEADER_LEN 52
 
+#ifdef STA_SUPPORT
+/** Region code mapping */
+typedef struct _region_code_mapping {
+	/** Region */
+	t_u8 region[COUNTRY_CODE_LEN];
+	/** Code */
+	t_u8 code;
+} region_code_mapping_t;
+extern region_code_mapping_t region_code_mapping[];
+t_u8 *wlan_11d_code_2_region(pmlan_adapter pmadapter, t_u8 code);
+#endif
+
 /** Rx packet Sniffer Operation Mode
  *
  * MODE1 : Can be enabled only in disconnected state.
@@ -3181,6 +3365,10 @@ mlan_status wlan_write_data_complete(pmlan_adapter pmlan_adapter,
 				     pmlan_buffer pmbuf, mlan_status status);
 
 #ifdef USB
+/** Request event lock */
+t_void wlan_request_event_lock(mlan_adapter *pmadapter);
+/** Release event lock */
+t_void wlan_release_event_lock(mlan_adapter *pmadapter);
 mlan_status wlan_usb_deaggr_rx_pkt(pmlan_adapter pmadapter, pmlan_buffer pmbuf);
 
 /**
@@ -3380,6 +3568,12 @@ mlan_status wlan_ret_cross_chip_synch(pmlan_private pmpriv,
 				      mlan_ioctl_req *pioctl_buf);
 mlan_status wlan_misc_ioctl_cross_chip_synch(pmlan_adapter pmadapter,
 					     pmlan_ioctl_req pioctl_req);
+mlan_status wlan_cmd_tsp_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
+				t_u16 cmd_action, t_void *pdata_buf);
+mlan_status wlan_ret_tsp_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+				mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_misc_ioctl_tsp_config(pmlan_adapter pmadapter,
+				       pmlan_ioctl_req pioctl_req);
 /** get ralist info */
 int wlan_get_ralist_info(mlan_private *priv, pralist_info buf);
 /** dump ralist */
@@ -3454,6 +3648,16 @@ mlan_status wlan_ret_802_11_hs_cfg(pmlan_private pmpriv,
 /** Sends HS_WAKEUP event to applications */
 t_void wlan_host_sleep_wakeup_event(pmlan_private priv);
 
+mlan_status wlan_cmd_802_11_fw_wakeup_method(pmlan_private pmpriv,
+					     HostCmd_DS_COMMAND *cmd,
+					     t_u16 cmd_action,
+					     t_u16 *pdata_buf);
+mlan_status wlan_ret_fw_wakeup_method(pmlan_private pmpriv,
+				      HostCmd_DS_COMMAND *resp,
+				      mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_fw_wakeup_method(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req);
+
 /** Prepares command of robustcoex */
 mlan_status wlan_cmd_robustcoex(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
 				t_u16 cmd_action, t_u16 *pdata_buf);
@@ -3836,6 +4040,7 @@ t_void wlan_set_chan_dfs_state(mlan_private *priv, t_u16 band, t_u8 chan,
 			       dfs_state_t dfs_state);
 t_void wlan_reset_all_chan_dfs_state(mlan_private *priv, t_u16 band,
 				     dfs_state_t dfs_state);
+
 /* 802.11D related functions */
 /** Initialize 11D */
 t_void wlan_11d_priv_init(mlan_private *pmpriv);
@@ -4079,6 +4284,7 @@ mlan_status wlan_misc_ioctl_custom_ie_list(pmlan_adapter pmadapter,
 					   pmlan_ioctl_req pioctl_req,
 					   t_bool send_ioctl);
 
+mlan_status wlan_cmd_func_init(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd);
 mlan_status wlan_cmd_get_hw_spec(pmlan_private pmpriv,
 				 HostCmd_DS_COMMAND *pcmd);
 mlan_status wlan_ret_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
@@ -4368,7 +4574,6 @@ mlan_status wlan_misc_ioctl_get_tsf(pmlan_adapter pmadapter,
 				    pmlan_ioctl_req pioctl_req);
 void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left);
 void wlan_free_fw_cfp_tables(mlan_adapter *pmadapter);
-
 mlan_status wlan_misc_chan_reg_cfg(pmlan_adapter pmadapter,
 				   pmlan_ioctl_req pioctl_req);
 mlan_status wlan_misc_region_power_cfg(pmlan_adapter pmadapter,
@@ -4410,6 +4615,9 @@ t_u8 wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate);
 t_u8 wlan_get_center_freq_idx(mlan_private *pmpriv, t_u16 band, t_u32 pri_chan,
 			      t_u8 chan_bw);
 
+mlan_status wlan_cmd_chan_region_cfg(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				     t_void *pdata_buf);
 mlan_status wlan_ret_chan_region_cfg(pmlan_private pmpriv,
 				     HostCmd_DS_COMMAND *resp,
 				     mlan_ioctl_req *pioctl_buf);
@@ -4449,6 +4657,9 @@ mlan_status wlan_cmd_set_get_low_power_mode_cfg(pmlan_private pmpriv,
 mlan_status wlan_ret_set_get_low_power_mode_cfg(pmlan_private pmpriv,
 						HostCmd_DS_COMMAND *resp,
 						mlan_ioctl_req *pioctl_buf);
+mlan_status wlan_ret_auth_assoc_timeout_cfg(pmlan_private pmpriv,
+					    HostCmd_DS_COMMAND *resp,
+					    mlan_ioctl_req *pioctl_buf);
 
 mlan_status wlan_cmd_range_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
 			       t_u16 cmd_action, t_void *pdata_buf);
@@ -4472,6 +4683,9 @@ mlan_status wlan_cmd_edmac_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
 mlan_status wlan_misc_ioctl_country_code(pmlan_adapter pmadapter,
 					 mlan_ioctl_req *pioctl_req);
 
+/** Get custom Fw data */
+mlan_status wlan_get_custom_fw_data(pmlan_adapter pmadapter, t_u8 *pdata);
+
 /**
  *  @brief RA based queueing
  *
@@ -4836,4 +5050,27 @@ t_bool wlan_secure_add(t_void *datain, t_s32 add, t_void *dataout,
 t_bool wlan_secure_sub(t_void *datain, t_s32 sub, t_void *dataout,
 		       data_type type);
 
+void wlan_wmm_contention_init(
+	mlan_private *mlan,
+	const IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES]);
+void wlan_update_sta_ps_state(pmlan_private priv, t_u8 *mac, t_u8 sleep);
+mlan_status wlan_cmd_sta_tx_rate_req(pmlan_private pmpriv,
+				     HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				     t_pvoid pdata_buf);
+mlan_status wlan_ret_sta_tx_rate(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
+				 mlan_ioctl_req *pioctl_buf);
+
+mlan_status wlan_cmd_mclient_scheduling_cfg(pmlan_private pmpriv,
+					    HostCmd_DS_COMMAND *cmd,
+					    t_u16 cmd_action,
+					    t_pvoid pdata_buf);
+
+mlan_status wlan_cmd_mclient_scheduling_enable(pmlan_private pmpriv,
+					       t_bool enable);
+
+void wlan_add_iPhone_entry(mlan_private *priv, t_u8 *mac);
+void wlan_delete_iPhone_entry(mlan_private *priv, t_u8 *mac);
+
+extern void print_chan_switch_block_event(t_u16 reason_code);
+
 #endif /* !_MLAN_MAIN_H_ */
diff --git a/mlan/mlan_misc.c b/mlan/mlan_misc.c
index 35789ac..954f736 100644
--- a/mlan/mlan_misc.c
+++ b/mlan/mlan_misc.c
@@ -46,6 +46,31 @@ Change Log:
 /********************************************************
 			Global Variables
 ********************************************************/
+#if defined(USB8978) || defined(SD8978)
+/** custom Fw data */
+/** Fw remap config */
+t_u8 fw_data_fw_remap_config[FW_DATA_FW_REMAP_CONFIG_LEN] = {
+	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
+	0x00, 0x6A, 0x26, 0x96, 0xB2, 0x44, 0x65, 0x01, 0x04, 0x01, 0x00,
+	0x00, 0x80, 0x00, 0x00, 0x0C, 0xA0, 0xCC, 0x1B, 0x6A, 0x41, 0x04,
+	0x00, 0x0C, 0xA0, 0x02, 0x00, 0x00, 0x00, 0x4A, 0xE7, 0xE5, 0xA3};
+#endif
+
+#if defined(USB8978)
+/** USB endpoint config */
+t_u8 fw_data_usb_bulk_ep[FW_DATA_USB_BULK_EP_LEN] = {
+	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+	0x93, 0xCC, 0x0E, 0xB8, 0xFC, 0x83, 0x02, 0xC0, 0x01, 0x00, 0x00, 0x00,
+	0xF8, 0x83, 0x02, 0xC0, 0xCC, 0x1B, 0x6A, 0x41, 0xAC, 0x56, 0xD9, 0xEB};
+#endif
+
+#if defined(USB8978) || defined(SD8978)
+/** DPD curremt optimizations */
+t_u8 fw_data_dpd_current_opt[FW_DATA_DPD_CURRENT_OPT_LEN] = {
+	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+	0x93, 0xCC, 0x0E, 0xB8, 0xF8, 0xAF, 0x00, 0xB0, 0xCC, 0x1B, 0x6A, 0x41,
+	0xFC, 0xAF, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x00, 0xF5, 0x1D, 0xBA, 0x80};
+#endif
 
 /********************************************************
 			Local Functions
@@ -300,6 +325,71 @@ static mlan_status wlan_custom_ioctl_auto_delete(pmlan_private pmpriv,
 /********************************************************
 			Global Functions
 ********************************************************/
+/**
+ *  @brief Get custom Fw data
+ *
+ *  @param pmadapter    A pointer to mlan_adapter structure
+ *  @param pioctl_req   A pointer to custom Fw data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS --success, otherwise
+ * MLAN_STATUS_FAILURE
+ */
+mlan_status wlan_get_custom_fw_data(pmlan_adapter pmadapter, t_u8 *pdata)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u32 fw_data_param = pmadapter->init_para.fw_data_cfg;
+	t_u32 fw_data_param_num = 0, index = 0, i = 0;
+	fw_data_t *pfw_data_list = MNULL;
+
+	ENTER();
+	MASSERT(pmadapter);
+	if (MNULL == pdata) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	fw_data_param_num = MIN(MAX_FW_DATA_BLOCK, bitcount(fw_data_param));
+	pfw_data_list = (fw_data_t *)pdata;
+	for (i = 0; i < fw_data_param_num; i++) {
+		/** initilize the Fw data buffers with correct index */
+		while (fw_data_param) {
+			index = fw_data_param & (-fw_data_param);
+			switch (index) {
+#if defined(USB8978) || defined(SD8978)
+			case MBIT(0):
+				pfw_data_list[i].fw_data_buffer =
+					fw_data_fw_remap_config;
+				pfw_data_list[i].fw_data_buffer_len =
+					sizeof(fw_data_fw_remap_config);
+				break;
+#endif
+#if defined(USB8978)
+			case MBIT(1):
+				pfw_data_list[i].fw_data_buffer =
+					fw_data_usb_bulk_ep;
+				pfw_data_list[i].fw_data_buffer_len =
+					sizeof(fw_data_usb_bulk_ep);
+				break;
+#endif
+#if defined(USB8978) || defined(SD8978)
+			case MBIT(2):
+				pfw_data_list[i].fw_data_buffer =
+					fw_data_dpd_current_opt;
+				pfw_data_list[i].fw_data_buffer_len =
+					sizeof(fw_data_dpd_current_opt);
+				break;
+#endif
+			default:
+				break;
+			}
+			fw_data_param ^= index;
+			break;
+		}
+	}
+
+	LEAVE();
+	return ret;
+}
 
 /**
  *  @brief send host cmd
@@ -857,6 +947,40 @@ mlan_status wlan_pm_ioctl_hscfg(pmlan_adapter pmadapter,
 	return status;
 }
 
+/**
+ *  @brief Get/Set the firmware wakeup method
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
+ * otherwise fail
+ */
+mlan_status wlan_fw_wakeup_method(pmlan_adapter pmadapter,
+				  pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action;
+	mlan_ds_pm_cfg *pmcfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_FW_WAKE_METHOD,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &pmcfg->param.fw_wakeup_params);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+	LEAVE();
+	return ret;
+}
+
 /**
  *  @brief Set Robustcoex gpiocfg
  *
@@ -1388,6 +1512,14 @@ mlan_status wlan_misc_ioctl_custom_ie_list(pmlan_adapter pmadapter,
 		pioctl_req->action = MLAN_ACT_GET;
 		/* Get the IE */
 		cmd_action = HostCmd_ACT_GEN_GET;
+		ie_data = (custom_ie *)(((t_u8 *)&misc->param.cust_ie) +
+					sizeof(MrvlIEtypesHeader_t));
+		index = ie_data->ie_index;
+		if (index >= pmadapter->max_mgmt_ie_index) {
+			PRINTM(MERROR, "Invalid custom IE index %d\n", index);
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
 	} else {
 		/* ioctl_len : ioctl length from application, start with
 		 * misc->param.cust_ie.len and reach upto 0 */
@@ -1728,7 +1860,7 @@ mlan_status wlan_reg_mem_ioctl_reg_rw(pmlan_adapter pmadapter,
 	defined(PCIE9097) || defined(USB9097) || defined(SDIW624) ||           \
 	defined(SDAW693) || defined(PCIEAW693) || defined(PCIEIW624) ||        \
 	defined(USBIW624) || defined(SD9097) || defined(SD9177) ||             \
-	defined(SDIW615) || defined(USBIW615)
+	defined(SDIW610) || defined(USBIW610)
 	case MLAN_REG_CIU:
 		cmd_no = HostCmd_CMD_REG_ACCESS;
 		break;
@@ -1912,6 +2044,38 @@ done:
 	return sta_ptr;
 }
 
+/**
+ *  @brief This function deletes iPhone entry from llde device list
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     iPhone mac address to dekete in llde iPhone device list table
+ *
+ *  @return	   void
+ */
+void wlan_delete_iPhone_entry(mlan_private *priv, t_u8 *mac)
+{
+	t_u8 i = 0;
+
+	/* validate devices which are in llde_iphonefilters list are available
+	 */
+	for (i = 0; i < MAX_IPHONE_FILTER_ENTRIES; i++) {
+		if (memcmp(priv->adapter,
+			   &priv->adapter
+				    ->llde_iphonefilters[i *
+							 MLAN_MAC_ADDR_LENGTH],
+			   mac, MLAN_MAC_ADDR_LENGTH) == 0) {
+			/* remove device as it is not available */
+			// coverity[bad_memset: SUPPRESS]
+			memset(priv->adapter,
+			       (t_u8 *)&priv->adapter->llde_iphonefilters
+				       [i * MLAN_MAC_ADDR_LENGTH],
+			       0, MLAN_MAC_ADDR_LENGTH);
+			priv->adapter->llde_totalIPhones--;
+			break;
+		}
+	}
+}
+
 /**
  *  @brief This function will delete a station entry from station list
  *
@@ -1927,6 +2091,8 @@ t_void wlan_delete_station_entry(mlan_private *priv, t_u8 *mac)
 	ENTER();
 	sta_ptr = wlan_get_station_entry(priv, mac);
 	if (sta_ptr) {
+		if (sta_ptr->is_apple_sta)
+			wlan_delete_iPhone_entry(priv, mac);
 		util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list,
 				 (pmlan_linked_list)sta_ptr,
 				 priv->adapter->callbacks.moal_spin_lock,
@@ -3178,7 +3344,8 @@ mlan_status wlan_reg_rx_mgmt_ind(pmlan_adapter pmadapter,
 
 	/* Send request to firmware */
 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_MGMT_IND,
-			       pioctl_req->action, 0, (t_void *)pioctl_req,
+			       (t_u16)pioctl_req->action, 0,
+			       (t_void *)pioctl_req,
 			       &misc->param.mgmt_subtype_mask);
 
 	if (ret == MLAN_STATUS_SUCCESS)
@@ -3408,7 +3575,8 @@ mlan_status wlan_process_802dot11_mgmt_pkt(mlan_private *priv, t_u8 *payload,
 			       prx_pd->nf, prx_pd->snr);
 		}
 		if (memcmp(pmadapter, pieee_pkt_hdr->addr1, broadcast,
-			   MLAN_MAC_ADDR_LENGTH))
+			   MLAN_MAC_ADDR_LENGTH) &&
+		    !is_mcast_addr(pieee_pkt_hdr->addr1))
 			unicast = MTRUE;
 		break;
 	default:
@@ -3596,8 +3764,17 @@ mlan_status wlan_misc_multi_ap_cfg(pmlan_adapter pmadapter,
 
 	if (MLAN_ACT_GET == pioctl_req->action)
 		misc->param.multi_ap_flag = pmpriv->multi_ap_flag;
-	else if (MLAN_ACT_SET == pioctl_req->action)
+	else if (MLAN_ACT_SET == pioctl_req->action) {
+		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_APCMD_SYS_CONFIGURE,
+					       HostCmd_ACT_GEN_SET, 0,
+					       (t_void *)pioctl_req, MNULL);
+			if (ret == MLAN_STATUS_SUCCESS)
+				ret = MLAN_STATUS_PENDING;
+		}
 		pmpriv->multi_ap_flag = misc->param.multi_ap_flag;
+	}
 
 	LEAVE();
 	return ret;
@@ -3734,25 +3911,95 @@ static t_u8 wlan_check_ie_11b_support_rates(pIEEEtypes_Generic_t prates)
 #endif
 
 /**
- *  @brief check if Apple ie present.
+ *  @brief This function adds iPhone entry into llde device list
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param mac     iPhone mac address to add in llde iPhone device list table
+ *
+ *  @return	   void
+ */
+void wlan_add_iPhone_entry(mlan_private *priv, t_u8 *mac)
+{
+	t_u8 null_mac_addr[MLAN_MAC_ADDR_LENGTH] = {0};
+	t_u8 t_iphonefilters[MAX_IPHONE_FILTER_ENTRIES * MLAN_MAC_ADDR_LENGTH] =
+		{0};
+	int i = 0, j = 0;
+
+	/* reset count */
+	priv->adapter->llde_totalIPhones = 0;
+
+	if (MAX_IPHONE_FILTER_ENTRIES > 1) {
+		/* back up original list */
+		memcpy_ext(priv->adapter, &t_iphonefilters,
+			   &priv->adapter->llde_iphonefilters,
+			   MAX_IPHONE_FILTER_ENTRIES * MLAN_MAC_ADDR_LENGTH,
+			   MAX_IPHONE_FILTER_ENTRIES * MLAN_MAC_ADDR_LENGTH);
+
+		/* clear original list */
+		// coverity[bad_memset: SUPPRESS]
+		memset(priv->adapter,
+		       (t_u8 *)&priv->adapter->llde_iphonefilters, 0,
+		       MAX_IPHONE_FILTER_ENTRIES * MLAN_MAC_ADDR_LENGTH);
+
+		/* copy valid entries into original list */
+		for (i = 0, j = 1; i < MAX_IPHONE_FILTER_ENTRIES; i++) {
+			if (memcmp(priv->adapter,
+				   &t_iphonefilters[i * MLAN_MAC_ADDR_LENGTH],
+				   &null_mac_addr, MLAN_MAC_ADDR_LENGTH) != 0) {
+				memcpy_ext(
+					priv->adapter,
+					&priv->adapter->llde_iphonefilters
+						 [j++ * MLAN_MAC_ADDR_LENGTH],
+					&t_iphonefilters[i *
+							 MLAN_MAC_ADDR_LENGTH],
+					MLAN_MAC_ADDR_LENGTH,
+					MLAN_MAC_ADDR_LENGTH);
+			}
+		}
+	}
+
+	/* add latest connected device entry at the start of list to get high
+	 * priority while search in list */
+	if (MAX_IPHONE_FILTER_ENTRIES) {
+		memcpy_ext(priv->adapter, &priv->adapter->llde_iphonefilters[0],
+			   mac, MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	}
+
+	/* update connected device count */
+	for (i = 0; i < MAX_IPHONE_FILTER_ENTRIES; i++) {
+		if (memcmp(priv->adapter,
+			   &priv->adapter
+				    ->llde_iphonefilters[i *
+							 MLAN_MAC_ADDR_LENGTH],
+			   &null_mac_addr, MLAN_MAC_ADDR_LENGTH) != 0)
+			priv->adapter->llde_totalIPhones++;
+	}
+
+	return;
+}
+
+/**
+ *  @brief extracts all vendor specific oui's to pass it to fw in add_station
+ * cmd
  *
  *  @param pmadapter A pointer to mlan_adapter structure
+ *  @param sta_ptr A pointer to sta_node
  *  @param pbuf     A pointer to IE buffer
  *  @param buf_len  IE buffer len
  *
  *  @return         MTRUE/MFALSE
  */
-static t_u8 wlan_is_apple_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf,
-				     t_u16 buf_len)
+static void wlan_check_sta_vendor_ies(pmlan_adapter pmadapter,
+				      sta_node *sta_ptr, t_u8 *pbuf,
+				      t_u16 buf_len)
 {
 	t_u16 bytes_left = buf_len;
 	IEEEtypes_ElementId_e element_id;
 	t_u8 *pcurrent_ptr = pbuf;
-	t_u8 element_len;
+	t_u8 element_len, oui_pos = 0, index = 0, found_existing_oui = 0;
 	t_u16 total_ie_len;
 	IEEEtypes_VendorSpecific_t *pvendor_ie;
-	const t_u8 apple_oui[4] = {0x00, 0x17, 0xf2, 0x0a};
-	t_u8 found_apple_ie = MFALSE;
+	const t_u8 apple_oui[VENDOR_OUI_LEN] = {0x00, 0x17, 0xf2, 0x0a};
 
 	ENTER();
 
@@ -3773,8 +4020,35 @@ static t_u8 wlan_is_apple_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf,
 			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
 			if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
 				    apple_oui, sizeof(apple_oui))) {
-				found_apple_ie = MTRUE;
-				PRINTM(MINFO, "found Apple IE\n");
+				sta_ptr->is_apple_sta = MTRUE;
+			}
+			found_existing_oui = 0;
+			/* check if oui already present in list */
+			for (index = 0; index < sta_ptr->vendor_oui_count;
+			     index++) {
+				oui_pos = index * VENDOR_OUI_LEN;
+				if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+					    (t_u8 *)&sta_ptr
+						    ->vendor_oui[oui_pos],
+					    VENDOR_OUI_LEN)) {
+					found_existing_oui = 1;
+					break;
+				}
+			}
+			if ((found_existing_oui == 0) &&
+			    (sta_ptr->vendor_oui_count < MAX_VENDOR_OUI_NUM)) {
+				// add oui in list, sta_ptr->vendor_oui_count
+				// does not exceed MAX_VENDOR_OUI_NUM hence
+				// sta_ptr->vendor_oui buffer size does not
+				// exceed (MAX_VENDOR_OUI_NUM * VENDOR_OUI_LEN)
+				// coverity[overrun-buffer-arg: SUPPRESS]
+				memcpy_ext(pmadapter,
+					   (t_u8 *)&sta_ptr->vendor_oui
+						   [sta_ptr->vendor_oui_count *
+						    VENDOR_OUI_LEN],
+					   pvendor_ie->vend_hdr.oui,
+					   VENDOR_OUI_LEN, VENDOR_OUI_LEN);
+				sta_ptr->vendor_oui_count++;
 			}
 			break;
 		default:
@@ -3783,12 +4057,10 @@ static t_u8 wlan_is_apple_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf,
 		pcurrent_ptr += element_len + 2;
 		/* Need to account for IE ID and IE Len */
 		bytes_left -= (element_len + 2);
-		if (found_apple_ie)
-			break;
 	}
 
 	LEAVE();
-	return found_apple_ie;
+	return;
 }
 
 /**
@@ -3872,6 +4144,7 @@ void wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent,
 	t_u8 *rate = MNULL;
 	t_u8 b_only = MFALSE;
 #endif
+	t_u8 maxIPhoneEntries = MAX_IPHONE_FILTER_ENTRIES;
 
 	int tlv_buf_left = pevent->data_len - ASSOC_EVENT_FIX_SIZE;
 	MrvlIEtypesHeader_t *tlv =
@@ -3930,12 +4203,14 @@ void wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent,
 							       ie_len);
 				PRINTM(MCMND, "STA: is_wmm_enabled=%d\n",
 				       sta_ptr->is_wmm_enabled);
-				sta_ptr->is_apple_sta =
-					wlan_is_apple_ie_present(priv->adapter,
-								 assoc_req_ie,
-								 ie_len);
-				PRINTM(MINFO, "STA: is Apple device=%d\n",
-				       sta_ptr->is_apple_sta);
+
+				wlan_check_sta_vendor_ies(priv->adapter,
+							  sta_ptr, assoc_req_ie,
+							  ie_len);
+				if (sta_ptr->is_apple_sta && maxIPhoneEntries) {
+					wlan_add_iPhone_entry(
+						priv, sta_ptr->mac_addr);
+				}
 				pht_cap = (IEEEtypes_HTCap_t *)
 					wlan_get_specific_ie(priv, assoc_req_ie,
 							     ie_len,
@@ -4325,10 +4600,17 @@ mlan_status wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter,
 	defined(PCIE9097) || defined(USB9097) || defined(SDIW624) ||           \
 	defined(SDAW693) || defined(PCIEAW693) || defined(PCIEIW624) ||        \
 	defined(USBIW624) || defined(SD9097)
-			if (IS_CARD9098(pmadapter->card_type) ||
-			    IS_CARD9097(pmadapter->card_type) ||
-			    IS_CARDAW693(pmadapter->card_type) ||
-			    IS_CARDIW624(pmadapter->card_type)) {
+			if (IS_CARDAW693(pmadapter->card_type) &&
+			    ant_cfg->tx_antenna == RF_ANTENNA_AUTO) {
+				PRINTM(MCMND,
+				       "user_htstream=0x%x, tx_antenna=0x%x >rx_antenna=0x%x\n",
+				       pmadapter->user_htstream,
+				       ant_cfg->tx_antenna,
+				       ant_cfg->rx_antenna);
+			} else if (IS_CARD9098(pmadapter->card_type) ||
+				   IS_CARD9097(pmadapter->card_type) ||
+				   IS_CARDAW693(pmadapter->card_type) ||
+				   IS_CARDIW624(pmadapter->card_type)) {
 				ant_cfg->tx_antenna &= 0x0303;
 				ant_cfg->rx_antenna &= 0x0303;
 				/** 2G antcfg TX */
@@ -4378,10 +4660,11 @@ mlan_status wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter,
 			}
 #endif
 			if (!ant_cfg->tx_antenna ||
-			    bitcount(ant_cfg->tx_antenna & 0x00FF) >
-				    pmadapter->number_of_antenna ||
-			    bitcount(ant_cfg->tx_antenna & 0xFF00) >
-				    pmadapter->number_of_antenna) {
+			    (ant_cfg->tx_antenna != RF_ANTENNA_AUTO &&
+			     (bitcount(ant_cfg->tx_antenna & 0x00FF) >
+				      pmadapter->number_of_antenna ||
+			      bitcount(ant_cfg->tx_antenna & 0xFF00) >
+				      pmadapter->number_of_antenna))) {
 				PRINTM(MERROR,
 				       "Invalid TX antenna setting: 0x%x\n",
 				       ant_cfg->tx_antenna);
@@ -4390,6 +4673,7 @@ mlan_status wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter,
 				ret = MLAN_STATUS_FAILURE;
 				goto exit;
 			}
+
 			if (ant_cfg->rx_antenna) {
 				if (bitcount(ant_cfg->rx_antenna & 0x00FF) >
 					    pmadapter->number_of_antenna ||
@@ -4403,8 +4687,11 @@ mlan_status wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter,
 					ret = MLAN_STATUS_FAILURE;
 					goto exit;
 				}
-			} else
-				ant_cfg->rx_antenna = ant_cfg->tx_antenna;
+			} else {
+				if (ant_cfg->tx_antenna != RF_ANTENNA_AUTO)
+					ant_cfg->rx_antenna =
+						ant_cfg->tx_antenna;
+			}
 		} else if (!radio_cfg->param.ant_cfg_1x1.antenna ||
 			   ((radio_cfg->param.ant_cfg_1x1.antenna !=
 			     RF_ANTENNA_AUTO) &&
@@ -5275,6 +5562,47 @@ mlan_status wlan_misc_ioctl_cross_chip_synch(pmlan_adapter pmadapter,
 	return ret;
 }
 
+/**
+ *  @brief Set/Get TSP config
+ *
+ *  @param pmadapter	A pointer to mlan_adapter structure
+ *  @param pioctl_req	A pointer to ioctl request buffer
+ *
+ *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+mlan_status wlan_misc_ioctl_tsp_config(pmlan_adapter pmadapter,
+				       pmlan_ioctl_req pioctl_req)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+	t_u16 cmd_action = 0;
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+
+	ENTER();
+
+	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else if (pioctl_req->action == MLAN_ACT_GET)
+		cmd_action = HostCmd_ACT_GEN_GET;
+	else {
+		PRINTM(MERROR, "Unsupported cmd_action\n");
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+
+	/* Send request to firmware */
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TSP_CFG, cmd_action, 0,
+			       (t_void *)pioctl_req,
+			       &misc_cfg->param.gpio_tsf_latch_config);
+
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
 /**
  *  @brief Set coalesce config
  *
@@ -6568,33 +6896,37 @@ mlan_status wlan_misc_chan_reg_cfg(pmlan_adapter pmadapter,
 
 	ENTER();
 
-	if (pioctl_req->action == MLAN_ACT_GET)
-		cmd_action = HostCmd_ACT_GEN_GET;
-	else {
-		PRINTM(MERROR, "No support set channel region cfg!");
-		LEAVE();
-		return MLAN_STATUS_FAILURE;
-	}
-
 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
-	if (misc_cfg &&
-	    misc_cfg->param.custom_reg_domain.region.country_code[0] != '\0' &&
-	    misc_cfg->param.custom_reg_domain.region.country_code[1] != '\0') {
-		/* Copy the driver country code in the custom_reg_domain. The
-		 * cmd response handler will use it to compare with the FW
-		 * country code
-		 */
-		pmadapter->country_code[0] =
-			misc_cfg->param.custom_reg_domain.region.country_code[0];
-		pmadapter->country_code[1] =
-			misc_cfg->param.custom_reg_domain.region.country_code[1];
-		pmadapter->country_code[2] = '\0';
+	if (pioctl_req->action == MLAN_ACT_GET) {
+		cmd_action = HostCmd_ACT_GEN_GET;
+		if (misc_cfg &&
+		    misc_cfg->param.custom_reg_domain.region.country_code[0] !=
+			    '\0' &&
+		    misc_cfg->param.custom_reg_domain.region.country_code[1] !=
+			    '\0') {
+			/* Copy the driver country code in the
+			 * custom_reg_domain. The cmd response handler will use
+			 * it to compare with the FW country code
+			 */
+			pmadapter->country_code[0] =
+				misc_cfg->param.custom_reg_domain.region
+					.country_code[0];
+			pmadapter->country_code[1] =
+				misc_cfg->param.custom_reg_domain.region
+					.country_code[1];
+			pmadapter->country_code[2] = '\0';
+		}
+		/* Send 2G/5G/6G CFP table request to the firmware */
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CHAN_REGION_CFG,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       MNULL);
+	} else {
+		cmd_action = HostCmd_ACT_GEN_SET;
+		/* Send 2G/5G/6G CFP table to the firmware */
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CHAN_REGION_CFG,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       &misc_cfg->param.chan_attr_cfg);
 	}
-
-	/* Send 2G/5G CFP table request to firmware */
-	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CHAN_REGION_CFG, cmd_action,
-			       0, (t_void *)pioctl_req, MNULL);
-
 	if (ret == MLAN_STATUS_SUCCESS)
 		ret = MLAN_STATUS_PENDING;
 
@@ -6758,7 +7090,7 @@ mlan_status wlan_misc_ioctl_ch_load(pmlan_adapter pmadapter,
 		return MLAN_STATUS_FAILURE;
 	pmpriv = pmadapter->priv[pioctl_req->bss_index];
 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
-	cmd_action = pioctl_req->action;
+	cmd_action = (t_u16)pioctl_req->action;
 
 	/* Send request to firmware */
 	pmpriv->ch_load_param = 255; /* Default value for identifying
@@ -7548,6 +7880,21 @@ mlan_status wlan_misc_ioctl_rf_test_cfg(pmlan_adapter pmadapter,
 				       cmd_action, 0, (t_void *)pioctl_req,
 				       &(pmisc->param.mfg_otp_mac_addr_rd_wr));
 		break;
+
+	case MLAN_OID_MISC_OTP_CAL_DATA_RD_WR:
+		if (pioctl_req->action == MLAN_ACT_SET)
+			cmd_action = HostCmd_ACT_GEN_SET;
+		else if (pioctl_req->action == MLAN_ACT_GET)
+			cmd_action = HostCmd_ACT_GEN_GET;
+		else {
+			PRINTM(MERROR, "Unsupported cmd_action\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
+				       cmd_action, 0, (t_void *)pioctl_req,
+				       &(pmisc->param.mfg_otp_cal_data_rd_wr));
+		break;
 	}
 
 	if (ret == MLAN_STATUS_SUCCESS)
@@ -7909,11 +8256,42 @@ mlan_status wlan_misc_ioctl_edmac_cfg(pmlan_adapter pmadapter,
 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
 
 	if (MLAN_ACT_SET == pioctl_req->action) {
-		misc->param.edmac_cfg.ed_ctrl_2g = 0x1;
-		misc->param.edmac_cfg.ed_offset_2g = 0x8;
-		misc->param.edmac_cfg.ed_ctrl_5g = 0x1;
-		misc->param.edmac_cfg.ed_offset_5g = 0x8;
-		misc->param.edmac_cfg.ed_bitmap_txq_lock = 0x1e00FF;
+		if (IS_CARD9098(pmadapter->card_type) ||
+		    IS_CARD9097(pmadapter->card_type) ||
+		    IS_CARDAW693(pmadapter->card_type) ||
+		    IS_CARDIW624(pmadapter->card_type) ||
+		    IS_CARDIW610(pmadapter->card_type)) {
+			misc->param.edmac_cfg.ed_ctrl_2g = 0x1;
+			misc->param.edmac_cfg.ed_offset_2g = 0x8;
+			misc->param.edmac_cfg.ed_ctrl_5g = 0x1;
+			misc->param.edmac_cfg.ed_offset_5g = 0x8;
+			misc->param.edmac_cfg.ed_bitmap_txq_lock = 0x1e00FF;
+		} else if (IS_CARD9177(pmadapter->card_type)) {
+			// from config/ed_mac_ctrl_V2_nw61x.conf
+			misc->param.edmac_cfg.ed_ctrl_2g = 0x1;
+			misc->param.edmac_cfg.ed_offset_2g = 0xA;
+			misc->param.edmac_cfg.ed_ctrl_5g = 0x1;
+			misc->param.edmac_cfg.ed_offset_5g = 0xA;
+			misc->param.edmac_cfg.ed_bitmap_txq_lock = 0x1e00FF;
+		} else if (IS_CARD8997(pmadapter->card_type)) {
+			// from config/ed_mac_ctrl_V2_8997.conf
+			misc->param.edmac_cfg.ed_ctrl_2g = 0x1;
+			misc->param.edmac_cfg.ed_offset_2g = 0x0;
+			misc->param.edmac_cfg.ed_ctrl_5g = 0x1;
+			misc->param.edmac_cfg.ed_offset_5g = 0x4;
+			misc->param.edmac_cfg.ed_bitmap_txq_lock = 0xFF;
+		} else if (IS_CARD8978(pmadapter->card_type)) {
+			// from config/ed_mac_ctrl_V2_iw416.conf
+			misc->param.edmac_cfg.ed_ctrl_2g = 0x1;
+			misc->param.edmac_cfg.ed_offset_2g = 0x9;
+			misc->param.edmac_cfg.ed_ctrl_5g = 0x1;
+			misc->param.edmac_cfg.ed_offset_5g = 0xC;
+			misc->param.edmac_cfg.ed_bitmap_txq_lock = 0xFF;
+		} else {
+			PRINTM(MERROR, "Failed to configure edmac param");
+			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
+			return MLAN_STATUS_FAILURE;
+		}
 	} else {
 		misc->param.edmac_cfg.ed_ctrl_2g = 0x0;
 		misc->param.edmac_cfg.ed_ctrl_5g = 0x0;
@@ -8111,3 +8489,41 @@ fail:
 	status = MFALSE;
 	goto ret;
 }
+
+/**
+ *  @brief Prints verbose msg of 6G chan_switch block event for the reason_code
+ *
+ *  @param reason_code       Reason code contained in event body
+ *
+ *  @return                  N/A
+ */
+void print_chan_switch_block_event(t_u16 reason_code)
+{
+	ENTER();
+	switch (reason_code) {
+	case BLOCK_6G_CHAN_SWITCH_REASON_STA_RX_ECSA:
+		PRINTM(MEVENT,
+		       "EVENT: Mobile-AP does not support HE-Cap/WPA3"
+		       " to switch to 6Ghz, leading to RX ECSA Failure of STA\n");
+		break;
+	case BLOCK_6G_CHAN_SWITCH_REASON_MMH_STA:
+		PRINTM(MEVENT,
+		       "EVENT: Mobile-AP does not support HE-Cap/WPA3"
+		       " to switch to 6Ghz, leading to 6Ghz Assoc Failure of STA\n");
+		break;
+	case BLOCK_6G_CHAN_SWITCH_REASON_STA_MMH:
+		PRINTM(MEVENT,
+		       "EVENT: Mobile-AP does not support HE-Cap/WPA3"
+		       " to switch to 6Ghz channel same as STA, leading to bss start failure");
+		break;
+	case BLOCK_6G_CHAN_SWITCH_REASON_MMH:
+		PRINTM(MEVENT,
+		       "EVENT: Mobile-AP does not support HE-Cap/WPA3"
+		       " to switch to 6Ghz channel, leading to chan_switch failure");
+		break;
+	default:
+		break;
+	}
+	LEAVE();
+	return;
+}
diff --git a/mlan/mlan_pcie.c b/mlan/mlan_pcie.c
index 96004c4..3575a9a 100644
--- a/mlan/mlan_pcie.c
+++ b/mlan/mlan_pcie.c
@@ -270,7 +270,8 @@ static mlan_status wlan_init_dma_cfg_registers(mlan_adapter *pmadapter,
 					       t_u8 dma_mode, t_u16 size,
 					       t_u8 init)
 {
-	t_u32 dma_cfg, dma_cfg2, dma_cfg3;
+	t_u32 dma_cfg, dma_cfg2 = 0;
+	t_u32 dma_cfg3 = 0;
 	pmlan_callbacks pcb = &pmadapter->callbacks;
 	mlan_status ret = MLAN_STATUS_SUCCESS;
 
@@ -532,11 +533,16 @@ static mlan_status wlan_init_adma(mlan_adapter *pmadapter, t_u8 type,
 			}
 		}
 	}
-	if (wlan_init_dma_cfg_registers(pmadapter, q_addr, direction, dma_mode,
-					size, init)) {
-		PRINTM(MERROR, "Failed to configure dma_cfg registers\n");
-		ret = MLAN_STATUS_FAILURE;
-		goto done;
+	if (!IS_PCIEIW624(pmadapter->card_type) &&
+	    !(IS_PCIEAW693(pmadapter->card_type) &&
+	      (pmadapter->card_rev > CHIP_AW693_REV_A0))) {
+		if (wlan_init_dma_cfg_registers(pmadapter, q_addr, direction,
+						dma_mode, size, init)) {
+			PRINTM(MERROR,
+			       "Failed to configure dma_cfg registers\n");
+			ret = MLAN_STATUS_FAILURE;
+			goto done;
+		}
 	}
 
 	if (type == ADMA_CMD && !init) {
@@ -968,9 +974,20 @@ static mlan_status wlan_pcie_send_vdll(mlan_adapter *pmadapter,
 	defined(PCIEIW624)
 	/* issue the DMA */
 	if (pmadapter->pcard_pcie->reg->use_adma) {
-		/* send the VDLL block down to the firmware */
-		wlan_init_adma(pmadapter, ADMA_CMD, pmbuf->buf_pa,
-			       pmbuf->data_len, MFALSE);
+		if (IS_PCIEIW624(pmadapter->card_type) ||
+		    (IS_PCIEAW693(pmadapter->card_type) &&
+		     (pmadapter->card_rev > CHIP_AW693_REV_A0))) {
+			if (wlan_pcie_send_boot_cmd(pmadapter, pmbuf, MFALSE)) {
+				PRINTM(MERROR,
+				       "Failed to send vdll block to device\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		} else {
+			/* send the VDLL block down to the firmware */
+			wlan_init_adma(pmadapter, ADMA_CMD, pmbuf->buf_pa,
+				       pmbuf->data_len, MFALSE);
+		}
 	}
 #endif
 
@@ -1852,7 +1869,7 @@ static mlan_status wlan_pcie_alloc_cmdrsp_buf(mlan_adapter *pmadapter)
 	pmlan_callbacks pcb = &pmadapter->callbacks;
 	mlan_status ret = MLAN_STATUS_SUCCESS;
 	/** Virtual base address of command response */
-	t_u8 *cmdrsp_vbase;
+	t_u8 *cmdrsp_vbase = MNULL;
 	/** Physical base address of command response */
 	t_u64 cmdrsp_pbase = 0;
 
@@ -2029,7 +2046,7 @@ static mlan_status wlan_pcie_send_data_complete(mlan_adapter *pmadapter)
 	pmlan_callbacks pcb = &pmadapter->callbacks;
 	mlan_buffer *pmbuf;
 	t_u32 wrdoneidx;
-	t_u32 rdptr;
+	t_u32 rdptr = 0;
 	t_u32 unmap_count = 0;
 #if defined(PCIE8997) || defined(PCIE8897)
 	t_u32 txrx_rw_ptr_mask = pmadapter->pcard_pcie->reg->txrx_rw_ptr_mask;
@@ -2395,9 +2412,10 @@ static mlan_status wlan_pcie_send_adma_data(mlan_adapter *pmadapter,
 		if (wlan_check_txbd_not_full(pmadapter)) {
 #ifdef PCIEAW693
 			if (IS_PCIEAW693(pmadapter->card_type) &&
-			    (wlan_pcie_get_max_msdu_cnt(pmadapter) < 2))
+			    (wlan_pcie_get_max_msdu_cnt(pmadapter) < 2)) {
 				pmadapter->data_sent = MTRUE;
-			else
+				wlan_pcie_process_tx_complete(pmadapter);
+			} else
 #endif
 				pmadapter->data_sent = MFALSE;
 		} else
@@ -2626,9 +2644,10 @@ static mlan_status wlan_pcie_send_data(mlan_adapter *pmadapter, t_u8 type,
 		if (wlan_check_txbd_not_full(pmadapter)) {
 #ifdef PCIEAW693
 			if (IS_PCIEAW693(pmadapter->card_type) &&
-			    (wlan_pcie_get_max_msdu_cnt(pmadapter) < 2))
+			    (wlan_pcie_get_max_msdu_cnt(pmadapter) < 2)) {
 				pmadapter->data_sent = MTRUE;
-			else
+				wlan_pcie_process_tx_complete(pmadapter);
+			} else
 #endif
 				pmadapter->data_sent = MFALSE;
 		} else
@@ -2803,7 +2822,8 @@ static mlan_status wlan_pcie_process_recv_data(mlan_adapter *pmadapter)
 {
 	mlan_status ret = MLAN_STATUS_SUCCESS;
 	pmlan_callbacks pcb = &pmadapter->callbacks;
-	t_u32 rdptr, rd_index;
+	t_u32 rdptr = 0;
+	t_u32 rd_index;
 	mlan_buffer *pmbuf = MNULL;
 	t_u32 txbd_val = 0;
 	t_u16 rx_len = 0, rx_type;
@@ -2819,7 +2839,8 @@ static mlan_status wlan_pcie_process_recv_data(mlan_adapter *pmadapter)
 	defined(PCIEIW624)
 	adma_dual_desc_buf *padma_bd_buf;
 #endif
-	t_u32 in_ts_sec, in_ts_usec;
+	t_u32 in_ts_sec = 0;
+	t_u32 in_ts_usec = 0;
 
 	ENTER();
 
@@ -3187,10 +3208,21 @@ static mlan_status wlan_pcie_send_cmd(mlan_adapter *pmadapter,
 		wlan_init_adma(pmadapter, ADMA_CMDRESP,
 			       pmadapter->pcard_pcie->cmdrsp_buf->buf_pa,
 			       MRVDRV_SIZE_OF_CMD_BUFFER, MFALSE);
-		wlan_init_adma(pmadapter, ADMA_CMD,
-			       pmadapter->pcard_pcie->cmd_buf->buf_pa,
-			       pmadapter->pcard_pcie->cmd_buf->data_len,
-			       MFALSE);
+		if (IS_PCIEIW624(pmadapter->card_type) ||
+		    (IS_PCIEAW693(pmadapter->card_type) &&
+		     (pmadapter->card_rev > CHIP_AW693_REV_A0))) {
+			if (wlan_pcie_send_boot_cmd(pmadapter, pmbuf, MFALSE)) {
+				PRINTM(MERROR,
+				       "Failed to send vdll block to device\n");
+				ret = MLAN_STATUS_FAILURE;
+				goto done;
+			}
+		} else {
+			wlan_init_adma(pmadapter, ADMA_CMD,
+				       pmadapter->pcard_pcie->cmd_buf->buf_pa,
+				       pmadapter->pcard_pcie->cmd_buf->data_len,
+				       MFALSE);
+		}
 	}
 #endif
 done:
@@ -3441,7 +3473,8 @@ static mlan_status wlan_pcie_process_event_ready(mlan_adapter *pmadapter)
 {
 	t_u32 rd_index =
 		pmadapter->pcard_pcie->evtbd_rdptr & (MLAN_MAX_EVT_BD - 1);
-	t_u32 rdptr, event;
+	t_u32 rdptr = 0;
+	t_u32 event;
 	pmlan_callbacks pcb = &pmadapter->callbacks;
 #if defined(PCIE8997) || defined(PCIE8897)
 	mlan_pcie_evt_buf *pevtbd_buf;
@@ -3639,7 +3672,7 @@ static mlan_status wlan_pcie_event_complete(mlan_adapter *pmadapter,
 	pmlan_callbacks pcb = &pmadapter->callbacks;
 	t_u32 wrptr =
 		pmadapter->pcard_pcie->evtbd_wrptr & (MLAN_MAX_EVT_BD - 1);
-	t_u32 rdptr;
+	t_u32 rdptr = 0;
 #if defined(PCIE8997) || defined(PCIE8897)
 	mlan_pcie_evt_buf *pevtbd_buf;
 #endif
@@ -4171,7 +4204,7 @@ mlan_status wlan_pcie_wakeup(mlan_adapter *pmadapter)
  */
 static mlan_status wlan_pcie_interrupt(t_u16 msg_id, pmlan_adapter pmadapter)
 {
-	t_u32 pcie_ireg;
+	t_u32 pcie_ireg = 0;
 	pmlan_callbacks pcb = &pmadapter->callbacks;
 	t_void *pmoal_handle = pmadapter->pmoal_handle;
 	t_void *pint_lock = pmadapter->pint_lock;
@@ -4487,7 +4520,7 @@ static mlan_status wlan_pcie_check_fw_status(mlan_adapter *pmadapter,
 {
 	mlan_status ret = MLAN_STATUS_SUCCESS;
 	pmlan_callbacks pcb = &pmadapter->callbacks;
-	t_u32 firmware_stat;
+	t_u32 firmware_stat = 0;
 	t_u32 tries;
 
 	ENTER();
@@ -4663,7 +4696,7 @@ mlan_status wlan_alloc_ssu_pcie_buf(pmlan_adapter pmadapter)
 	pmlan_callbacks pcb = &pmadapter->callbacks;
 	mlan_buffer *pmbuf = MNULL;
 	/** Virtual base address of ssu buffer */
-	t_u8 *ssu_vbase;
+	t_u8 *ssu_vbase = MNULL;
 	/** Physical base address of ssu buffer */
 	t_u64 ssu_pbase = 0;
 
@@ -4874,6 +4907,12 @@ mlan_status wlan_set_pcie_buf_config(mlan_private *pmpriv)
 	pmlan_adapter pmadapter = MNULL;
 #if defined(PCIE8997) || defined(PCIE8897)
 	HostCmd_DS_PCIE_HOST_BUF_DETAILS host_spec;
+#endif
+#if defined(PCIE)
+#if defined(PCIE9098) || defined(PCIE9097) || defined(PCIEAW693) ||            \
+	defined(PCIEIW624)
+	HostCmd_DS_PCIE_ADMA_INIT pcie_adma_cfg;
+#endif
 #endif
 	mlan_status ret = MLAN_STATUS_SUCCESS;
 
@@ -4925,6 +4964,26 @@ mlan_status wlan_set_pcie_buf_config(mlan_private *pmpriv)
 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIEAW693) ||            \
 	defined(PCIEIW624)
 	if (pmadapter->pcard_pcie->reg->use_adma) {
+		if (IS_PCIEIW624(pmadapter->card_type) ||
+		    (IS_PCIEAW693(pmadapter->card_type) &&
+		     (pmadapter->card_rev > CHIP_AW693_REV_A0))) {
+			pcie_adma_cfg.tx_ring_size =
+				pmadapter->pcard_pcie->txrx_bd_size;
+			pcie_adma_cfg.rx_ring_size =
+				pmadapter->pcard_pcie->txrx_bd_size;
+			pcie_adma_cfg.evt_ring_size = MLAN_MAX_EVT_BD;
+			pcie_adma_cfg.int_mode =
+				pmadapter->pcard_pcie->pcie_int_mode;
+			ret = wlan_prepare_cmd(pmpriv,
+					       HostCmd_CMD_PCIE_ADMA_INIT,
+					       HostCmd_ACT_GEN_SET, 0, MNULL,
+					       &pcie_adma_cfg);
+			if (ret) {
+				PRINTM(MERROR,
+				       "PCIE_ADMA_INIT: send command failed\n");
+				ret = MLAN_STATUS_FAILURE;
+			}
+		}
 		/** config ADMA for Tx Data */
 		wlan_init_adma(pmadapter, ADMA_TX_DATA,
 			       pmadapter->pcard_pcie->txbd_ring_pbase,
@@ -4985,6 +5044,40 @@ mlan_status wlan_cmd_pcie_host_buf_cfg(pmlan_private pmpriv,
 }
 #endif
 
+#if defined(PCIE)
+/**
+ *  @brief This function prepares command PCIE ADMA init.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_cmd_pcie_adma_init(pmlan_private pmpriv,
+				    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
+				    t_pvoid pdata_buf)
+{
+	HostCmd_DS_PCIE_ADMA_INIT *ppcie_adma_cfg =
+		&cmd->params.pcie_adma_config;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_PCIE_ADMA_INIT);
+	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_PCIE_ADMA_INIT)) +
+				     S_DS_GEN);
+
+	if (cmd_action == HostCmd_ACT_GEN_SET) {
+		memcpy_ext(pmpriv->adapter, ppcie_adma_cfg, pdata_buf,
+			   sizeof(HostCmd_DS_PCIE_ADMA_INIT),
+			   sizeof(HostCmd_DS_PCIE_ADMA_INIT));
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+#endif
+
 /**
  *  @brief This function wakes up the card.
  *
@@ -5228,7 +5321,9 @@ static mlan_status wlan_pcie_send_data_list(mlan_adapter *pmadapter, t_u8 type,
 		return MLAN_STATUS_FAILURE;
 	}
 #endif
-	if (wlan_is_tx_pending(pmadapter))
+	if ((((pmadapter->pcard_pcie->txbd_wrptr >> 1) %
+	      TX_DONE_POLL_DISTANCE) == 0) &&
+	    wlan_is_tx_pending(pmadapter))
 		wlan_pcie_process_tx_complete(pmadapter);
 
 	if (num_pkt == 1) {
diff --git a/mlan/mlan_pcie.h b/mlan/mlan_pcie.h
index a472d3c..ca1e6ac 100644
--- a/mlan/mlan_pcie.h
+++ b/mlan/mlan_pcie.h
@@ -466,6 +466,9 @@ Change log:
 /** Max interrupt status register read limit */
 #define MAX_READ_REG_RETRY 10000
 
+/* check TX done ring on every X pushed packets */
+#define TX_DONE_POLL_DISTANCE 16
+
 extern mlan_adapter_operations mlan_pcie_ops;
 
 /* Get pcie device from card type */
@@ -481,6 +484,13 @@ mlan_status wlan_cmd_pcie_host_buf_cfg(pmlan_private pmpriv,
 				       t_u16 cmd_action, t_pvoid pdata_buf);
 #endif
 
+#if defined(PCIE)
+/** Prepare command PCIE host buffer config */
+mlan_status wlan_cmd_pcie_adma_init(pmlan_private pmpriv,
+				    pHostCmd_DS_COMMAND cmd, t_u16 cmd_action,
+				    t_pvoid pdata_buf);
+#endif
+
 /** Wakeup PCIE card */
 mlan_status wlan_pcie_wakeup(pmlan_adapter pmadapter);
 
diff --git a/mlan/mlan_scan.c b/mlan/mlan_scan.c
index 196eb65..84c3456 100644
--- a/mlan/mlan_scan.c
+++ b/mlan/mlan_scan.c
@@ -407,7 +407,7 @@ static t_u8 is_wpa_oui_present(mlan_adapter *pmadapter,
  *  @return  matched: non-zero. unmatched: 0
  *
  */
-static t_u8 wlan_is_band_compatible(t_u8 cfg_band, t_u8 scan_band)
+static t_u16 wlan_is_band_compatible(t_u16 cfg_band, t_u16 scan_band)
 {
 	t_u16 band;
 	switch (scan_band) {
@@ -2341,6 +2341,23 @@ static mlan_status wlan_interpret_bss_desc_with_ie(pmlan_adapter pmadapter,
 					(t_u16)(pcurrent_ptr -
 						pbss_entry->pbeacon_buf);
 				break;
+			case MU_EDCA_PARAM_SET:
+				PRINTM(MCMND, "MU-EDCA IE received\n");
+				pbss_entry->pmuedca_ie =
+					(IEEEtypes_MUEDCAParamSet_t *)
+						pcurrent_ptr;
+				pbss_entry->muedca_offset =
+					(t_u16)(pcurrent_ptr -
+						pbss_entry->pbeacon_buf);
+				break;
+			case MBSSID_CONFIG:
+				pbss_entry->pmbssid_config =
+					(IEEEtypes_MBSSID_Config_t *)
+						pcurrent_ptr;
+				pbss_entry->mbssid_config_offset =
+					(t_u16)(pcurrent_ptr -
+						pbss_entry->pbeacon_buf);
+				break;
 			default:
 				break;
 			}
@@ -2495,11 +2512,24 @@ static t_void wlan_adjust_ie_in_bss_entry(mlan_private *pmpriv,
 					 *)(pbss_entry->pbeacon_buf +
 					    pbss_entry->he_oprat_offset);
 		}
+
+		if (pbss_entry->pmuedca_ie) {
+			pbss_entry->pmuedca_ie =
+				(IEEEtypes_MUEDCAParamSet_t
+					 *)(pbss_entry->pbeacon_buf +
+					    pbss_entry->muedca_offset);
+		}
 		if (pbss_entry->prsnx_ie) {
 			pbss_entry->prsnx_ie =
 				(IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
 							pbss_entry->rsnx_offset);
 		}
+		if (pbss_entry->pmbssid_config) {
+			pbss_entry->pmbssid_config =
+				(IEEEtypes_MBSSID_Config_t
+					 *)(pbss_entry->pbeacon_buf +
+					    pbss_entry->mbssid_config_offset);
+		}
 	} else {
 		pbss_entry->pwpa_ie = MNULL;
 		pbss_entry->wpa_offset = 0;
@@ -2522,6 +2552,10 @@ static t_void wlan_adjust_ie_in_bss_entry(mlan_private *pmpriv,
 		pbss_entry->ext_cap_offset = 0;
 		pbss_entry->poverlap_bss_scan_param = MNULL;
 		pbss_entry->overlap_bss_offset = 0;
+		pbss_entry->pmuedca_ie = MNULL;
+		pbss_entry->muedca_offset = 0;
+		pbss_entry->pmbssid_config = MNULL;
+		pbss_entry->mbssid_config_offset = 0;
 	}
 	LEAVE();
 	return;
@@ -2830,10 +2864,18 @@ static t_void wlan_ret_802_11_scan_store_beacon(mlan_private *pmpriv,
 				pnew_beacon->he_oprat_offset =
 					pmadapter->pscan_table[beacon_idx]
 						.he_oprat_offset;
+			if (pnew_beacon->pmuedca_ie)
+				pnew_beacon->muedca_offset =
+					pmadapter->pscan_table[beacon_idx]
+						.muedca_offset;
 			if (pnew_beacon->prsnx_ie)
 				pnew_beacon->rsnx_offset =
 					pmadapter->pscan_table[beacon_idx]
 						.rsnx_offset;
+			if (pnew_beacon->pmbssid_config)
+				pnew_beacon->mbssid_config_offset =
+					pmadapter->pscan_table[beacon_idx]
+						.mbssid_config_offset;
 		}
 		/* Point the new entry to its permanent storage space */
 		pnew_beacon->pbeacon_buf = pbcn_store;
@@ -3094,12 +3136,24 @@ static mlan_status wlan_update_curr_bcn(mlan_private *pmpriv)
 					 *)(pcurr_bss->pbeacon_buf +
 					    pcurr_bss->he_oprat_offset);
 		}
+
+		if (pcurr_bss->pmuedca_ie) {
+			pcurr_bss->pmuedca_ie =
+				(IEEEtypes_MUEDCAParamSet_t
+					 *)(pcurr_bss->pbeacon_buf +
+					    pcurr_bss->muedca_offset);
+		}
 		if (pcurr_bss->prsnx_ie) {
 			pcurr_bss->prsnx_ie =
 				(IEEEtypes_Generic_t *)(pcurr_bss->pbeacon_buf +
 							pcurr_bss->rsnx_offset);
 		}
-
+		if (pcurr_bss->pmbssid_config) {
+			pcurr_bss->pmbssid_config =
+				(IEEEtypes_MBSSID_Config_t
+					 *)(pcurr_bss->pbeacon_buf +
+					    pcurr_bss->mbssid_config_offset);
+		}
 		PRINTM(MINFO, "current beacon restored %d\n",
 		       pmpriv->curr_bcn_size);
 	} else {
@@ -3314,8 +3368,16 @@ static t_void wlan_scan_process_results(mlan_private *pmpriv)
 				MNULL;
 			pmpriv->curr_bss_params.bss_descriptor.he_oprat_offset =
 				0;
+			pmpriv->curr_bss_params.bss_descriptor.pmuedca_ie =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor.muedca_offset =
+				0;
 			pmpriv->curr_bss_params.bss_descriptor.prsnx_ie = MNULL;
 			pmpriv->curr_bss_params.bss_descriptor.rsnx_offset = 0;
+			pmpriv->curr_bss_params.bss_descriptor.pmbssid_config =
+				MNULL;
+			pmpriv->curr_bss_params.bss_descriptor
+				.mbssid_config_offset = 0;
 			pmpriv->curr_bss_params.bss_descriptor.pbeacon_buf =
 				MNULL;
 			pmpriv->curr_bss_params.bss_descriptor.beacon_buf_size =
@@ -3695,6 +3757,26 @@ static t_void wlan_scan_delete_table_entry(mlan_private *pmpriv,
 							    ->pscan_table[del_idx]
 							    .he_oprat_offset);
 			}
+			if (pmadapter->pscan_table[del_idx].pmuedca_ie) {
+				pmadapter->pscan_table[del_idx].pmuedca_ie =
+					(IEEEtypes_MUEDCAParamSet_t
+						 *)(pmadapter
+							    ->pscan_table[del_idx]
+							    .pbeacon_buf +
+						    pmadapter
+							    ->pscan_table[del_idx]
+							    .muedca_offset);
+			}
+			if (pmadapter->pscan_table[del_idx].pmbssid_config) {
+				pmadapter->pscan_table[del_idx].pmbssid_config =
+					(IEEEtypes_MBSSID_Config_t
+						 *)(pmadapter
+							    ->pscan_table[del_idx]
+							    .pbeacon_buf +
+						    pmadapter
+							    ->pscan_table[del_idx]
+							    .mbssid_config_offset);
+			}
 		}
 	}
 
@@ -5203,148 +5285,535 @@ done:
 /** 8 bytes timestamp, 2 bytest interval, 2 bytes capability */
 #define BEACON_FIX_SIZE 12
 
+/* Element iteration helpers */
+#define for_each_element(_elem, _data, _datalen)                               \
+	for (_elem = (IEEEtypes_Element_t *)(_data);                           \
+	     (const t_u8 *)(_data) + (_datalen) - (const t_u8 *)_elem >=       \
+		     (int)sizeof(*_elem) &&                                    \
+	     (const t_u8 *)(_data) + (_datalen) - (const t_u8 *)_elem >=       \
+		     (int)sizeof(*_elem) + _elem->ieee_hdr.len;                \
+	     _elem = (IEEEtypes_Element_t *)(_elem->data +                     \
+					     _elem->ieee_hdr.len))
+
+#define for_each_element_id(element, _id, data, datalen)                       \
+	for_each_element (element, data, datalen)                              \
+		if (element->ieee_hdr.element_id == (_id))
+
 /**
- *  @brief This function realloc the beacon buffer and update ssid for new entry
- *
- *  @param pmadpater        A pointer to mlan_adapter structure
- *  @param pbss_entry       A pointer to the bss_entry which has multi-bssid IE
- *  @param pnew_entry       A pinter to new entry
- *  @param pssid            A pointer to ssid IE
- *
- *  @return                MLAN_STATUS_FAILURE/MLAN_STATUS_SUCCESS
+ *  @brief This function updates the NonTx BSS Descriptor entry before adding
+ *         it to the scan table
+ *  @param pmadapter	A pointer to mlan adapter
+ *  @param pbss_entry	A pointer to the parent BSS descriptor entry
+ *  @param pnew_entry   A pointer to the nonTx BSS descriptor entry
+ *  @param pbeacon_info A pointer to the beacon buffer of NonTx BSS descriptor
+ *  @param ie_len		NonTx beacon buffer length
  */
-static mlan_status wlan_update_ssid_in_beacon_buf(
-	mlan_adapter *pmadapter, BSSDescriptor_t *pbss_entry,
-	BSSDescriptor_t *pnew_entry, IEEEtypes_Ssid_t *pssid,
-	IEEEtypes_ExtCap_t *pnew_extcap, IEEEtypes_Generic_t *pnew_rsnx,
-	IEEEtypes_Generic_t *pnew_rsn)
+static mlan_status wlan_update_nonTx_bss_desc(mlan_adapter *pmadapter,
+					      BSSDescriptor_t *pbss_entry,
+					      BSSDescriptor_t *pnew_entry,
+					      t_u8 **pbeacon_info, t_u32 ie_len)
 {
 	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
-	t_u8 *pbeacon_buf = MNULL;
-	t_u32 beacon_buf_size = 0;
-	t_s8 offset = pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len;
-	IEEEtypes_ExtCap_t *pextcap;
+	IEEEtypes_ElementId_e element_id;
+	t_u8 *pcurrent_ptr = MNULL;
+	t_u8 *pbuf = MNULL;
+	t_u8 *prate = MNULL;
+	t_u8 element_len = 0;
+	t_u8 bytes_to_copy = 0;
+	t_u8 rate_size = 0;
+	t_u8 found_data_rate_ie = 0;
+	t_u16 total_ie_len = 0;
+	t_u32 beacon_buf_size = BEACON_FIX_SIZE + ie_len;
+	t_u32 bytes_left = 0;
 	mlan_status ret = MLAN_STATUS_FAILURE;
-	t_u32 rsnx_offset = 0, rsn_offset = 0;
+	IEEEtypes_VendorSpecific_t *pvendor_ie;
+	const t_u8 wpa_oui[4] = {0x00, 0x50, 0xf2, 0x01};
+	const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
+	const t_u8 owe_oui[4] = {0x50, 0x6f, 0x9a, 0x1c};
+	const t_u8 osen_oui[] = {0x50, 0x6f, 0x9a, 0x12};
+	IEEEtypes_CountryInfoSet_t *pcountry_info;
+	IEEEtypes_Extension_t *pext_tlv;
 
-	if (pnew_entry->ssid.ssid_len >= pbss_entry->ssid.ssid_len)
-		beacon_buf_size =
-			pbss_entry->beacon_buf_size +
-			(pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len);
-	else
-		beacon_buf_size =
-			pbss_entry->beacon_buf_size -
-			(pbss_entry->ssid.ssid_len - pnew_entry->ssid.ssid_len);
-
-	rsnx_offset = beacon_buf_size;
-	if (pnew_rsnx)
-		beacon_buf_size +=
-			pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
-
-	rsn_offset = beacon_buf_size;
-	if (pnew_rsn)
-		beacon_buf_size +=
-			pnew_rsn->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
+	ENTER();
+	found_data_rate_ie = MFALSE;
+	rate_size = 0;
 
+	/* Allocate the beacon buffer for new entry */
 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, beacon_buf_size,
-			       MLAN_MEM_DEF, (t_u8 **)&pbeacon_buf);
-	if (ret != MLAN_STATUS_SUCCESS || !pbeacon_buf) {
-		PRINTM(MERROR,
-		       "Memory allocation for beacon buf for bss_new_entry\n");
+			       MLAN_MEM_DEF, (t_u8 **)&pbuf);
+	if (ret != MLAN_STATUS_SUCCESS || !pbuf) {
+		PRINTM(MERROR, "Memory allocation for beacon buf failed!\n");
 		goto done;
 	}
+
 	pnew_entry->beacon_buf_size = beacon_buf_size;
-	pnew_entry->pbeacon_buf = pbeacon_buf;
-	/** copy fixed IE */
-	memcpy_ext(pmadapter, pbeacon_buf, pbss_entry->pbeacon_buf,
-		   BEACON_FIX_SIZE, BEACON_FIX_SIZE);
-	/** copy new ssid ie */
-	memcpy_ext(pmadapter, pbeacon_buf + BEACON_FIX_SIZE, (t_u8 *)pssid,
-		   pssid->len + sizeof(IEEEtypes_Header_t),
-		   pssid->len + sizeof(IEEEtypes_Header_t));
-	/** copy left IE to new beacon buffer */
-	memcpy_ext(pmadapter,
-		   pbeacon_buf + BEACON_FIX_SIZE + pssid->len +
-			   sizeof(IEEEtypes_Header_t),
-		   pbss_entry->pbeacon_buf + BEACON_FIX_SIZE +
-			   pbss_entry->ssid.ssid_len +
-			   sizeof(IEEEtypes_Header_t),
-		   pbss_entry->beacon_buf_size - BEACON_FIX_SIZE -
-			   (pbss_entry->ssid.ssid_len +
-			    sizeof(IEEEtypes_Header_t)),
-		   pbss_entry->beacon_buf_size - BEACON_FIX_SIZE -
-			   (pbss_entry->ssid.ssid_len +
-			    sizeof(IEEEtypes_Header_t)));
+	pnew_entry->pbeacon_buf = pbuf;
 
-	/* adjust the ie pointer */
-	if (pnew_entry->pwpa_ie)
-		pnew_entry->wpa_offset += offset;
-	if (pnew_entry->prsn_ie)
-		pnew_entry->rsn_offset += offset;
-	if (pnew_entry->pwapi_ie)
-		pnew_entry->wapi_offset += offset;
+	/** Copy fixed IE to beacon buffer */
+	memcpy_ext(pmadapter, pbuf, pbss_entry->pbeacon_buf, BEACON_FIX_SIZE,
+		   BEACON_FIX_SIZE);
 
-	if (pnew_entry->posen_ie)
-		pnew_entry->osen_offset += offset;
-	if (pnew_entry->pmd_ie)
-		pnew_entry->md_offset += offset;
-	if (pnew_entry->pht_cap)
-		pnew_entry->ht_cap_offset += offset;
-	if (pnew_entry->pht_info)
-		pnew_entry->ht_info_offset += offset;
-	if (pnew_entry->pbss_co_2040)
-		pnew_entry->bss_co_2040_offset += offset;
-	if (pnew_entry->pext_cap) {
-		pnew_entry->ext_cap_offset += offset;
-		if (pnew_extcap) {
-			pextcap = (IEEEtypes_ExtCap_t
-					   *)(pnew_entry->pbeacon_buf +
-					      pnew_entry->ext_cap_offset);
-			memcpy_ext(pmadapter,
-				   pbeacon_buf + pnew_entry->ext_cap_offset,
-				   (t_u8 *)pnew_extcap,
-				   pnew_extcap->ieee_hdr.len +
-					   sizeof(IEEEtypes_Header_t),
-				   pextcap->ieee_hdr.len +
-					   sizeof(IEEEtypes_Header_t));
+	/** Initialize the current working beacon pointer */
+	pcurrent_ptr = *pbeacon_info;
+
+	/** Copy variable IEs to beacon buffer */
+	memcpy_ext(pmadapter, pbuf + BEACON_FIX_SIZE, pcurrent_ptr, ie_len,
+		   ie_len);
+
+	pcurrent_ptr = pbuf + BEACON_FIX_SIZE;
+	bytes_left = ie_len;
+
+	/* Adjust the IE pointers and offsets */
+	while (bytes_left >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+
+		switch (element_id) {
+		case SSID:
+			// coverity[bad_memset:SUPPRESS]
+			memset(pmadapter, (t_u8 *)&pnew_entry->ssid.ssid, 0,
+			       sizeof(mlan_802_11_ssid));
+			pnew_entry->ssid.ssid_len = element_len;
+			memcpy_ext(pmadapter, pnew_entry->ssid.ssid,
+				   (pcurrent_ptr + 2), element_len,
+				   element_len);
+			PRINTM(MMSG, "SSID: %-32s\n", pnew_entry->ssid.ssid);
+			break;
+
+		case SUPPORTED_RATES:
+			memcpy_ext(pmadapter, pnew_entry->data_rates,
+				   pcurrent_ptr + 2, element_len,
+				   sizeof(pnew_entry->data_rates));
+			memcpy_ext(pmadapter, pnew_entry->supported_rates,
+				   pcurrent_ptr + 2, element_len,
+				   sizeof(pnew_entry->supported_rates));
+			DBG_HEXDUMP(MINFO, "SupportedRates:",
+				    pnew_entry->supported_rates, element_len);
+			rate_size = element_len;
+			found_data_rate_ie = MTRUE;
+			break;
+		/* Handle Country Info IE */
+		case COUNTRY_INFO:
+			pcountry_info =
+				(IEEEtypes_CountryInfoSet_t *)pcurrent_ptr;
+			memcpy_ext(pmadapter, &pnew_entry->country_info,
+				   pcountry_info, pcountry_info->len + 2,
+				   sizeof(pnew_entry->country_info));
+			DBG_HEXDUMP(MINFO,
+				    "CountryInfo:", pnew_entry->country_info,
+				    element_len + 2);
+			break;
+		case POWER_CONSTRAINT:
+		case POWER_CAPABILITY:
+		case TPC_REPORT:
+		case CHANNEL_SWITCH_ANN:
+		case QUIET:
+		case SUPPORTED_CHANNELS:
+		case TPC_REQUEST:
+			wlan_11h_process_bss_elem(
+				pmadapter, &pnew_entry->wlan_11h_bss_info,
+				pcurrent_ptr);
+			break;
+		case EXTENDED_SUPPORTED_RATES:
+			/* Only process extended supported rate
+			 * if data rate is already found.
+			 * Data rate IE should come before
+			 * extended supported rate IE
+			 */
+			if (found_data_rate_ie) {
+				if ((element_len + rate_size) >
+				    WLAN_SUPPORTED_RATES) {
+					bytes_to_copy = (WLAN_SUPPORTED_RATES -
+							 rate_size);
+				} else {
+					bytes_to_copy = element_len;
+				}
+
+				prate = (t_u8 *)pnew_entry->data_rates;
+				prate += rate_size;
+				memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
+					   bytes_to_copy, bytes_to_copy);
+
+				prate = (t_u8 *)pnew_entry->supported_rates;
+				prate += rate_size;
+				memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
+					   bytes_to_copy, bytes_to_copy);
+			}
+			DBG_HEXDUMP(MINFO, "Ext SupportedRates:",
+				    pnew_entry->supported_rates,
+				    element_len + rate_size);
+			break;
+
+		case VENDOR_SPECIFIC_221:
+			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
+
+			if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+				    wpa_oui, sizeof(wpa_oui))) {
+				pnew_entry->pwpa_ie =
+					(IEEEtypes_VendorSpecific_t *)
+						pcurrent_ptr;
+				pnew_entry->wpa_offset =
+					(t_u16)(pcurrent_ptr -
+						pnew_entry->pbeacon_buf);
+
+				DBG_HEXDUMP(
+					MINFO,
+					"WPA_IE:", (t_u8 *)pnew_entry->pwpa_ie,
+					((*(pnew_entry->pwpa_ie)).vend_hdr.len +
+					 sizeof(IEEEtypes_Header_t)));
+			} else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+					   wmm_oui, sizeof(wmm_oui))) {
+				if (total_ie_len ==
+					    sizeof(IEEEtypes_WmmParameter_t) ||
+				    total_ie_len ==
+					    sizeof(IEEEtypes_WmmInfo_t)) {
+					/* Only accept and copy the WMM IE if
+					 * it matches the size expected for the
+					 * WMM Info IE or the WMM Parameter IE
+					 */
+					memcpy_ext(pmadapter,
+						   (t_u8 *)&pnew_entry->wmm_ie,
+						   pcurrent_ptr, total_ie_len,
+						   sizeof(pnew_entry->wmm_ie));
+					DBG_HEXDUMP(MINFO, "WMM_IE:",
+						    (t_u8 *)&pnew_entry->wmm_ie,
+						    total_ie_len);
+				}
+			} else if (IS_FW_SUPPORT_EMBEDDED_OWE(pmadapter) &&
+				   !memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+					   owe_oui, sizeof(owe_oui))) {
+				/* Current Format of OWE IE is
+				 * element_id:element_len:oui:MAC Address:SSID
+				 * length:SSID */
+				t_u8 trans_ssid_len = *(
+					pcurrent_ptr +
+					sizeof(IEEEtypes_Header_t) +
+					sizeof(owe_oui) + MLAN_MAC_ADDR_LENGTH);
+
+				if (!trans_ssid_len ||
+				    trans_ssid_len > MRVDRV_MAX_SSID_LENGTH) {
+					bytes_left = 0;
+					continue;
+				}
+
+				if (!pnew_entry->cap_info.privacy)
+					pnew_entry->owe_transition_mode =
+						OWE_TRANS_MODE_OPEN;
+				else
+					pnew_entry->owe_transition_mode =
+						OWE_TRANS_MODE_OWE;
+
+				memcpy_ext(
+					pmadapter,
+					pnew_entry->trans_mac_address,
+					(pcurrent_ptr +
+					 sizeof(IEEEtypes_Header_t) +
+					 sizeof(owe_oui)),
+					MLAN_MAC_ADDR_LENGTH,
+					sizeof(pnew_entry->trans_mac_address));
+
+				pnew_entry->trans_ssid.ssid_len =
+					trans_ssid_len;
+
+				memcpy_ext(
+					pmadapter, pnew_entry->trans_ssid.ssid,
+					(pcurrent_ptr +
+					 sizeof(IEEEtypes_Header_t) +
+					 sizeof(owe_oui) +
+					 MLAN_MAC_ADDR_LENGTH + sizeof(t_u8)),
+					trans_ssid_len,
+					sizeof(pnew_entry->trans_ssid.ssid));
+
+				PRINTM(MINFO,
+				       "OWE Transition AP privacy=%d MAC Addr-" MACSTR
+				       " ssid %s\n",
+				       pnew_entry->owe_transition_mode,
+				       MAC2STR(pnew_entry->trans_mac_address),
+				       pnew_entry->trans_ssid.ssid);
+			} else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
+					   osen_oui, sizeof(osen_oui))) {
+				pnew_entry->posen_ie =
+					(IEEEtypes_Generic_t *)pcurrent_ptr;
+				pnew_entry->osen_offset =
+					(t_u16)(pcurrent_ptr -
+						pnew_entry->pbeacon_buf);
+
+				DBG_HEXDUMP(
+					MINFO, "OSEN_IE:",
+					(t_u8 *)pnew_entry->posen_ie,
+					(*(pnew_entry->posen_ie)).ieee_hdr.len +
+						sizeof(IEEEtypes_Header_t));
+			}
+			break;
+		case RSN_IE:
+			pnew_entry->prsn_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pnew_entry->rsn_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO,
+				    "RSN_IE:", (t_u8 *)pnew_entry->prsn_ie,
+				    (*(pnew_entry->prsn_ie)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+		case RSNX_IE:
+			pnew_entry->prsnx_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pnew_entry->rsnx_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO,
+				    "RSNX_IE:", (t_u8 *)pnew_entry->prsnx_ie,
+				    (*(pnew_entry->prsnx_ie)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+		case WAPI_IE:
+			pnew_entry->pwapi_ie =
+				(IEEEtypes_Generic_t *)pcurrent_ptr;
+			pnew_entry->wapi_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO,
+				    "WAPI_IE:", (t_u8 *)pnew_entry->pwapi_ie,
+				    (*(pnew_entry->pwapi_ie)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+		case HT_CAPABILITY:
+			pnew_entry->pht_cap = (IEEEtypes_HTCap_t *)pcurrent_ptr;
+			pnew_entry->ht_cap_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO,
+				    "HTCAP_IE:", (t_u8 *)pnew_entry->pht_cap,
+				    (*(pnew_entry->pht_cap)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case HT_OPERATION:
+			pnew_entry->pht_info =
+				(IEEEtypes_HTInfo_t *)pcurrent_ptr;
+			pnew_entry->ht_info_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO,
+				    "HTOPER_IE:", (t_u8 *)pnew_entry->pht_info,
+				    (*(pnew_entry->pht_info)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case BSSCO_2040:
+			pnew_entry->pbss_co_2040 =
+				(IEEEtypes_2040BSSCo_t *)pcurrent_ptr;
+			pnew_entry->bss_co_2040_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO, "2040BSSCOEX_IE:",
+				    (t_u8 *)pnew_entry->pbss_co_2040,
+				    (*(pnew_entry->pbss_co_2040)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case EXT_CAPABILITY:
+			pnew_entry->pext_cap =
+				(IEEEtypes_ExtCap_t *)pcurrent_ptr;
+			pnew_entry->ext_cap_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO,
+				    "EXTCAP_IE:", (t_u8 *)pnew_entry->pext_cap,
+				    (*(pnew_entry->pext_cap)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case OVERLAPBSSSCANPARAM:
+			pnew_entry->poverlap_bss_scan_param =
+				(IEEEtypes_OverlapBSSScanParam_t *)pcurrent_ptr;
+			pnew_entry->overlap_bss_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO, "OBSS_IE",
+				    (t_u8 *)pnew_entry->poverlap_bss_scan_param,
+				    (*(pnew_entry->poverlap_bss_scan_param))
+						    .ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+		case VHT_CAPABILITY:
+			pnew_entry->pvht_cap =
+				(IEEEtypes_VHTCap_t *)pcurrent_ptr;
+			pnew_entry->vht_cap_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO,
+				    "VHTCAP_IE:", (t_u8 *)pnew_entry->pvht_cap,
+				    (*(pnew_entry->pvht_cap)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case VHT_OPERATION:
+			pnew_entry->pvht_oprat =
+				(IEEEtypes_VHTOprat_t *)pcurrent_ptr;
+			pnew_entry->vht_oprat_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO, "VHTOPER_IE:",
+				    (t_u8 *)pnew_entry->pvht_oprat,
+				    (*(pnew_entry->pvht_oprat)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case EXT_BSS_LOAD:
+			pnew_entry->pext_bssload =
+				(IEEEtypes_ExtBSSload_t *)pcurrent_ptr;
+			pnew_entry->ext_bssload_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO, "EXTBSSLOAD_IE",
+				    (t_u8 *)pnew_entry->pext_bssload,
+				    (*(pnew_entry->pext_bssload)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case VHT_TX_POWER_ENV:
+			pnew_entry->pvht_txpower =
+				(IEEEtypes_VHTtxpower_t *)pcurrent_ptr;
+			pnew_entry->vht_txpower_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO, "TXPOW_IE:",
+				    (t_u8 *)pnew_entry->pvht_txpower,
+				    (*(pnew_entry->pvht_txpower)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case EXT_POWER_CONSTR:
+			pnew_entry->pext_pwer =
+				(IEEEtypes_ExtPwerCons_t *)pcurrent_ptr;
+			pnew_entry->ext_pwer_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO, "EXTPOW_IE",
+				    (t_u8 *)pnew_entry->pext_pwer,
+				    (*(pnew_entry->pext_pwer)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case QUIET_CHAN:
+			pnew_entry->pquiet_chan =
+				(IEEEtypes_QuietChan_t *)pcurrent_ptr;
+			pnew_entry->quiet_chan_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO, "QUIETCHAN_IE",
+				    (t_u8 *)pnew_entry->pquiet_chan,
+				    (*(pnew_entry->pquiet_chan)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+
+		case OPER_MODE_NTF:
+			pnew_entry->poper_mode =
+				(IEEEtypes_OperModeNtf_t *)pcurrent_ptr;
+			pnew_entry->oper_mode_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO,
+				    "OMN_IE:", (t_u8 *)pnew_entry->poper_mode,
+				    (*(pnew_entry->poper_mode)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+		case EXTENSION:
+			pext_tlv = (IEEEtypes_Extension_t *)pcurrent_ptr;
+			switch (pext_tlv->ext_id) {
+			case HE_CAPABILITY:
+				pnew_entry->phe_cap =
+					(IEEEtypes_HECap_t *)pcurrent_ptr;
+				pnew_entry->he_cap_offset =
+					(t_u16)(pcurrent_ptr -
+						pnew_entry->pbeacon_buf);
+				DBG_HEXDUMP(
+					MINFO, "HECAP_IE:",
+					(t_u8 *)pnew_entry->phe_cap,
+					(*(pnew_entry->phe_cap)).ieee_hdr.len +
+						sizeof(IEEEtypes_Header_t));
+				break;
+			case HE_OPERATION:
+				pnew_entry->phe_oprat = pext_tlv;
+				pnew_entry->he_oprat_offset =
+					(t_u16)(pcurrent_ptr -
+						pnew_entry->pbeacon_buf);
+				DBG_HEXDUMP(
+					MINFO, "HEOPER_IE:",
+					(t_u8 *)pnew_entry->phe_oprat,
+					(*(pnew_entry->phe_oprat)).ieee_hdr.len +
+						sizeof(IEEEtypes_Header_t));
+				break;
+			case MU_EDCA_PARAM_SET:
+				pnew_entry->pmuedca_ie =
+					(IEEEtypes_MUEDCAParamSet_t *)
+						pcurrent_ptr;
+				pnew_entry->muedca_offset =
+					(t_u16)(pcurrent_ptr -
+						pnew_entry->pbeacon_buf);
+				DBG_HEXDUMP(MINFO, "MUEDCA_IE:",
+					    (t_u8 *)pnew_entry->pmuedca_ie,
+					    (*(pnew_entry->pmuedca_ie))
+							    .ieee_hdr.len +
+						    sizeof(IEEEtypes_Header_t));
+				break;
+			case MBSSID_CONFIG:
+				pnew_entry->pmbssid_config =
+					(IEEEtypes_MBSSID_Config_t *)
+						pcurrent_ptr;
+				pnew_entry->mbssid_config_offset =
+					(t_u16)(pcurrent_ptr -
+						pnew_entry->pbeacon_buf);
+				DBG_HEXDUMP(MINFO, "MBSSID_CONFIG_IE:",
+					    (t_u8 *)pnew_entry->pmbssid_config,
+					    (*(pnew_entry->pmbssid_config))
+							    .ieee_hdr.len +
+						    sizeof(IEEEtypes_Header_t));
+				break;
+			default:
+				break;
+			}
+			break;
+		case MOBILITY_DOMAIN:
+			pnew_entry->pmd_ie =
+				(IEEEtypes_MobilityDomain_t *)pcurrent_ptr;
+			pnew_entry->md_offset =
+				(t_u16)(pcurrent_ptr - pnew_entry->pbeacon_buf);
+			DBG_HEXDUMP(MINFO, "Mobility Domain IE",
+				    (t_u8 *)pnew_entry->pmd_ie,
+				    (*(pnew_entry->pmd_ie)).ieee_hdr.len +
+					    sizeof(IEEEtypes_Header_t));
+			break;
+		default:
+			break;
 		}
+
+		pcurrent_ptr += element_len + 2;
+		bytes_left -= (element_len + 2);
 	}
-	if (pnew_entry->poverlap_bss_scan_param)
-		pnew_entry->overlap_bss_offset += offset;
-	if (pnew_entry->pvht_cap)
-		pnew_entry->vht_cap_offset += offset;
-	if (pnew_entry->pvht_oprat)
-		pnew_entry->vht_oprat_offset += offset;
-	if (pnew_entry->pvht_txpower)
-		pnew_entry->vht_txpower_offset += offset;
-	if (pnew_entry->pext_pwer)
-		pnew_entry->ext_pwer_offset += offset;
-	if (pnew_entry->pext_bssload)
-		pnew_entry->ext_bssload_offset += offset;
-	if (pnew_entry->pquiet_chan)
-		pnew_entry->quiet_chan_offset += offset;
-	if (pnew_entry->poper_mode)
-		pnew_entry->oper_mode_offset += offset;
-	if (pnew_entry->phe_cap)
-		pnew_entry->he_cap_offset += offset;
-	if (pnew_entry->phe_oprat)
-		pnew_entry->he_oprat_offset += offset;
-	if (pnew_rsnx)
-		memcpy_ext(
-			pmadapter, pbeacon_buf + rsnx_offset, (t_u8 *)pnew_rsnx,
-			pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t),
-			pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
-	if (pnew_rsn)
-		memcpy_ext(pmadapter, pbeacon_buf + rsn_offset,
-			   (t_u8 *)pnew_rsn,
-			   pnew_rsn->ieee_hdr.len + sizeof(IEEEtypes_Header_t),
-			   pnew_rsn->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
-	DBG_HEXDUMP(MCMD_D, "MBSSID beacon buf", pbeacon_buf, beacon_buf_size);
-	ret = MLAN_STATUS_SUCCESS;
 done:
+	LEAVE();
 	return ret;
 }
 
+/**
+ *  @brief This function returns a pointer to IE with matching element ID
+ *
+ *  @param pmadpater		A pointer to mlan_adapter structure
+ *  @param eid   			A pointer to element ID to search for
+ *	@param subie			NonTx BSSID buffer from which to search
+ *IE
+ *	@param subie_len		NonTx BSSID buffer len
+ *	@param match			Pointer to IE to be matched
+ *	@param match_len		1 for EXT_ID, 0 for Non_Ext ID
+ *	@param match_offset		IE offset to be matched
+ *  @return elem            Returns pointer to the matched element
+ */
+static IEEEtypes_Element_t *wlan_find_elem_match(mlan_adapter *pmadapter,
+						 t_u8 eid, t_u8 *subie,
+						 t_u32 subie_len, t_u8 *match,
+						 t_u32 match_len,
+						 t_u32 match_offset)
+{
+	IEEEtypes_Element_t *elem;
+
+	for_each_element_id (elem, eid, subie, subie_len) {
+		if (elem->ieee_hdr.len >= match_offset + match_len &&
+		    !memcmp(pmadapter, elem->data + match_offset, match,
+			    match_len))
+			return elem;
+	}
+	return MNULL;
+}
+
 /**
  *  @brief This function generate the bssid from bssid_idx
  *
@@ -5385,195 +5854,719 @@ static void wlan_gen_multi_bssid_by_bssid_index(pmlan_adapter pmadapter,
 }
 
 /**
- *  @brief This function parse the non_trans_bssid_profile
+ *  @brief This function checks if the given IE is inherited
  *
- *  @param pmadapter        A pointer to mlan_adapter structure
- *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
- * IE
- *  @param pbss_profile     A pointer to IEEEtypes_NonTransBSSIDprofile_t
- *  @param num_in_table     A pointer to buffer to save num of entry in scan
- * table.
- *  @param  max_bssid_indicator max bssid indicator
+ *  @param elem				The element to check
+ *  @param non_inherit_ie   A pointer
+ *
+ *  @return                 TRUE -  if element is inherited from TxBSSID
+ *                          FALSE - IF element in NOT inherited
+ */
+static t_bool wlan_is_element_inherited(IEEEtypes_Element_t *elem,
+					IEEEtypes_Element_t *non_inherit_ie)
+{
+	t_u8 id_len, ext_id_len, i, loop_len, id;
+	const t_u8 *list;
+
+	ENTER();
+	if (elem->ieee_hdr.element_id == MULTI_BSSID)
+		return MFALSE;
+
+	if (!non_inherit_ie || non_inherit_ie->ieee_hdr.len < 2)
+		return MTRUE;
+
+	/*
+	 * non inheritance element format is:
+	 * ext ID (56) | IDs list len | list | extension IDs list len | list
+	 * Both lists are optional. Both lengths are mandatory */
+	id_len = non_inherit_ie->data[1];
+	if (non_inherit_ie->ieee_hdr.len < 3 + id_len)
+		return MTRUE;
+
+	ext_id_len = non_inherit_ie->data[2 + id_len];
+	if (non_inherit_ie->ieee_hdr.len < 3 + id_len + ext_id_len)
+		return MTRUE;
+
+	if (elem->ieee_hdr.element_id == EXTENSION) {
+		if (!ext_id_len)
+			return MTRUE;
+		loop_len = ext_id_len;
+		list = &non_inherit_ie->data[3 + id_len];
+		id = elem->data[0];
+	} else {
+		if (!id_len)
+			return MTRUE;
+		loop_len = id_len;
+		list = &non_inherit_ie->data[2];
+		id = elem->ieee_hdr.element_id;
+	}
+
+	for (i = 0; i < loop_len; i++) {
+		if (list[i] == id)
+			return MFALSE;
+	}
+
+	LEAVE();
+	return MTRUE;
+}
+
+/**
+ *  @brief This function copies an IE fragment by fragment from the parent
+ *  		(Tx BSSID) to non-Tx BSSID
+ *
+ *  @param pmadapter	A pointer to mlan adapter
+ *  @param elem			A pointer to the IE to be copied from parent to
+ * NonTx BSSID
+ *  @param ie     		A pointer to the IE buffer in parent Tx BSSID
+ *  @param ie_len     	IE buffer length
+ *  @param pos			Pointer to location where IE is copied
+ *  @param buf        	Original buffer pointer of the new generated IE
+ *  @param buf_len     	Buffer length of generated IE
+ *  @return             Copied IE length
+ */
+static t_u32 wlan_copy_ie_with_fragments(pmlan_adapter pmadapter,
+					 IEEEtypes_Element_t *elem,
+					 const t_u8 *ie, t_u32 ie_len,
+					 t_u8 **pos, t_u8 *buf, t_u32 buf_len)
+{
+	ENTER();
+	/* Error checking */
+	if (elem->ieee_hdr.len + 2 > buf + buf_len - *pos) {
+		PRINTM(MERROR, "Copy length in error!\n");
+		return 0;
+	}
+
+	/* Copy the IE */
+	memcpy_ext(pmadapter, *pos, elem, elem->ieee_hdr.len + 2,
+		   elem->ieee_hdr.len + 2);
+	DBG_HEXDUMP(MINFO, "Copying the IE", *pos, elem->ieee_hdr.len + 2);
+	*pos += elem->ieee_hdr.len + 2;
+
+	/* Finish the copy if element is not fragmented */
+	if (elem->ieee_hdr.len != 255) {
+		// coverity[overflow_sink:SUPPRESS]
+		return *pos - buf;
+	}
+
+	/* Adjust the IE offsets */
+	ie_len = ie + ie_len - elem->data - elem->ieee_hdr.len;
+	ie = (const t_u8 *)elem->data + elem->ieee_hdr.len;
+
+	/* Check for remaining fragments and copy if any */
+	for_each_element (elem, ie, ie_len) {
+		if (elem->ieee_hdr.element_id != FRAGMENT)
+			break;
+
+		/* Error checking */
+		if (elem->ieee_hdr.len + 2 > buf + buf_len - *pos) {
+			PRINTM(MERROR, "Copy length in error!!\n");
+			return 0;
+		}
+
+		/* Copy the IE */
+		memcpy_ext(pmadapter, *pos, elem, elem->ieee_hdr.len + 2,
+			   elem->ieee_hdr.len + 2);
+		*pos += elem->ieee_hdr.len + 2;
+
+		/* Break if element is not fragmented */
+		if (elem->ieee_hdr.len != 255)
+			break;
+	}
+
+	LEAVE();
+	// coverity[overflow_sink:SUPPRESS]
+	return *pos - buf;
+}
+
+/**
+ *  @brief This function generates a new NonTx BSSID entry from
+ *  	   the parent TxBSS entry
+ *
+ *  @param pmadapter		A pointer to mlan private
+ *  @param ie     			A pointer to the IE buffer in parent Tx
+ * BSSID
+ *  @param ie_len     		IE buffer length
+ *  @param merged_ie		Pointer to merged NonTx BSSID profile
+ *  @param merged_ie_len    Length of the NonTx BSSID profile
+ *  @param new_ie     		Pointer to new ie buffer
+ *  @param new_ie_len     	Length of new ie buffer
+ *  @return             	Copied IE length
+ */
+static t_u32 wlan_gen_new_ie(mlan_private *pmpriv, t_u8 *ie, t_u32 ie_len,
+			     t_u8 *merged_ie, t_u32 merged_ie_len, t_u8 *new_ie,
+			     t_u32 new_ie_len)
+{
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	IEEEtypes_ElementId_e element_id;
+	IEEEtypes_Extension_t *pext_tlv = MNULL;
+	IEEEtypes_Element_t *non_inherit_elem = MNULL;
+	IEEEtypes_Element_t *parent = MNULL, *sub = MNULL;
+	t_u8 element_len = 0, id = 0, ext_id = 0;
+	t_u8 *pcurrent_ptr = merged_ie, *pos = new_ie;
+	t_u32 left_len = merged_ie_len, match_len = 0;
+	t_s32 ret_val = 0;
+
+	ENTER();
+	/* Fetch the Non-Inherit Element */
+	while (left_len >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+
+		if (element_id == EXTENSION) {
+			pext_tlv = (IEEEtypes_Extension_t *)pcurrent_ptr;
+
+			if (pext_tlv->ext_id == NON_INHERITANCE) {
+				non_inherit_elem =
+					(IEEEtypes_Element_t *)pcurrent_ptr;
+				break;
+			}
+		}
+		pcurrent_ptr += element_len + 2;
+		left_len -= (element_len + 2);
+	}
+
+	if (!non_inherit_elem)
+		PRINTM(MINFO, "Non-Inherit Elem NOT present\n");
+
+	/* Copy the elements from the parent MBSSID Beacon IE to the generated
+	 * IE
+	 * If they are included in the NonTx profile or in the Non inheritance
+	 * element, then copy all occurances of these elements, the first time
+	 * we encounter them
+	 */
+	for_each_element (parent, ie, ie_len) {
+		if (parent->ieee_hdr.element_id == FRAGMENT)
+			continue;
+
+		if (parent->ieee_hdr.element_id == EXTENSION) {
+			if (parent->ieee_hdr.len < 1)
+				continue;
+
+			id = EXTENSION;
+			ext_id = parent->data[0];
+			match_len = 1;
+		} else {
+			id = parent->ieee_hdr.element_id;
+			match_len = 0;
+		}
+
+		/* Check for the first occurance in NonTx profile */
+		sub = wlan_find_elem_match(pmadapter, id, merged_ie,
+					   merged_ie_len, &ext_id, match_len,
+					   0);
+
+		/* Copy from Tx profile if not present in NonTx profile and
+		 * inherited
+		 */
+		if (!sub &&
+		    wlan_is_element_inherited(parent, non_inherit_elem)) {
+			if ((ret_val = wlan_copy_ie_with_fragments(
+				     pmadapter, parent, ie, ie_len, &pos,
+				     new_ie, new_ie_len)) <= 0)
+				return 0;
+
+			continue;
+		}
+
+		/* Already copied if an earlier element had the same type */
+		if (wlan_find_elem_match(pmadapter, id, ie, (t_u8 *)parent - ie,
+					 &ext_id, match_len, 0))
+			continue;
+
+		/* Not inheriting, copy all similar elements from NonTx profile
+		 */
+		while (sub) {
+			if ((ret_val = wlan_copy_ie_with_fragments(
+				     pmadapter, sub, merged_ie, merged_ie_len,
+				     &pos, new_ie, new_ie_len)) <= 0)
+				return 0;
+			// coverity[overflow_sink:SUPPRESS]
+			sub = wlan_find_elem_match(
+				pmadapter, id, sub->data + sub->ieee_hdr.len,
+				merged_ie_len + merged_ie -
+					(sub->data + sub->ieee_hdr.len),
+				&ext_id, match_len, 0);
+		}
+	}
+
+	/* The above loop skips the elements that are included in NonTx profile
+	 * but NOT in the parent Tx profile; So do a pass over NonTx profile
+	 * and append the missed IEs. Skip the NonTx BSSID cpas and Non-
+	 * Inheritance element */
+	for_each_element (sub, merged_ie, merged_ie_len) {
+		if (sub->ieee_hdr.element_id == NONTX_BSSID_CAP)
+			continue;
+
+		if (sub->ieee_hdr.element_id == FRAGMENT)
+			continue;
+
+		if (sub->ieee_hdr.element_id == EXTENSION) {
+			if (sub->ieee_hdr.len < 1)
+				continue;
+
+			id = EXTENSION;
+			ext_id = sub->data[0];
+			match_len = 1;
+
+			if (ext_id == NON_INHERITANCE)
+				continue;
+		} else {
+			id = sub->ieee_hdr.element_id;
+			match_len = 0;
+		}
+
+		/* Processed if one was included in the parent */
+		if (wlan_find_elem_match(pmadapter, id, ie, ie_len, &ext_id,
+					 match_len, 0))
+			continue;
+
+		if ((ret_val = wlan_copy_ie_with_fragments(
+			     pmadapter, sub, merged_ie, merged_ie_len, &pos,
+			     new_ie, new_ie_len)) <= 0)
+			return 0;
+	}
+
+	LEAVE();
+	return pos - new_ie;
+}
+
+/**
+ *  @brief This function generates the nonTx BSSID profile
+ *
+ *  @param pmadapter       		A pointer to mlan_private structure
+ *  @param pbss_entry       	A pointer to BSSDescriptor_t which has
+ * multi-bssid IE
+ *  @param pmerged_profile  	A pointer to merged NonTX BSSID Profile
+ *  @param profile_len      	Length of the merged NonTX Profile
+ *  @param num_in_table			A pointer to buffer to save num of entry
+ * in scan table.
+ *  @param max_bssid_indicator 	max bssid indicator
  *
  *  @return                 N/A
  */
-static t_void wlan_parse_non_trans_bssid_profile(
-	mlan_private *pmpriv, BSSDescriptor_t *pbss_entry,
-	IEEEtypes_NonTransBSSIDProfile_t *pbss_profile, t_u32 *num_in_table,
-	t_u8 max_bssid_indicator)
+static void wlan_gen_non_trans_bssid_profile(mlan_private *pmpriv,
+					     BSSDescriptor_t *pbss_entry,
+					     t_u8 *pmerged_profile,
+					     t_u32 profile_len,
+					     t_u32 *num_in_table,
+					     t_u8 max_bssid_indicator)
 {
 	mlan_adapter *pmadapter = pmpriv->adapter;
-	IEEEtypes_Header_t *pheader =
-		(IEEEtypes_Header_t *)pbss_profile->profile_data;
+	t_u8 *pcurrent_ptr = pmerged_profile;
+	IEEEtypes_ElementId_e element_id =
+		(IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
 	IEEEtypes_MultiBSSIDIndex_t *pbssid_index = MNULL;
-	IEEEtypes_Ssid_t *pssid = MNULL;
-	IEEEtypes_Generic_t *prsn = MNULL;
-	IEEEtypes_NotxBssCap_t *pcap =
-		(IEEEtypes_NotxBssCap_t *)pbss_profile->profile_data;
-	t_u8 *pos = pbss_profile->profile_data;
-	t_u8 left_len = pbss_profile->ieee_hdr.len;
-	t_u8 ret = MFALSE;
+	IEEEtypes_NotxBssCap_t *pcap = MNULL;
 	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
 	BSSDescriptor_t *bss_new_entry = MNULL;
-	t_u8 *pbeacon_buf = MNULL;
-	IEEEtypes_ExtCap_t *pextcap = MNULL;
-	IEEEtypes_Generic_t *prsnx = MNULL;
+	t_u8 *pbeacon_buf = MNULL, *pnew_beacon_buf = MNULL;
+	t_u8 element_len = *((t_u8 *)pcurrent_ptr + 1);
+	t_u32 left_len = profile_len;
+	t_u32 ie_len = pbss_entry->beacon_buf_size - BEACON_FIX_SIZE;
+	t_u32 copied_len = 0;
+	t_u8 ret = MFALSE;
 
 	ENTER();
-
-	/* The first element within the Nontransmitted
-	 * BSSID Profile is not the Nontransmitted
-	 * BSSID Capability element.
-	 */
-	if (pcap->element_id != NONTX_BSSID_CAP || pcap->len != 2) {
+	/* Check for NonTx BSSID Capability */
+	if (element_id != NONTX_BSSID_CAP || element_len != 2) {
 		PRINTM(MERROR,
-		       "The first element within the Nontransmitted BSSID Profile is not the NontransmittedBSSID Capability element\n");
+		       "The first element within the NonTx BSSID profile is not the "
+		       "NonTx BSSID Capability element\n");
 		LEAVE();
 		return;
 	}
 
+	/* Check for valid NonTx BSSID */
 	while (left_len >= 2) {
-		pheader = (IEEEtypes_Header_t *)pos;
-		if ((t_s8)(pheader->len + sizeof(IEEEtypes_Header_t)) >
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+
+		if ((t_u8)(element_len + sizeof(IEEEtypes_Header_t)) >
 		    left_len) {
-			PRINTM(MMSG, "invalid IE length = %d left len %d\n",
-			       pheader->len, left_len);
-			break;
+			PRINTM(MERROR, "Invalid IE length = %d left len %d\n",
+			       element_len, left_len);
+			goto done;
 		}
-		switch (pheader->element_id) {
-		case MBSSID_INDEX:
-			pbssid_index = (IEEEtypes_MultiBSSIDIndex_t *)pos;
+
+		/* Find the NonTx Capability */
+		if (element_id == NONTX_BSSID_CAP) {
+			pcap = (IEEEtypes_NotxBssCap_t *)pcurrent_ptr;
+			PRINTM(MINFO, "NonTx Cap =%x\n", pcap->cap);
+		}
+
+		/* Find the MBSSID Index */
+		if (element_id == MBSSID_INDEX) {
+			pbssid_index =
+				(IEEEtypes_MultiBSSIDIndex_t *)pcurrent_ptr;
 			if (pbssid_index->bssid_index == 0 ||
 			    pbssid_index->bssid_index > 46) {
 				PRINTM(MERROR,
-				       " No valid Multiple BSSID-Index element\n");
+				       "No valid Multiple BSSID-Index element\n");
 				goto done;
 			}
-			PRINTM(MCMND, "MBSSID: Find mbssid_index=%d\n",
+			PRINTM(MCMND, "MBSSID: mbssid_index=%d\n",
 			       pbssid_index->bssid_index);
 			ret = MTRUE;
 			break;
-		case EXT_CAPABILITY:
-			pextcap = (IEEEtypes_ExtCap_t *)pos;
-			DBG_HEXDUMP(MCMD_D, "MBSSID extcap", pos,
-				    pextcap->ieee_hdr.len +
-					    sizeof(IEEEtypes_Header_t));
-			break;
-		case RSNX_IE:
-			prsnx = (IEEEtypes_Generic_t *)pos;
-			DBG_HEXDUMP(MCMD_D, "MBSSID RSNX", pos,
-				    prsnx->ieee_hdr.len +
-					    sizeof(IEEEtypes_Header_t));
-			break;
-		case RSN_IE:
-			prsn = (IEEEtypes_Generic_t *)pos;
-			DBG_HEXDUMP(MCMD_D, "MBSSID RSN", pos,
-				    prsn->ieee_hdr.len +
-					    sizeof(IEEEtypes_Header_t));
-			break;
-		case SSID:
-			pssid = (IEEEtypes_Ssid_t *)pos;
-			PRINTM(MCMND, "MBSSID: Find mbssid ssid=%s\n",
-			       pssid->ssid);
-			break;
-		default:
-			break;
 		}
-		left_len -= pheader->len + sizeof(IEEEtypes_Header_t);
-		pos += pheader->len + sizeof(IEEEtypes_Header_t);
+
+		left_len -= (element_len + 2);
+		pcurrent_ptr += element_len + 2;
 	}
+
 	if (ret == MTRUE) {
 		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
 				       sizeof(BSSDescriptor_t), MLAN_MEM_DEF,
 				       (t_u8 **)&bss_new_entry);
+
 		if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
 			PRINTM(MERROR,
 			       "Memory allocation for bss_new_entry failed!\n");
 			goto done;
 		}
+
+		/* Populate the fixed fields of new NonTx BSS entry */
 		memcpy_ext(pmadapter, bss_new_entry, pbss_entry,
 			   sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
+
 		wlan_gen_multi_bssid_by_bssid_index(pmadapter, pbss_entry,
 						    bss_new_entry,
 						    pbssid_index->bssid_index,
 						    max_bssid_indicator);
-		if (pssid) {
-			memset(pmadapter, (t_u8 *)&bss_new_entry->ssid, 0,
-			       sizeof(mlan_802_11_ssid));
-			bss_new_entry->ssid.ssid_len = pssid->len;
-			memcpy_ext(pmadapter, bss_new_entry->ssid.ssid,
-				   pssid->ssid, pssid->len,
-				   MLAN_MAX_SSID_LENGTH);
-			if (MLAN_STATUS_SUCCESS !=
-			    wlan_update_ssid_in_beacon_buf(
-				    pmadapter, pbss_entry, bss_new_entry, pssid,
-				    pextcap, prsnx, prsn)) {
-				PRINTM(MERROR,
-				       "Fail to update MBSSID beacon buf\n");
-				pcb->moal_mfree(pmadapter->pmoal_handle,
-						(t_u8 *)bss_new_entry);
-				goto done;
-			}
-			pbeacon_buf = bss_new_entry->pbeacon_buf;
-		}
+
 		memcpy_ext(pmadapter, &bss_new_entry->cap_info, &pcap->cap,
 			   sizeof(IEEEtypes_CapInfo_t),
 			   sizeof(IEEEtypes_CapInfo_t));
+
 		bss_new_entry->multi_bssid_ap = MULTI_BSSID_SUB_AP;
+
+		/* Allocate the beacon buffer for new entry */
+		// coverity[overflow_sink:SUPPRESS]
+		ret = pcb->moal_malloc(pmadapter->pmoal_handle, ie_len,
+				       MLAN_MEM_DEF, (t_u8 **)&pbeacon_buf);
+		if (ret != MLAN_STATUS_SUCCESS || !pbeacon_buf) {
+			PRINTM(MERROR,
+			       "Memory allocation for beacon buf failed!\n");
+			goto done;
+		}
+
+		/** Generate the NonTx BSSID Beacon buffer */
+		// coverity[overflow_sink:SUPPRESS]
+		copied_len = wlan_gen_new_ie(
+			pmpriv, pbss_entry->pbeacon_buf + BEACON_FIX_SIZE,
+			ie_len, pmerged_profile, profile_len, pbeacon_buf,
+			ie_len);
+
+		if (!copied_len) {
+			PRINTM(MERROR, "Failed to generate NonTx BSSID IE!\n");
+			goto done;
+		} else {
+			PRINTM(MMSG, "NonTx Beacon Buffer IE Len = %d\n",
+			       copied_len);
+		}
+		DBG_HEXDUMP(MCMD_D, "NonTx BSSID", pbeacon_buf, copied_len);
+
+		/** Update NonTx BSS descriptor entries */
+		// coverity[overflow_sink:SUPPRESS]
+		if (MLAN_STATUS_SUCCESS !=
+		    wlan_update_nonTx_bss_desc(pmadapter, pbss_entry,
+					       bss_new_entry, &pbeacon_buf,
+					       copied_len)) {
+			PRINTM(MERROR,
+			       "Fail to update NonTx BSSID beacon buf\n");
+			goto done;
+		}
+		pnew_beacon_buf = bss_new_entry->pbeacon_buf;
+		DBG_HEXDUMP(MCMD_D, "NonTx Beacon buf",
+			    bss_new_entry->pbeacon_buf,
+			    BEACON_FIX_SIZE + copied_len);
+
+		/** Add the NonTx BSS entry to the scan table */
 		wlan_add_new_entry_to_scan_table(pmpriv, bss_new_entry,
 						 num_in_table);
-		if (pssid && pbeacon_buf)
-			pcb->moal_mfree(pmadapter->pmoal_handle,
-					(t_u8 *)pbeacon_buf);
-		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
 	}
 done:
+	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)(pnew_beacon_buf));
+	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
+	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pbeacon_buf);
 	LEAVE();
 	return;
 }
 
 /**
- *  @brief This function parse the multi_bssid IE from pbss_entry
+ *  @brief This function finds the next MBSSID element containing the split
+ *         NonTx BSSID profile
+ *
+ *  @param pbss_entry   	A pointer to BSSDescriptor_t that has MBSSID IE
+ *  @param ie_len      		Maximum IE len in beacon/probe response
+ *  @param pmbssid     		A pointer to MBSSID IE
+ *  @param pnontx_bssid     A pointer to NonTx BSSID subelement
+ *  @return                 A pointer to next MBSSID element
+ */
+static IEEEtypes_MultiBSSID_t *
+wlan_get_next_mbssid_profile(BSSDescriptor_t *pbss_entry, t_u32 ie_len,
+			     IEEEtypes_MultiBSSID_t *pmbssid,
+			     IEEEtypes_NonTransBSSIDProfile_t *pnontx_bssid)
+{
+	IEEEtypes_MultiBSSID_t *pnext_mbssid = MNULL;
+	IEEEtypes_NonTransBSSIDProfile_t *pnext_nontx_bssid = MNULL;
+	t_u8 *mbssid_end = MNULL;
+	t_u8 *pcurrent_ptr = MNULL;
+	IEEEtypes_ElementId_e element_id;
+	t_u32 bytes_left = 0;
+	t_u16 total_ie_len = 0;
+	t_u8 element_len = 0;
+
+	ENTER();
+	if (!pmbssid || !pnontx_bssid) {
+		PRINTM(MERROR, "No MBSSID or NonTx BSSID element present\n");
+		return MNULL;
+	}
+
+	mbssid_end = pmbssid->sub_elem_data + (pmbssid->ieee_hdr.len - 1);
+	pcurrent_ptr = pmbssid->sub_elem_data + (pmbssid->ieee_hdr.len - 1);
+	bytes_left = ie_len -
+		     (mbssid_end - (pbss_entry->pbeacon_buf + BEACON_FIX_SIZE));
+
+	/* If it is not the last NonTx subelement in current MBSSID IE,
+	 * return MNULL
+	 */
+	if ((pnontx_bssid->profile_data + pnontx_bssid->ieee_hdr.len) <
+	    (mbssid_end - 1)) {
+		PRINTM(MMSG, "Not the last Subelement\n");
+		return MNULL;
+	}
+
+	/* Search for the next MBSSID */
+	while (bytes_left >= 2) {
+		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
+		element_len = *((t_u8 *)pcurrent_ptr + 1);
+		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
+		PRINTM(MINFO, "bytes_left=%d total_ie_len=%d\n", bytes_left,
+		       total_ie_len);
+
+		if (bytes_left < total_ie_len) {
+			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
+				       "bytes left < IE length\n");
+			bytes_left = 0;
+			continue;
+		}
+		if (element_id == MULTI_BSSID) {
+			pnext_mbssid = (IEEEtypes_MultiBSSID_t *)pcurrent_ptr;
+			break;
+		}
+		pcurrent_ptr += total_ie_len;
+		bytes_left -= total_ie_len;
+	}
+
+	/* There isn't a next MBSSID IE - profile is complete.
+	 */
+	if (!pnext_mbssid) {
+		PRINTM(MMSG, "Profile Complete\n");
+		return MNULL;
+	}
+
+	/* Length error */
+	if (pnext_mbssid->ieee_hdr.len < 4) {
+		PRINTM(MERROR, "Next MBSSID Length error\n");
+		return MNULL;
+	}
+
+	/* Next nonTx BSSID */
+	pnext_nontx_bssid =
+		(IEEEtypes_NonTransBSSIDProfile_t *)pnext_mbssid->sub_elem_data;
+
+	/* Next nonTx BSSID length error */
+	if ((pnext_mbssid->sub_elem_data + pnext_mbssid->ieee_hdr.len - 1) <
+	    (pnext_nontx_bssid->profile_data +
+	     pnext_nontx_bssid->ieee_hdr.len)) {
+		PRINTM(MERROR, "Next nonTxBSSID Length error\n");
+		return MNULL;
+	}
+
+	if ((pnext_nontx_bssid->ieee_hdr.element_id != 0) ||
+	    (pnext_nontx_bssid->ieee_hdr.len < 2)) {
+		PRINTM(MERROR, "Next nonTxBSSID Length error\n");
+		return MNULL;
+	}
+
+	/* Check if next nonTx BSSID is start of a new profile
+	 * OR a split profile */
+	LEAVE();
+	return pnext_nontx_bssid->profile_data[0] == NONTX_BSSID_CAP ?
+		       MNULL :
+		       pnext_mbssid;
+}
+
+/**
+ *  @brief This function merges the NonTx BSSID profile entries split
+ *         across multiple MBSSID elements
+ *
+ *  @param pmpriv			A pointer to mlan adapter
+ *  @param pbss_entry   	A pointer to BSSDescriptor_t that has MBSSID IE
+ *  @param pmbssid     		A pointer to MBSSID IE
+ *  @param pnontx_bssid     A pointer to NonTx BSSID subelement
+ *  @param merged_ie        A pointer to merged NonTx BSSID element
+ *  @param max_copy_len     Maximum IE len in beacon/probe response
+ *  @return                 Length of merged NonTX BSSID element
+ */
+static t_u32
+wlan_merge_nontx_bssid_profile(pmlan_adapter pmadapter,
+			       BSSDescriptor_t *pbss_entry,
+			       IEEEtypes_MultiBSSID_t *pmbssid,
+			       IEEEtypes_NonTransBSSIDProfile_t *pnontx_bssid,
+			       t_u8 *merged_ie, t_u32 max_copy_len)
+{
+	IEEEtypes_MultiBSSID_t *pnext_mbssid = pmbssid;
+	IEEEtypes_NonTransBSSIDProfile_t *pnext_nontx_bssid = pnontx_bssid;
+	t_u32 copied_len = 0;
+	t_u32 ie_len = pbss_entry->beacon_buf_size - BEACON_FIX_SIZE;
+
+	ENTER();
+	if (!pmbssid || !pnontx_bssid) {
+		PRINTM(MERROR, "No MBSSID or NonTx BSSID element present\n");
+		return 0;
+	}
+
+	/* Length error */
+	if (pnontx_bssid->ieee_hdr.len > max_copy_len) {
+		PRINTM(MERROR,
+		       "Invalid NonTxBSSID profile length:%d max_copy_len:%d\n",
+		       pnontx_bssid->ieee_hdr.len, max_copy_len);
+		return 0;
+	}
+
+	copied_len = pnontx_bssid->ieee_hdr.len;
+	/* Copy the 1st part of NonTxBssid profile */
+	PRINTM(MINFO, "NonTxBSSID 1st part length: %d\n",
+	       pnontx_bssid->ieee_hdr.len);
+	memcpy_ext(pmadapter, merged_ie, pnontx_bssid->profile_data,
+		   pnontx_bssid->ieee_hdr.len, pnontx_bssid->ieee_hdr.len);
+
+	/* Check for split nonTxBssid in next MBSSID elem */
+	// coverity[overflow_sink:SUPPRESS]
+	while ((pnext_mbssid = wlan_get_next_mbssid_profile(
+			pbss_entry, ie_len, pnext_mbssid, pnext_nontx_bssid)) !=
+	       MNULL) {
+		// coverity[overflow_sink:SUPPRESS]
+		pnext_nontx_bssid = (IEEEtypes_NonTransBSSIDProfile_t *)
+					    pnext_mbssid->sub_elem_data;
+
+		if (copied_len + pnext_nontx_bssid->ieee_hdr.len >
+		    max_copy_len) {
+			PRINTM(MINFO, "Total length:%d\n",
+			       copied_len + pnext_nontx_bssid->ieee_hdr.len);
+			break;
+		}
+		memcpy_ext(pmadapter, merged_ie + copied_len,
+			   pnext_nontx_bssid->profile_data,
+			   pnext_nontx_bssid->ieee_hdr.len,
+			   pnext_nontx_bssid->ieee_hdr.len);
+		copied_len += pnext_nontx_bssid->ieee_hdr.len;
+		PRINTM(MINFO, "NonTxBSSID next part length: %d\n",
+		       pnext_nontx_bssid->ieee_hdr.len);
+	}
+
+	LEAVE();
+	// coverity[overflow_sink:SUPPRESS]
+	return copied_len;
+}
+
+/**
+ *  @brief This function parses the multi_bssid IE from pbss_entry
  *
  *  @param pmpriv        A pointer to mlan_private structure
- *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
- * IE
- *  @param num_in_table     A pointer to buffer to save num of entry in scan
- * table.
+ *  @param pbss_entry    A pointer to BSSDescriptor_t that has Multi-BSSID IE
+ *  @param pmulti_bssid  A pointer to Multi-BSSID IE
+ *  @param num_in_table  A pointer to number entry in the scan table
  *
- *  @return                 number entry in scan table
+ *  @return              void
  */
 static t_void wlan_parse_multi_bssid_ie(mlan_private *pmpriv,
 					BSSDescriptor_t *pbss_entry,
 					IEEEtypes_MultiBSSID_t *pmulti_bssid,
 					t_u32 *num_in_table)
 {
-	t_u32 bytes_left = 0;
+	mlan_adapter *pmadapter = pmpriv->adapter;
+	t_u32 bytes_left = 0, max_copy_len = 0, profile_len = 0;
 	t_u8 *pcurrent_ptr = MNULL;
 	IEEEtypes_NonTransBSSIDProfile_t *pbssid_profile = MNULL;
+	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
+	t_u8 *pmerged_profile = MNULL;
+	t_u8 ret = 0;
 
+	ENTER();
 	if (!pmulti_bssid)
 		return;
+
+	if (pmulti_bssid->ieee_hdr.len < 4) {
+		PRINTM(MINFO, "MBSSID IE length error!\n");
+		return;
+	}
+
+	max_copy_len = pbss_entry->beacon_buf_size - BEACON_FIX_SIZE;
 	bytes_left = pmulti_bssid->ieee_hdr.len - 1;
 	pcurrent_ptr = pmulti_bssid->sub_elem_data;
+
+	/* Allocate memory for the merged profile */
+	// coverity[overflow_sink:SUPPRESS]
+	// coverity[overwrite_var:SUPPRESS]
+	ret = pcb->moal_malloc(pmadapter->pmoal_handle, max_copy_len,
+			       MLAN_MEM_DEF, &pmerged_profile);
+	if (ret != MLAN_STATUS_SUCCESS || !pmerged_profile) {
+		PRINTM(MERROR,
+		       "Memory allocation for pmerged_profile failed!\n");
+		goto done;
+	}
+
 	while (bytes_left >= 2) {
+		/* NonTx BSSID Profile */
 		pbssid_profile =
 			(IEEEtypes_NonTransBSSIDProfile_t *)pcurrent_ptr;
+
 		if (pbssid_profile->ieee_hdr.element_id !=
 		    NONTRANS_BSSID_PROFILE_SUBELEM_ID) {
-			PRINTM(MERROR, "Invalid multi-bssid IE\n");
+			PRINTM(MERROR, "Invalid NonTx BSSID IE\n");
 			break;
 		}
 		if (bytes_left < (t_u32)(pbssid_profile->ieee_hdr.len + 2)) {
-			PRINTM(MERROR, "Invalid multi-bssid IE\n");
+			PRINTM(MERROR, "Invalid NonTx BSSID IE length\n");
 			break;
 		}
-		wlan_parse_non_trans_bssid_profile(
-			pmpriv, pbss_entry, pbssid_profile, num_in_table,
-			pmulti_bssid->max_bssid_indicator);
+
+		/* Check for NonTx BSSID Capability */
+		if (pbssid_profile->profile_data[0] != NONTX_BSSID_CAP) {
+			PRINTM(MERROR,
+			       "The first element within the NonTx BSSID profile is not the "
+			       "NonTx BSSID Capability element\n");
+			pcurrent_ptr += pbssid_profile->ieee_hdr.len + 2;
+			bytes_left -= pbssid_profile->ieee_hdr.len + 2;
+			continue;
+		}
+
+		/* Merge the split nonTxBSSID profiles */
+		profile_len = wlan_merge_nontx_bssid_profile(
+			pmpriv->adapter, pbss_entry, pmulti_bssid,
+			pbssid_profile, pmerged_profile, max_copy_len);
+		PRINTM(MCMND, "Length of Merged profile: %d\n", profile_len);
+		DBG_HEXDUMP(MCMD_D, "Merged NonTx Profile", pmerged_profile,
+			    profile_len);
+
+		/* Generate the NonTx BSSID entry and add to the scan table */
+		// coverity[overflow_sink:SUPPRESS]
+		wlan_gen_non_trans_bssid_profile(
+			pmpriv, pbss_entry, pmerged_profile, profile_len,
+			num_in_table, pmulti_bssid->max_bssid_indicator);
+
 		pcurrent_ptr += pbssid_profile->ieee_hdr.len + 2;
 		bytes_left -= pbssid_profile->ieee_hdr.len + 2;
+
+		// coverity[bad_memset:SUPPRESS]
+		memset(pmadapter, (t_u8 *)pmerged_profile, 0x00, max_copy_len);
 	}
+done:
+	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmerged_profile);
+	LEAVE();
 	return;
 }
 
@@ -5616,11 +6609,13 @@ static void wlan_parse_multi_bssid_ap(mlan_private *pmpriv,
 			bytes_left = 0;
 			continue;
 		}
-		if (element_id == MULTI_BSSID)
+		if (element_id == MULTI_BSSID) {
+			PRINTM(MINFO, "Found MBSSID IE!!\n");
 			wlan_parse_multi_bssid_ie(
 				pmpriv, pbss_entry,
 				(IEEEtypes_MultiBSSID_t *)pcurrent_ptr,
 				num_in_table);
+		}
 		pcurrent_ptr += total_ie_len;
 		bytes_left -= total_ie_len;
 	}
diff --git a/mlan/mlan_sdio.c b/mlan/mlan_sdio.c
index b79e543..ebd7e4b 100644
--- a/mlan/mlan_sdio.c
+++ b/mlan/mlan_sdio.c
@@ -226,7 +226,7 @@ static const struct _mlan_card_info mlan_card_info_sd8897 = {
 #if defined(SD8977) || defined(SD8997) || defined(SD8987) ||                   \
 	defined(SD9098) || defined(SD9097) || defined(SDIW624) ||              \
 	defined(SDAW693) || defined(SD8978) || defined(SD9177) ||              \
-	defined(SDIW615)
+	defined(SDIW610)
 static const struct _mlan_sdio_card_reg mlan_reg_sd8977_sd8997 = {
 	.start_rd_port = 0,
 	.start_wr_port = 0,
@@ -359,8 +359,8 @@ static const struct _mlan_card_info mlan_card_info_sd9177 = {
 };
 #endif
 
-#ifdef SDIW615
-static const struct _mlan_card_info mlan_card_info_sdiw615 = {
+#ifdef SDIW610
+static const struct _mlan_card_info mlan_card_info_sdiw610 = {
 	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
 	.v16_fw_api = 1,
 	.v17_fw_api = 1,
@@ -1068,11 +1068,11 @@ static mlan_status wlan_sdio_prog_fw_w_helper(pmlan_adapter pmadapter, t_u8 *fw,
 	}
 #endif
 #if defined(SD9097) || defined(SD9177) || defined(SDIW624) ||                  \
-	defined(SDAW693) || defined(SDIW615)
+	defined(SDAW693) || defined(SDIW610)
 	if (IS_SD9097(pmadapter->card_type) ||
 	    IS_SDIW624(pmadapter->card_type) ||
 	    IS_SDAW693(pmadapter->card_type) ||
-	    IS_SDIW615(pmadapter->card_type) || IS_SD9177(pmadapter->card_type))
+	    IS_SDIW610(pmadapter->card_type) || IS_SD9177(pmadapter->card_type))
 		check_fw_status = MTRUE;
 #endif
 
@@ -1280,6 +1280,7 @@ static mlan_status wlan_decode_rx_packet(mlan_adapter *pmadapter,
 {
 	t_u8 *cmd_buf;
 	t_u32 event;
+	t_u32 offset = 0;
 	t_u32 in_ts_sec, in_ts_usec;
 	pmlan_callbacks pcb = &pmadapter->callbacks;
 
@@ -1408,8 +1409,11 @@ static mlan_status wlan_decode_rx_packet(mlan_adapter *pmadapter,
 	case MLAN_TYPE_EVENT:
 		PRINTM(MINFO, "--- Rx: Event ---\n");
 
-		event = *(t_u32 *)&pmbuf->pbuf[pmbuf->data_offset +
-					       SDIO_INTF_HEADER_LEN];
+		if (!wlan_secure_add(&pmbuf->data_offset, SDIO_INTF_HEADER_LEN,
+				     &offset, TYPE_UINT32)) {
+			PRINTM(MERROR, "offset is invalid\n");
+		}
+		event = *(t_u32 *)&pmbuf->pbuf[offset];
 		pmadapter->event_cause = wlan_le32_to_cpu(event);
 		if ((pmadapter->upld_len > MLAN_EVENT_HEADER_LEN) &&
 		    ((pmadapter->upld_len - MLAN_EVENT_HEADER_LEN) <
@@ -1937,6 +1941,7 @@ static mlan_status wlan_host_to_card_mp_aggr(mlan_adapter *pmadapter,
 	t_s32 f_send_cur_buf = 0;
 	t_s32 f_precopy_cur_buf = 0;
 	t_s32 f_postcopy_cur_buf = 0;
+	t_u32 temp = 0;
 	t_u8 aggr_sg = 0;
 	t_u8 mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
 	t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode;
@@ -2055,8 +2060,12 @@ tx_curr_single:
 	if (f_send_cur_buf) {
 		PRINTM(MINFO, "host_2_card_mp_aggr: writing to port #%d\n",
 		       port);
-		ret = wlan_write_data_sync(pmadapter, mbuf,
-					   pmadapter->pcard_sd->ioport + port);
+		if (!wlan_secure_add(&pmadapter->pcard_sd->ioport, port, &temp,
+				     TYPE_UINT32)) {
+			PRINTM(MERROR, "temp is  overflowed\n");
+			return MLAN_STATUS_FAILURE;
+		}
+		ret = wlan_write_data_sync(pmadapter, mbuf, temp);
 		if (!(pmadapter->pcard_sd->mp_wr_bitmap &
 		      (1 << pmadapter->pcard_sd->curr_wr_port)))
 			pmadapter->pcard_sd->mpa_sent_no_ports++;
@@ -2463,10 +2472,10 @@ mlan_status wlan_get_sdio_device(pmlan_adapter pmadapter)
 		pmadapter->pcard_info = &mlan_card_info_sdaw693;
 		break;
 #endif
-#ifdef SDIW615
-	case CARD_TYPE_SDIW615:
+#ifdef SDIW610
+	case CARD_TYPE_SDIW610:
 		pmadapter->pcard_sd->reg = &mlan_reg_sd8977_sd8997;
-		pmadapter->pcard_info = &mlan_card_info_sdiw615;
+		pmadapter->pcard_info = &mlan_card_info_sdiw610;
 		break;
 #endif
 #ifdef SD9177
@@ -3086,7 +3095,7 @@ exit:
 
 #if defined(SD9098) || defined(SD9097) || defined(SDIW624) ||                  \
 	defined(SDAW693) || defined(SD9177) || defined(SD8997) ||              \
-	defined(SD8987) || defined(SD8978) || defined(SDIW615)
+	defined(SD8987) || defined(SD8978) || defined(SDIW610)
 /**
  *  @brief This function sends vdll data to the card.
  *
@@ -3149,7 +3158,7 @@ static mlan_status wlan_sdio_host_to_card_ext(pmlan_private pmpriv, t_u8 type,
 
 #if defined(SD9098) || defined(SD9097) || defined(SDIW624) ||                  \
 	defined(SDAW693) || defined(SD9177) || defined(SD8997) ||              \
-	defined(SD8987) || defined(SD8978) || defined(SDIW615)
+	defined(SD8987) || defined(SD8978) || defined(SDIW610)
 	if (type == MLAN_TYPE_VDLL)
 		return wlan_sdio_send_vdll(pmadapter, pmbuf);
 #endif
@@ -3479,8 +3488,12 @@ static mlan_status wlan_pm_sdio_wakeup_card(pmlan_adapter pmadapter,
 		pmadapter->wakeup_fw_timer_is_set = MTRUE;
 	}
 
-	ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
-				  HOST_TO_CARD_EVENT_REG, HOST_POWER_UP);
+	if (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
+		/* GPIO_PORT_TO_LOW(); */
+	} else
+		ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+					  HOST_TO_CARD_EVENT_REG,
+					  HOST_POWER_UP);
 
 	LEAVE();
 	return ret;
@@ -3500,8 +3513,11 @@ static mlan_status wlan_pm_sdio_reset_card(pmlan_adapter pmadapter)
 
 	ENTER();
 
-	ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
-				  HOST_TO_CARD_EVENT_REG, 0);
+	if (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
+		/* GPIO_PORT_TO_HIGH(); */
+	} else
+		ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
+					  HOST_TO_CARD_EVENT_REG, 0);
 
 	LEAVE();
 	return ret;
@@ -3633,7 +3649,7 @@ mlan_status wlan_reset_fw(pmlan_adapter pmadapter)
 #if defined(SD8997) || defined(SD8977) || defined(SD8987) ||                   \
 	defined(SD9098) || defined(SD9097) || defined(SDIW624) ||              \
 	defined(SDAW693) || defined(SD8978) || defined(SD9177) ||              \
-	defined(SDIW615)
+	defined(SDIW610)
 	if (MFALSE
 #ifdef SD8997
 	    || IS_SD8997(pmadapter->card_type)
@@ -3659,8 +3675,8 @@ mlan_status wlan_reset_fw(pmlan_adapter pmadapter)
 #ifdef SDAW693
 	    || IS_SDAW693(pmadapter->card_type)
 #endif
-#ifdef SDIW615
-	    || IS_SDIW615(pmadapter->card_type)
+#ifdef SDIW610
+	    || IS_SDIW610(pmadapter->card_type)
 #endif
 #ifdef SD9177
 	    || IS_SD9177(pmadapter->card_type)
diff --git a/mlan/mlan_shim.c b/mlan/mlan_shim.c
index 165602f..0752d7f 100644
--- a/mlan/mlan_shim.c
+++ b/mlan/mlan_shim.c
@@ -317,6 +317,8 @@ mlan_status mlan_register(pmlan_device pmdevice, t_void **ppmlan_adapter)
 	MASSERT(pcb->moal_hist_data_add);
 	MASSERT(pcb->moal_updata_peer_signal);
 	MASSERT(pcb->moal_do_div);
+
+	MASSERT(pcb->moal_get_host_time_ns);
 	/* Save pmoal_handle */
 	pmadapter->pmoal_handle = pmdevice->pmoal_handle;
 
@@ -326,10 +328,12 @@ mlan_status mlan_register(pmlan_device pmdevice, t_void **ppmlan_adapter)
 	pmadapter->card_rev = pmdevice->card_rev;
 	pmadapter->init_para.uap_max_sta = pmdevice->uap_max_sta;
 	pmadapter->init_para.wacp_mode = pmdevice->wacp_mode;
+	pmadapter->init_para.fw_data_cfg = pmdevice->fw_data_cfg;
 	pmadapter->init_para.mcs32 = pmdevice->mcs32;
 	pmadapter->init_para.antcfg = pmdevice->antcfg;
 	pmadapter->init_para.reject_addba_req = pmdevice->reject_addba_req;
 	pmadapter->init_para.dmcs = pmdevice->dmcs;
+	pmadapter->init_para.pref_dbc = pmdevice->pref_dbc;
 
 #ifdef SDIO
 	if (IS_SD(pmadapter->card_type)) {
@@ -346,10 +350,8 @@ mlan_status mlan_register(pmlan_device pmdevice, t_void **ppmlan_adapter)
 		}
 		if ((pmdevice->int_mode == INT_MODE_GPIO) &&
 		    (pmdevice->gpio_pin == 0)) {
-			PRINTM(MERROR,
-			       "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n");
-			ret = MLAN_STATUS_FAILURE;
-			goto error;
+			PRINTM(MINFO,
+			       "SDIO_GPIO_INT_CONFIG: FW will duplicate SDIO Intr on GPIO-21\n");
 		}
 		pmadapter->init_para.int_mode = pmdevice->int_mode;
 		pmadapter->init_para.gpio_pin = pmdevice->gpio_pin;
@@ -382,6 +384,10 @@ mlan_status mlan_register(pmlan_device pmdevice, t_void **ppmlan_adapter)
 			   sizeof(mlan_adapter_operations),
 			   sizeof(mlan_adapter_operations));
 		pmadapter->init_para.ring_size = pmdevice->ring_size;
+		pmadapter->init_para.max_tx_pending = pmdevice->max_tx_pending;
+		pmadapter->init_para.tx_budget = pmdevice->tx_budget;
+		pmadapter->init_para.mclient_scheduling =
+			pmdevice->mclient_scheduling;
 		ret = wlan_get_pcie_device(pmadapter);
 		if (MLAN_STATUS_SUCCESS != ret) {
 			ret = MLAN_STATUS_FAILURE;
@@ -417,6 +423,7 @@ mlan_status mlan_register(pmlan_device pmdevice, t_void **ppmlan_adapter)
 #endif
 	pmadapter->init_para.auto_ds = pmdevice->auto_ds;
 	pmadapter->init_para.ext_scan = pmdevice->ext_scan;
+	pmadapter->init_para.bootup_cal_ctrl = pmdevice->bootup_cal_ctrl;
 	pmadapter->init_para.ps_mode = pmdevice->ps_mode;
 	if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
 	    pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
@@ -1318,10 +1325,24 @@ process_start:
 		}
 
 		/* Check for event */
+#ifdef USB
+		if (IS_USB(pmadapter->card_type))
+			wlan_request_event_lock(pmadapter);
+#endif
 		if (pmadapter->event_received) {
 			pmadapter->event_received = MFALSE;
+#ifdef USB
+			if (IS_USB(pmadapter->card_type))
+				wlan_release_event_lock(pmadapter);
+#endif
 			wlan_process_event(pmadapter);
 		}
+#ifdef USB
+		else {
+			if (IS_USB(pmadapter->card_type))
+				wlan_release_event_lock(pmadapter);
+		}
+#endif
 		/* Check if we need to confirm Sleep Request received previously
 		 */
 		if (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
@@ -1447,35 +1468,42 @@ exit_main_proc:
 static void mlan_check_llde_pkt_filter(mlan_adapter *pmadapter,
 				       pmlan_buffer pmbuf, t_u8 ip_protocol)
 {
-	mlan_private *pmpriv = pmadapter->priv[pmbuf->bss_index];
 	t_u8 matched_filter = 0;
+	t_u8 i = 0;
 
 	if (!(pmadapter->llde_enabled &&
 	      (pmadapter->llde_mode == MLAN_11AXCMD_LLDE_MODE_EVENT_DRIVEN))) {
 		return;
 	}
 	/* match iphone mac addr */
-	if (pmadapter->llde_device_filter == 1) {
-		sta_node *sta_ptr = MNULL;
-		// get station entry from Peer MAC address
-		sta_ptr = wlan_get_station_entry(
-			pmpriv, (pmbuf->pbuf + pmbuf->data_offset));
-		if (sta_ptr && sta_ptr->is_apple_sta) {
-			matched_filter = 1;
+	if (pmadapter->llde_device_filter) {
+		for (i = 0; i < pmadapter->llde_totalIPhones; i++) {
+			if (memcmp(pmadapter,
+				   &pmadapter->llde_iphonefilters
+					    [i * MLAN_MAC_ADDR_LENGTH],
+				   (pmbuf->pbuf + pmbuf->data_offset),
+				   MLAN_MAC_ADDR_LENGTH) == 0) {
+				matched_filter = 1;
+				break;
+			}
 		}
 	}
 	if (matched_filter == 0) {
 		/* check mac filter if iphone device filter not matched */
-		if ((memcmp(pmadapter, pmadapter->llde_macfilter1,
-			    (pmbuf->pbuf + pmbuf->data_offset),
-			    MLAN_MAC_ADDR_LENGTH) == 0) ||
-		    (memcmp(pmadapter, pmadapter->llde_macfilter2,
-			    (pmbuf->pbuf + pmbuf->data_offset),
-			    MLAN_MAC_ADDR_LENGTH) == 0)) {
-			matched_filter = 1;
+		for (i = 0; i < pmadapter->llde_totalMacFilters; i++) {
+			if (memcmp(pmadapter,
+				   &pmadapter->llde_macfilters
+					    [i * MLAN_MAC_ADDR_LENGTH],
+				   (pmbuf->pbuf + pmbuf->data_offset),
+				   MLAN_MAC_ADDR_LENGTH) == 0) {
+				matched_filter = 1;
+				break;
+			}
 		}
 	}
 
+	/* device address is matched, check packet type to mark it as special
+	 * llde packet */
 	if (matched_filter) {
 		if ((pmadapter->llde_packet_type == LLDE_FILTER_PKT_ALL) ||
 		    ((pmadapter->llde_packet_type == LLDE_FILTER_PKT_UDP) &&
@@ -1811,11 +1839,13 @@ mlan_status mlan_recv(t_void *padapter, pmlan_buffer pmbuf, t_u32 port)
 			if ((len > 0) && (len < MAX_EVENT_SIZE))
 				memmove(pmadapter, pmadapter->event_body, pbuf,
 					len);
+			wlan_request_event_lock(pmadapter);
 			/* remove 4 byte recv_type */
 			pmbuf->data_offset += MLAN_TYPE_LEN;
 			pmbuf->data_len -= MLAN_TYPE_LEN;
 			pmadapter->event_received = MTRUE;
 			pmadapter->pmlan_buffer_event = pmbuf;
+			wlan_release_event_lock(pmadapter);
 			/* MOAL to call mlan_main_process for processing */
 			break;
 		default:
diff --git a/mlan/mlan_sta_cmd.c b/mlan/mlan_sta_cmd.c
index 20437ea..4dd1712 100644
--- a/mlan/mlan_sta_cmd.c
+++ b/mlan/mlan_sta_cmd.c
@@ -549,6 +549,44 @@ static mlan_status wlan_cmd_mfg_otp_rw(pmlan_private pmpriv,
 	return MLAN_STATUS_SUCCESS;
 }
 
+/**
+ *  @brief This function prepares command of MFG OTP CAL DATA RW.
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
+ *  @param action       The action: GET or SET
+ *  @param pdata_buf    A pointer to data buffer
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+
+static mlan_status wlan_cmd_mfg_otp_cal_data_rw(pmlan_private pmpriv,
+						HostCmd_DS_COMMAND *cmd,
+						t_u16 action, t_void *pdata_buf)
+{
+	mfg_cmd_otp_cal_data_rd_wr_t *mcmd =
+		(mfg_cmd_otp_cal_data_rd_wr_t *)&cmd->params
+			.mfg_otp_cal_data_rd_wr;
+	mfg_cmd_otp_cal_data_rd_wr_t *cfg =
+		(mfg_cmd_otp_cal_data_rd_wr_t *)pdata_buf;
+
+	ENTER();
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND);
+	cmd->size = wlan_cpu_to_le16(sizeof(mfg_cmd_otp_cal_data_rd_wr_t) +
+				     S_DS_GEN);
+
+	mcmd->mfg_cmd = wlan_cpu_to_le32(cfg->mfg_cmd);
+	mcmd->action = wlan_cpu_to_le16(cfg->action);
+	mcmd->cal_data_status = wlan_cpu_to_le32(cfg->cal_data_status);
+	mcmd->cal_data_len = wlan_cpu_to_le32(cfg->cal_data_len);
+	if (action == HostCmd_ACT_GEN_SET) {
+		memcpy_ext(pmpriv->adapter, mcmd->cal_data, cfg->cal_data,
+			   mcmd->cal_data_len, mcmd->cal_data_len);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
 /**
  *  @brief This function prepares command of MFG cmd.
  *
@@ -591,6 +629,10 @@ mlan_status wlan_cmd_mfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
 	case MFG_CMD_OTP_MAC_ADD:
 		ret = wlan_cmd_mfg_otp_rw(pmpriv, cmd, action, pdata_buf);
 		goto cmd_mfg_done;
+	case MFG_CMD_OTP_CAL_DATA:
+		ret = wlan_cmd_mfg_otp_cal_data_rw(pmpriv, cmd, action,
+						   pdata_buf);
+		goto cmd_mfg_done;
 	case MFG_CMD_SET_TEST_MODE:
 	case MFG_CMD_UNSET_TEST_MODE:
 	case MFG_CMD_TX_ANT:
@@ -3610,6 +3652,51 @@ static mlan_status wlan_is_cmd_allowed(mlan_private *priv, t_u16 cmd_no)
 	return ret;
 }
 
+/**
+ *  @brief This function prepares command to configure Auth, (Re)assoc Timeout
+ *
+ *  @param pmpriv      A pointer to mlan_private structure
+ *  @param cmd         A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action  Action: GET or SET
+ *  @param pdata_buf   A pointer to data buffer
+ *
+ *  @return            MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_cmd_auth_assoc_timeout_cfg(pmlan_private pmpriv,
+						   HostCmd_DS_COMMAND *cmd,
+						   t_u16 cmd_action,
+						   t_void *pdata_buf)
+{
+	HostCmd_DS_AUTH_ASSOC_TIMEOUT_CFG *auth_assoc_cmd =
+		&cmd->params.auth_assoc_cfg;
+	mlan_ds_auth_assoc_timeout_cfg *auth_assoc_cfg =
+		(mlan_ds_auth_assoc_timeout_cfg *)pdata_buf;
+
+	ENTER();
+
+	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_AUTH_ASSOC_TIMEOUT_CFG);
+	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_AUTH_ASSOC_TIMEOUT_CFG) +
+				     S_DS_GEN);
+
+	auth_assoc_cmd->action = wlan_cpu_to_le16(cmd_action);
+
+	auth_assoc_cmd->auth_timeout =
+		wlan_cpu_to_le16(auth_assoc_cfg->auth_timeout);
+	auth_assoc_cmd->auth_retry_timeout_if_ack =
+		wlan_cpu_to_le16(auth_assoc_cfg->auth_retry_timeout_if_ack);
+	auth_assoc_cmd->auth_retry_timeout_if_no_ack =
+		wlan_cpu_to_le16(auth_assoc_cfg->auth_retry_timeout_if_no_ack);
+	auth_assoc_cmd->assoc_timeout =
+		wlan_cpu_to_le16(auth_assoc_cfg->assoc_timeout);
+	auth_assoc_cmd->reassoc_timeout =
+		wlan_cpu_to_le16(auth_assoc_cfg->reassoc_timeout);
+	auth_assoc_cmd->retry_timeout =
+		wlan_cpu_to_le16(auth_assoc_cfg->retry_timeout);
+
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
 /**
  *  @brief This function prepare the command before sending to firmware.
  *
@@ -3687,6 +3774,10 @@ mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no,
 		ret = wlan_cmd_802_11_hs_cfg(pmpriv, cmd_ptr, cmd_action,
 					     (hs_config_param *)pdata_buf);
 		break;
+	case HostCmd_CMD_802_11_FW_WAKE_METHOD:
+		ret = wlan_cmd_802_11_fw_wakeup_method(pmpriv, cmd_ptr,
+						       cmd_action, pdata_buf);
+		break;
 	case HostCmd_CMD_802_11_ROBUSTCOEX:
 		ret = wlan_cmd_robustcoex(pmpriv, cmd_ptr, cmd_action,
 					  pdata_buf);
@@ -3803,8 +3894,7 @@ mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no,
 		if (pmpriv->adapter->hw_status == WlanHardwareStatusReset)
 			pmpriv->adapter->hw_status =
 				WlanHardwareStatusInitializing;
-		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
-		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		ret = wlan_cmd_func_init(pmpriv, cmd_ptr);
 		break;
 	case HostCmd_CMD_FUNC_SHUTDOWN:
 		pmpriv->adapter->hw_status = WlanHardwareStatusReset;
@@ -3989,6 +4079,12 @@ mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no,
 						 pdata_buf);
 		break;
 #endif
+#endif
+#if defined(PCIE)
+	case HostCmd_CMD_PCIE_ADMA_INIT:
+		ret = wlan_cmd_pcie_adma_init(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
 #endif
 	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
 		ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action,
@@ -4080,10 +4176,8 @@ mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no,
 						     cmd_action, pdata_buf);
 		break;
 	case HostCmd_CMD_CHAN_REGION_CFG:
-		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
-		cmd_ptr->size = wlan_cpu_to_le16(
-			sizeof(HostCmd_DS_CHAN_REGION_CFG) + S_DS_GEN);
-		cmd_ptr->params.reg_cfg.action = wlan_cpu_to_le16(cmd_action);
+		ret = wlan_cmd_chan_region_cfg(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
 		break;
 	case HostCmd_CMD_REGION_POWER_CFG:
 		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
@@ -4192,6 +4286,10 @@ mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no,
 		ret = wlan_cmd_cross_chip_synch(pmpriv, cmd_ptr, cmd_action,
 						pdata_buf);
 		break;
+	case HostCmd_CMD_TSP_CFG:
+		ret = wlan_cmd_tsp_config(pmpriv, cmd_ptr, cmd_action,
+					  pdata_buf);
+		break;
 	case HostCmd_CMD_802_11_TX_FRAME:
 		ret = wlan_cmd_tx_frame(pmpriv, cmd_ptr, cmd_action, pdata_buf);
 		break;
@@ -4199,6 +4297,18 @@ mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no,
 		ret = wlan_cmd_edmac_cfg(pmpriv, cmd_ptr, cmd_action,
 					 pdata_buf);
 		break;
+	case HostCmd_CMD_PEER_TX_RATE_QUERY:
+		ret = wlan_cmd_sta_tx_rate_req(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
+		break;
+	case HostCmd_CMD_MCLIENT_SCHEDULE_CFG:
+		ret = wlan_cmd_mclient_scheduling_cfg(pmpriv, cmd_ptr,
+						      cmd_action, pdata_buf);
+		break;
+	case HostCmd_CMD_AUTH_ASSOC_TIMEOUT_CFG:
+		ret = wlan_cmd_auth_assoc_timeout_cfg(pmpriv, cmd_ptr,
+						      cmd_action, pdata_buf);
+		break;
 	default:
 		PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no);
 		ret = MLAN_STATUS_FAILURE;
diff --git a/mlan/mlan_sta_cmdresp.c b/mlan/mlan_sta_cmdresp.c
index 7c791c1..116506c 100644
--- a/mlan/mlan_sta_cmdresp.c
+++ b/mlan/mlan_sta_cmdresp.c
@@ -754,6 +754,8 @@ static mlan_status wlan_ret_get_log(pmlan_private pmpriv,
 			wlan_le32_to_cpu(pget_log->gdma_abort_cnt);
 		pget_info->param.stats.g_reset_rx_mac_cnt =
 			wlan_le32_to_cpu(pget_log->g_reset_rx_mac_cnt);
+		pget_info->param.stats.SdmaStuckCnt =
+			wlan_le32_to_cpu(pget_log->SdmaStuckCnt);
 		// Ownership error counters
 		pget_info->param.stats.dwCtlErrCnt =
 			wlan_le32_to_cpu(pget_log->dwCtlErrCnt);
@@ -1825,7 +1827,7 @@ static mlan_status wlan_ret_tdls_config(pmlan_private pmpriv,
 				wlan_le16_to_cpu(link_ptr->data_rssi_avg);
 			link_ptr->data_nf_avg =
 				wlan_le16_to_cpu(link_ptr->data_nf_avg);
-			link_length = sizeof(tdls_each_link_status) - 1;
+			link_length = sizeof(tdls_each_link_status);
 			/* adjust as per open or secure network */
 			if (link_ptr->link_flags & 0x02) {
 				link_ptr->key_lifetime = wlan_le32_to_cpu(
@@ -3036,6 +3038,40 @@ static mlan_status wlan_ret_mfg_otp_rw(pmlan_private pmpriv,
 	return MLAN_STATUS_SUCCESS;
 }
 
+/**
+ *  @brief This function prepares command resp of MFG CMD OTP CAL DATA RW
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+
+static mlan_status wlan_ret_mfg_otp_cal_data_rw(pmlan_private pmpriv,
+						HostCmd_DS_COMMAND *resp,
+						mlan_ioctl_req *pioctl_buf)
+{
+	mlan_ds_misc_cfg *misc = MNULL;
+	mfg_cmd_otp_cal_data_rd_wr_t *cfg = MNULL;
+	mfg_cmd_otp_cal_data_rd_wr_t *mcmd =
+		(mfg_cmd_otp_cal_data_rd_wr_t *)&resp->params
+			.mfg_otp_cal_data_rd_wr;
+
+	ENTER();
+	if (!pioctl_buf) {
+		LEAVE();
+		return MLAN_STATUS_FAILURE;
+	}
+	misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+	cfg = (mfg_cmd_otp_cal_data_rd_wr_t *)&misc->param
+		      .mfg_otp_cal_data_rd_wr;
+	memcpy_ext(pmpriv->adapter, &(cfg->cal_data[0]), &(mcmd->cal_data[0]),
+		   cfg->cal_data_len, cfg->cal_data_len);
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
 /**
  *  @brief This function prepares command resp of MFG Cmd
  *
@@ -3078,6 +3114,9 @@ mlan_status wlan_ret_mfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 	case MFG_CMD_OTP_MAC_ADD:
 		ret = wlan_ret_mfg_otp_rw(pmpriv, resp, pioctl_buf);
 		goto cmd_mfg_done;
+	case MFG_CMD_OTP_CAL_DATA:
+		ret = wlan_ret_mfg_otp_cal_data_rw(pmpriv, resp, pioctl_buf);
+		goto cmd_mfg_done;
 	case MFG_CMD_SET_TEST_MODE:
 	case MFG_CMD_UNSET_TEST_MODE:
 	case MFG_CMD_TX_ANT:
@@ -3100,7 +3139,8 @@ mlan_status wlan_ret_mfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 	card_type = card_type & 0xff;
 	if (((card_type == CARD_TYPE_9098) || (card_type == CARD_TYPE_9097) ||
 	     (card_type == CARD_TYPE_9177) || (card_type == CARD_TYPE_IW624) ||
-	     (card_type == CARD_TYPE_AW693)) &&
+	     (card_type == CARD_TYPE_AW693) ||
+	     (card_type == CARD_TYPE_IW610)) &&
 	    (wlan_le32_to_cpu(mcmd->mfg_cmd) == MFG_CMD_RFPWR)) {
 		//! TX_POWER was multipied by 16 while passing to fw
 		//! So It is needed to divide by 16 for user vals understanding.
@@ -3112,6 +3152,9 @@ mlan_status wlan_ret_mfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 	cfg->data2 = wlan_le32_to_cpu(mcmd->data2);
 	cfg->data3 = wlan_le32_to_cpu(mcmd->data3);
 cmd_mfg_done:
+	if (mcmd->error)
+		PRINTM(MERROR, "RFTM_COMMAND ERROR: 0x%08x\n",
+		       wlan_le32_to_cpu(mcmd->error));
 	LEAVE();
 	return ret;
 }
@@ -3149,6 +3192,47 @@ mlan_status wlan_ret_twt_report(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
 	return MLAN_STATUS_SUCCESS;
 }
 
+/**
+ *  @brief This function handles the command response of auth assoc timeout cfg
+ *
+ *  @param pmpriv       A pointer to mlan_private structure
+ *  @param resp         A pointer to HostCmd_DS_COMMAND
+ *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
+ *
+ *  @return             MLAN_STATUS_SUCCESS
+ */
+mlan_status wlan_ret_auth_assoc_timeout_cfg(pmlan_private pmpriv,
+					    HostCmd_DS_COMMAND *resp,
+					    mlan_ioctl_req *pioctl_buf)
+{
+	HostCmd_DS_AUTH_ASSOC_TIMEOUT_CFG *auth_assoc_cmd =
+		(HostCmd_DS_AUTH_ASSOC_TIMEOUT_CFG *)&resp->params
+			.auth_assoc_cfg;
+	mlan_ds_misc_cfg *misc_cfg = MNULL;
+
+	ENTER();
+
+	if (pioctl_buf) {
+		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
+		misc_cfg->param.auth_assoc_cfg.auth_timeout =
+			wlan_le16_to_cpu(auth_assoc_cmd->auth_timeout);
+		misc_cfg->param.auth_assoc_cfg.auth_retry_timeout_if_ack =
+			wlan_le16_to_cpu(
+				auth_assoc_cmd->auth_retry_timeout_if_ack);
+		misc_cfg->param.auth_assoc_cfg.auth_retry_timeout_if_no_ack =
+			wlan_le16_to_cpu(
+				auth_assoc_cmd->auth_retry_timeout_if_no_ack);
+		misc_cfg->param.auth_assoc_cfg.assoc_timeout =
+			wlan_le16_to_cpu(auth_assoc_cmd->assoc_timeout);
+		misc_cfg->param.auth_assoc_cfg.reassoc_timeout =
+			wlan_le16_to_cpu(auth_assoc_cmd->reassoc_timeout);
+		misc_cfg->param.auth_assoc_cfg.retry_timeout =
+			wlan_le16_to_cpu(auth_assoc_cmd->retry_timeout);
+	}
+	LEAVE();
+	return MLAN_STATUS_SUCCESS;
+}
+
 /**
  *  @brief This function handles the station command response
  *
@@ -3243,6 +3327,9 @@ mlan_status wlan_ops_sta_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
 	case HostCmd_CMD_802_11_SLEEP_PARAMS:
 		ret = wlan_ret_802_11_sleep_params(pmpriv, resp, pioctl_buf);
 		break;
+	case HostCmd_CMD_802_11_FW_WAKE_METHOD:
+		ret = wlan_ret_fw_wakeup_method(pmpriv, resp, pioctl_buf);
+		break;
 	case HostCmd_CMD_802_11_ROBUSTCOEX:
 		break;
 	case HostCmd_CMD_DMCS_CONFIG:
@@ -3487,6 +3574,12 @@ mlan_status wlan_ops_sta_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
 		PRINTM(MINFO, "PCIE host buffer configuration successful.\n");
 		break;
 #endif
+#endif
+#if defined(PCIE)
+	case HostCmd_CMD_PCIE_ADMA_INIT:
+		PRINTM(MINFO, "PCIE ADMA init successful.\n");
+		wlan_pcie_init_fw(pmpriv->adapter);
+		break;
 #endif
 	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
 		ret = wlan_ret_remain_on_channel(pmpriv, resp, pioctl_buf);
@@ -3651,10 +3744,21 @@ mlan_status wlan_ops_sta_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
 	case HostCmd_CMD_CROSS_CHIP_SYNCH:
 		ret = wlan_ret_cross_chip_synch(pmpriv, resp, pioctl_buf);
 		break;
+	case HostCmd_CMD_TSP_CFG:
+		ret = wlan_ret_tsp_config(pmpriv, resp, pioctl_buf);
+		break;
 	case HostCmd_CMD_802_11_TX_FRAME:
 		break;
 	case HostCmd_CMD_EDMAC_CFG:
 		break;
+	case HostCmd_CMD_PEER_TX_RATE_QUERY:
+		ret = wlan_ret_sta_tx_rate(pmpriv, resp, pioctl_buf);
+		break;
+	case HostCmd_CMD_MCLIENT_SCHEDULE_CFG:
+		break;
+	case HostCmd_CMD_AUTH_ASSOC_TIMEOUT_CFG:
+		ret = wlan_ret_auth_assoc_timeout_cfg(pmpriv, resp, pioctl_buf);
+		break;
 	default:
 		PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n",
 		       resp->command);
diff --git a/mlan/mlan_sta_event.c b/mlan/mlan_sta_event.c
index e5fa3ea..96bb2cb 100644
--- a/mlan/mlan_sta_event.c
+++ b/mlan/mlan_sta_event.c
@@ -611,15 +611,9 @@ static void wlan_process_sta_tx_pause_event(pmlan_private priv,
 		}
 		if (tlv_type == TLV_TYPE_TX_PAUSE) {
 			tx_pause_tlv = (MrvlIEtypes_tx_pause_t *)tlv;
-			PRINTM(MCMND,
-			       "TxPause: " MACSTR
-			       " pause=%d, pkts=%d, priv->tx_pause=%d\n",
+			PRINTM(MCMND, "TxPause: " MACSTR " pause=%d, pkts=%d\n",
 			       MAC2STR(tx_pause_tlv->peermac),
-			       tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt,
-			       priv->tx_pause);
-			if (bssid)
-				PRINTM(MCMND, "TxPause: " MACSTR "\n",
-				       MAC2STR(bssid));
+			       tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt);
 			status = wlan_get_tdls_link_status(
 				priv, tx_pause_tlv->peermac);
 			if (status != TDLS_NOT_SETUP) {
@@ -971,6 +965,13 @@ mlan_status wlan_ops_sta_process_event(t_void *priv)
 		wlan_recv_event(pmpriv, pevent->event_id, pevent);
 		break;
 
+	case EVENT_CHAN_SWITCH_TO_6G_BLOCK:
+		reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+							  pmbuf->data_offset +
+							  sizeof(eventcause)));
+		print_chan_switch_block_event(reason_code);
+		break;
+
 	case EVENT_BG_SCAN_REPORT:
 		PRINTM(MEVENT, "EVENT: BGS_REPORT\n");
 		pmadapter->bgscan_reported = MTRUE;
diff --git a/mlan/mlan_sta_ioctl.c b/mlan/mlan_sta_ioctl.c
index bbd2f5d..e1d21e4 100644
--- a/mlan/mlan_sta_ioctl.c
+++ b/mlan/mlan_sta_ioctl.c
@@ -692,47 +692,39 @@ static mlan_status wlan_bss_ioctl_set_multicast_list(pmlan_adapter pmadapter,
 	}
 	pioctl_req->data_read_written =
 		sizeof(mlan_multicast_list) + MLAN_SUB_COMMAND_SIZE;
-	if (bss->param.multicast_list.mode == MLAN_PROMISC_MODE) {
-		PRINTM(MINFO, "Enable Promiscuous mode\n");
-		pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+	/* Multicast */
+	pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+	if (bss->param.multicast_list.mode == MLAN_ALL_MULTI_MODE) {
+		PRINTM(MINFO, "Enabling All Multicast!\n");
+		pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+	} else {
 		pmpriv->curr_pkt_filter &=
 			~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
-	} else {
-		/* Multicast */
-		pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
-		if (bss->param.multicast_list.mode == MLAN_ALL_MULTI_MODE) {
-			PRINTM(MINFO, "Enabling All Multicast!\n");
+		if (bss->param.multicast_list.mode == MLAN_PROMISC_MODE)
 			pmpriv->curr_pkt_filter |=
-				HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
-		} else {
-			pmpriv->curr_pkt_filter &=
-				~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
-			if (bss->param.multicast_list.num_multicast_addr) {
-				PRINTM(MINFO, "Set multicast list=%d\n",
-				       bss->param.multicast_list
-					       .num_multicast_addr);
-				/* Set multicast addresses to firmware */
-				if (old_pkt_filter == pmpriv->curr_pkt_filter) {
-					/* Send request to firmware */
-					ret = wlan_prepare_cmd(
-						pmpriv,
-						HostCmd_CMD_MAC_MULTICAST_ADR,
-						HostCmd_ACT_GEN_SET, 0,
-						(t_void *)pioctl_req,
-						&bss->param.multicast_list);
-					if (ret == MLAN_STATUS_SUCCESS)
-						ret = MLAN_STATUS_PENDING;
-				} else {
-					/* Send request to firmware */
-					ret = wlan_prepare_cmd(
-						pmpriv,
-						HostCmd_CMD_MAC_MULTICAST_ADR,
-						HostCmd_ACT_GEN_SET, 0, MNULL,
-						&bss->param.multicast_list);
-				}
-				if (ret)
-					goto exit;
+				HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+		if (bss->param.multicast_list.num_multicast_addr) {
+			PRINTM(MINFO, "Set multicast list=%d\n",
+			       bss->param.multicast_list.num_multicast_addr);
+			/* Set multicast addresses to firmware */
+			if (old_pkt_filter == pmpriv->curr_pkt_filter) {
+				/* Send request to firmware */
+				ret = wlan_prepare_cmd(
+					pmpriv, HostCmd_CMD_MAC_MULTICAST_ADR,
+					HostCmd_ACT_GEN_SET, 0,
+					(t_void *)pioctl_req,
+					&bss->param.multicast_list);
+				if (ret == MLAN_STATUS_SUCCESS)
+					ret = MLAN_STATUS_PENDING;
+			} else {
+				/* Send request to firmware */
+				ret = wlan_prepare_cmd(
+					pmpriv, HostCmd_CMD_MAC_MULTICAST_ADR,
+					HostCmd_ACT_GEN_SET, 0, MNULL,
+					&bss->param.multicast_list);
 			}
+			if (ret)
+				goto exit;
 		}
 	}
 	PRINTM(MINFO, "old_pkt_filter=0x%x, curr_pkt_filter=0x%x\n",
@@ -1601,6 +1593,10 @@ static mlan_status wlan_power_ioctl_set_power(pmlan_adapter pmadapter,
 				  *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
 		pg_tlv->type = TLV_TYPE_POWER_GROUP;
 		pg_tlv->length = 4 * sizeof(Power_Group_t);
+		/*Power Groups for VHTBW20, VHTBW40, VHTBW80 */
+		pg_tlv->length += 3 * sizeof(Power_Group_t);
+		/*Power Groups for HEBW20, HEBW40, HEBW80 */
+		pg_tlv->length += 3 * sizeof(Power_Group_t);
 		pg = (Power_Group_t *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) +
 				       sizeof(MrvlTypes_Power_Group_t));
 		/* Power group for modulation class HR/DSSS */
@@ -1626,7 +1622,7 @@ static mlan_status wlan_power_ioctl_set_power(pmlan_adapter pmadapter,
 		pg->power_step = 0;
 		pg->power_min = (t_s8)dbm;
 		pg->power_max = (t_s8)dbm;
-		pg->ht_bandwidth = HT_BW_20;
+		pg->ht_bandwidth = BW_20;
 		pg++;
 		/* Power group for modulation class HTBW40 */
 		pg->first_rate_code = 0x00;
@@ -1635,7 +1631,61 @@ static mlan_status wlan_power_ioctl_set_power(pmlan_adapter pmadapter,
 		pg->power_step = 0;
 		pg->power_min = (t_s8)dbm;
 		pg->power_max = (t_s8)dbm;
-		pg->ht_bandwidth = HT_BW_40;
+		pg->ht_bandwidth = BW_40;
+		pg++;
+		/* Power group for modulation class VHTBW20 */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x19;
+		pg->modulation_class = MOD_CLASS_VHT;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg->ht_bandwidth = BW_20;
+		pg++;
+		/* Power group for modulation class VHTBW40 */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x19;
+		pg->modulation_class = MOD_CLASS_VHT;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg->ht_bandwidth = BW_40;
+		pg++;
+		/* Power group for modulation class VHTBW80 */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x19;
+		pg->modulation_class = MOD_CLASS_VHT;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg->ht_bandwidth = BW_80;
+		pg++;
+		/* Power group for modulation class HEBW20 */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x1B;
+		pg->modulation_class = MOD_CLASS_HE;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg->ht_bandwidth = BW_20;
+		pg++;
+		/* Power group for modulation class HEBW40 */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x1B;
+		pg->modulation_class = MOD_CLASS_HE;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg->ht_bandwidth = BW_40;
+		pg++;
+		/* Power group for modulation class HEBW80 */
+		pg->first_rate_code = 0x00;
+		pg->last_rate_code = 0x1B;
+		pg->modulation_class = MOD_CLASS_HE;
+		pg->power_step = 0;
+		pg->power_min = (t_s8)dbm;
+		pg->power_max = (t_s8)dbm;
+		pg->ht_bandwidth = BW_80;
 	}
 
 	/* Send request to firmware */
@@ -2247,6 +2297,9 @@ static mlan_status wlan_pm_ioctl(pmlan_adapter pmadapter,
 	case MLAN_OID_PM_CFG_SLEEP_PD:
 		status = wlan_set_get_sleep_pd(pmadapter, pioctl_req);
 		break;
+	case MLAN_OID_PM_CFG_FW_WAKEUP_METHOD:
+		status = wlan_fw_wakeup_method(pmadapter, pioctl_req);
+		break;
 	case MLAN_OID_PM_CFG_SLEEP_PARAMS:
 		status = wlan_set_get_sleep_params(pmadapter, pioctl_req);
 		break;
@@ -2842,8 +2895,8 @@ static mlan_status wlan_sec_ioctl_set_wpa_key(pmlan_adapter pmadapter,
 	}
 
 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
-			       pioctl_req->action, 0, (t_void *)pioctl_req,
-			       &sec->param.encrypt_key);
+			       (t_u16)pioctl_req->action, 0,
+			       (t_void *)pioctl_req, &sec->param.encrypt_key);
 
 	if (ret == MLAN_STATUS_SUCCESS)
 		ret = MLAN_STATUS_PENDING;
@@ -4846,6 +4899,38 @@ static mlan_status wlan_misc_cloud_keep_alive_rx(pmlan_adapter pmadapter,
 	return ret;
 }
 
+/**
+ *  @brief configure auth,assoc timeout parameter
+ *
+ *  @param pmadapter   A pointer to mlan_adapter structure
+ *  @param pioctl_req  A pointer to ioctl request buffer
+ *
+ *  @return        MLAN_STATUS_PENDING --success, otherwise fail
+ */
+static mlan_status wlan_misc_auth_assoc_timeout_cfg(pmlan_adapter pmadapter,
+						    pmlan_ioctl_req pioctl_req)
+{
+	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
+	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	t_u16 cmd_action = 0;
+
+	ENTER();
+
+	if (pioctl_req->action == MLAN_ACT_SET)
+		cmd_action = HostCmd_ACT_GEN_SET;
+	else
+		cmd_action = HostCmd_ACT_GEN_GET;
+	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AUTH_ASSOC_TIMEOUT_CFG,
+			       cmd_action, 0, (t_void *)pioctl_req,
+			       &(pmisc->param.auth_assoc_cfg));
+	if (ret == MLAN_STATUS_SUCCESS)
+		ret = MLAN_STATUS_PENDING;
+
+	LEAVE();
+	return ret;
+}
+
 /**
  *  @brief Miscellaneous configuration handler
  *
@@ -5065,6 +5150,9 @@ static mlan_status wlan_misc_cfg_ioctl(pmlan_adapter pmadapter,
 		status =
 			wlan_misc_ioctl_cross_chip_synch(pmadapter, pioctl_req);
 		break;
+	case MLAN_OID_MISC_TSP_CFG:
+		status = wlan_misc_ioctl_tsp_config(pmadapter, pioctl_req);
+		break;
 	case MLAN_OID_MISC_ROAM_OFFLOAD:
 		status = wlan_misc_roam_offload(pmadapter, pioctl_req);
 		break;
@@ -5180,6 +5268,7 @@ static mlan_status wlan_misc_cfg_ioctl(pmlan_adapter pmadapter,
 	case MLAN_OID_MISC_RF_TEST_TX_FRAME:
 	case MLAN_OID_MISC_RF_TEST_HE_POWER:
 	case MLAN_OID_MISC_OTP_MAC_RD_WR:
+	case MLAN_OID_MISC_OTP_CAL_DATA_RD_WR:
 		status = wlan_misc_ioctl_rf_test_cfg(pmadapter, pioctl_req);
 		break;
 	case MLAN_OID_MISC_ARB_CONFIG:
@@ -5207,6 +5296,10 @@ static mlan_status wlan_misc_cfg_ioctl(pmlan_adapter pmadapter,
 	case MLAN_OID_MISC_EDMAC_CONFIG:
 		status = wlan_misc_ioctl_edmac_cfg(pmadapter, pioctl_req);
 		break;
+	case MLAN_OID_MISC_AUTH_ASSOC_TIMEOUT_CONFIG:
+		status =
+			wlan_misc_auth_assoc_timeout_cfg(pmadapter, pioctl_req);
+		break;
 	default:
 		if (pioctl_req)
 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
diff --git a/mlan/mlan_sta_rx.c b/mlan/mlan_sta_rx.c
index 3f4c147..7dd371b 100644
--- a/mlan/mlan_sta_rx.c
+++ b/mlan/mlan_sta_rx.c
@@ -39,58 +39,6 @@ Change log:
 		Local Variables
 ********************************************************/
 
-/** IPv4 ARP request header */
-typedef MLAN_PACK_START struct {
-	/** Hardware type */
-	t_u16 Htype;
-	/** Protocol type */
-	t_u16 Ptype;
-	/** Hardware address length */
-	t_u8 addr_len;
-	/** Protocol address length */
-	t_u8 proto_len;
-	/** Operation code */
-	t_u16 op_code;
-	/** Source mac address */
-	t_u8 src_mac[MLAN_MAC_ADDR_LENGTH];
-	/** Sender IP address */
-	t_u8 src_ip[4];
-	/** Destination mac address */
-	t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
-	/** Destination IP address */
-	t_u8 dst_ip[4];
-} MLAN_PACK_END IPv4_ARP_t;
-
-/** IPv6 Nadv packet header */
-typedef MLAN_PACK_START struct {
-	/** IP protocol version */
-	t_u8 version;
-	/** flow label */
-	t_u8 flow_lab[3];
-	/** Payload length */
-	t_u16 payload_len;
-	/** Next header type */
-	t_u8 next_hdr;
-	/** Hot limit */
-	t_u8 hop_limit;
-	/** Source address */
-	t_u8 src_addr[16];
-	/** Destination address */
-	t_u8 dst_addr[16];
-	/** ICMP type */
-	t_u8 icmp_type;
-	/** IPv6 Code */
-	t_u8 ipv6_code;
-	/** IPv6 Checksum */
-	t_u16 ipv6_checksum;
-	/** Flags */
-	t_u32 flags;
-	/** Target address */
-	t_u8 taget_addr[16];
-	/** Reserved */
-	t_u8 rev[8];
-} MLAN_PACK_END IPv6_Nadv_t;
-
 /********************************************************
 		Global functions
 ********************************************************/
@@ -122,8 +70,8 @@ static t_u8 discard_gratuitous_ARP_msg(RxPacketHdr_t *prx_pkt,
 		/* Graguitous ARP can be ARP request or ARP reply*/
 		if ((parp_hdr->op_code == mlan_htons(0x01)) ||
 		    (parp_hdr->op_code == mlan_htons(0x02)))
-			if (memcmp(pmadapter, parp_hdr->src_ip,
-				   parp_hdr->dst_ip, 4) == 0)
+			if (memcmp(pmadapter, parp_hdr->sender_ip,
+				   parp_hdr->target_ip, 4) == 0)
 				ret = MTRUE;
 	}
 
diff --git a/mlan/mlan_tlv_ids.h b/mlan/mlan_tlv_ids.h
index 625b980..462c128 100755
--- a/mlan/mlan_tlv_ids.h
+++ b/mlan/mlan_tlv_ids.h
@@ -3,7 +3,7 @@
  *  @brief This file contains TLV ID definitions.
  *
  *
- *  Copyright 2024 NXP
+ *  Copyright 2023-2024 NXP
  *
  *  This software file (the File) is distributed by NXP
  *  under the terms of the GNU General Public License Version 2, June 1991
@@ -499,5 +499,8 @@
 #define TLV_TYPE_PS_EXT_PARAM (PROPRIETARY_TLV_BASE_ID + 351) /* 0x025f */
 #define TLV_TYPE_MCLIENT_FW_CAPS (PROPRIETARY_TLV_BASE_ID + 352) /* 0x0260 */
 #define NXP_CSI_MONITOR_TLV_ID (PROPRIETARY_TLV_BASE_ID + 354) /* 0x0262 */
+#define TLV_TYPE_BOOT_TIME_CFG (PROPRIETARY_TLV_BASE_ID + 355) /* 0x0263 */
+
+#define VENDOR_IE_OUIS_TLV_ID (PROPRIETARY_TLV_BASE_ID + 357) /* 0x0265 */
 
 #endif /* !MLAN_TLV_IDS_H_ */
diff --git a/mlan/mlan_uap_cmdevent.c b/mlan/mlan_uap_cmdevent.c
index a1bbbcb..6c50db9 100644
--- a/mlan/mlan_uap_cmdevent.c
+++ b/mlan/mlan_uap_cmdevent.c
@@ -681,6 +681,28 @@ static void wlan_process_tx_pause_event(pmlan_private priv, pmlan_buffer pevent)
 	return;
 }
 
+/**
+ *  @brief This function will STA`s PS mode change event
+ *
+ *  @param priv    A pointer to mlan_private
+ *  @param pevent  A pointer to event buf
+ *
+ *  @return	       N/A
+ */
+static void wlan_process_sta_ps_change_event(pmlan_private priv,
+					     pmlan_buffer pevent)
+{
+	MrvlIEtypes_PsStaStatus_t *ps_status =
+		(void *)(pevent->pbuf + pevent->data_offset + sizeof(t_u32));
+
+	ENTER();
+
+	wlan_update_sta_ps_state(priv, ps_status->mac, ps_status->sleep);
+
+	LEAVE();
+	return;
+}
+
 /**
  *  @brief This function prepares command for config uap settings
  *
@@ -1541,6 +1563,7 @@ static mlan_status wlan_uap_cmd_sys_configure(pmlan_private pmpriv,
 	MrvlIEtypes_action_chan_switch_t *tlv_chan_switch = MNULL;
 	IEEEtypes_ChanSwitchAnn_t *csa_ie = MNULL;
 	IEEEtypes_ExtChanSwitchAnn_t *ecsa_ie = MNULL;
+	MrvlIEtypes_MultiAp_t *tlv_multi_ap = MNULL;
 
 	ENTER();
 
@@ -1992,6 +2015,19 @@ static mlan_status wlan_uap_cmd_sys_configure(pmlan_private pmpriv,
 				sizeof(HostCmd_DS_SYS_CONFIG) + S_DS_GEN +
 				sizeof(MrvlIEtypes_wacp_mode_t));
 		}
+		if (misc->sub_command == MLAN_OID_MISC_MULTI_AP_CFG) {
+			/** Add multi AP tlv here */
+			tlv_multi_ap =
+				(MrvlIEtypes_MultiAp_t *)sys_config->tlv_buffer;
+			tlv_multi_ap->header.type =
+				wlan_cpu_to_le16(TLV_TYPE_MULTI_AP);
+			tlv_multi_ap->header.len =
+				wlan_cpu_to_le16(sizeof(tlv_multi_ap->flag));
+			tlv_multi_ap->flag = misc->param.multi_ap_flag;
+			cmd->size = wlan_cpu_to_le16(
+				sizeof(HostCmd_DS_SYS_CONFIG) + S_DS_GEN +
+				sizeof(MrvlIEtypes_MultiAp_t));
+		}
 	}
 done:
 	LEAVE();
@@ -3332,6 +3368,8 @@ static mlan_status wlan_uap_ret_get_log(pmlan_private pmpriv,
 			wlan_le32_to_cpu(pget_log->gdma_abort_cnt);
 		pget_info->param.stats.g_reset_rx_mac_cnt =
 			wlan_le32_to_cpu(pget_log->g_reset_rx_mac_cnt);
+		pget_info->param.stats.SdmaStuckCnt =
+			wlan_le32_to_cpu(pget_log->SdmaStuckCnt);
 		// Ownership error counters
 		pget_info->param.stats.dwCtlErrCnt =
 			wlan_le32_to_cpu(pget_log->dwCtlErrCnt);
@@ -3997,6 +4035,8 @@ static void wlan_check_uap_capability(pmlan_private priv, pmlan_buffer pevent)
 				wmm_param_ie.vend_hdr.element_id = WMM_IE;
 				wlan_wmm_setup_queue_priorities(priv,
 								&wmm_param_ie);
+				wlan_wmm_contention_init(
+					priv, wmm_param_ie.ac_params);
 			}
 		}
 		if (tlv_type == TLV_TYPE_UAP_PKT_FWD_CTL) {
@@ -4452,7 +4492,7 @@ static mlan_status wlan_uap_cmd_add_station(pmlan_private pmpriv,
 	tlv_buf = bss->param.sta_info.tlv;
 	tlv = (MrvlIEtypesHeader_t *)tlv_buf;
 	if (bss->param.sta_info.sta_flags & STA_FLAG_WME) {
-		PRINTM(MCMND, "STA flags supports wmm \n");
+		PRINTM(MCMND, "ADD_STA flags supports wmm \n");
 		sta_ptr->is_wmm_enabled = MTRUE;
 	}
 	// append sta_flag_flags.
@@ -4474,11 +4514,11 @@ static mlan_status wlan_uap_cmd_add_station(pmlan_private pmpriv,
 				(MrvlIEtypes_RatesParamSet_t *)tlv);
 			break;
 		case QOS_INFO:
-			PRINTM(MCMND, "STA supports wmm\n");
+			PRINTM(MCMND, "ADD_STA supports wmm\n");
 			sta_ptr->is_wmm_enabled = MTRUE;
 			break;
 		case HT_CAPABILITY:
-			PRINTM(MCMND, "STA supports 11n\n");
+			PRINTM(MCMND, "ADD_STA supports 11n\n");
 			sta_ptr->is_11n_enabled = MTRUE;
 			phtcap = (MrvlIETypes_HTCap_t *)tlv;
 			if (sta_ptr->HTcap.ieee_hdr.element_id ==
@@ -4497,7 +4537,7 @@ static mlan_status wlan_uap_cmd_add_station(pmlan_private pmpriv,
 				sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K;
 			break;
 		case VHT_CAPABILITY:
-			PRINTM(MCMND, "STA supports 11ac\n");
+			PRINTM(MCMND, "ADD_STA supports 11ac\n");
 			sta_ptr->is_11ac_enabled = MTRUE;
 			pvhtcap = (MrvlIETypes_VHTCap_t *)tlv;
 			if (GET_VHTCAP_MAXMPDULEN(
@@ -4515,7 +4555,7 @@ static mlan_status wlan_uap_cmd_add_station(pmlan_private pmpriv,
 			pext_tlv = (MrvlIEtypes_Extension_t *)tlv;
 			if (pext_tlv->ext_id == HE_CAPABILITY) {
 				sta_ptr->is_11ax_enabled = MTRUE;
-				PRINTM(MCMND, "STA supports 11ax\n");
+				PRINTM(MCMND, "ADD_STA supports 11ax\n");
 			} else {
 				pext_tlv = MNULL;
 			}
@@ -4547,6 +4587,7 @@ static mlan_status wlan_uap_cmd_add_station(pmlan_private pmpriv,
 			memcpy_ext(pmadapter, pos,
 				   (t_u8 *)&sta_ptr->he_cap.ext_id, tlv->len,
 				   tlv->len);
+			pos += tlv->len;
 			travel_len += sizeof(MrvlIEtypesHeader_t) + tlv->len;
 			tlv->len = wlan_cpu_to_le16(tlv->len);
 		}
@@ -4560,6 +4601,19 @@ static mlan_status wlan_uap_cmd_add_station(pmlan_private pmpriv,
 		pos += sizeof(MrvlIEtypesHeader_t);
 		memcpy_ext(pmadapter, pos, (t_u8 *)&sta_ptr->multi_ap_ie.data,
 			   tlv->len, tlv->len);
+		pos += tlv->len;
+		travel_len += sizeof(MrvlIEtypesHeader_t) + tlv->len;
+		tlv->len = wlan_cpu_to_le16(tlv->len);
+	}
+
+	if (sta_ptr->vendor_oui_count) {
+		tlv = (MrvlIEtypesHeader_t *)pos;
+		tlv->type = wlan_cpu_to_le16(VENDOR_IE_OUIS_TLV_ID);
+		tlv->len = sta_ptr->vendor_oui_count * VENDOR_OUI_LEN;
+		pos += sizeof(MrvlIEtypesHeader_t);
+		memcpy_ext(pmadapter, pos, (t_u8 *)&sta_ptr->vendor_oui,
+			   tlv->len, tlv->len);
+		pos += tlv->len;
 		travel_len += sizeof(MrvlIEtypesHeader_t) + tlv->len;
 		tlv->len = wlan_cpu_to_le16(tlv->len);
 	}
@@ -4810,8 +4864,7 @@ mlan_status wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no,
 		if (pmpriv->adapter->hw_status == WlanHardwareStatusReset)
 			pmpriv->adapter->hw_status =
 				WlanHardwareStatusInitializing;
-		cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
-		cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
+		ret = wlan_cmd_func_init(pmpriv, cmd_ptr);
 		break;
 	case HostCmd_CMD_FUNC_SHUTDOWN:
 		pmpriv->adapter->hw_status = WlanHardwareStatusReset;
@@ -4866,6 +4919,10 @@ mlan_status wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no,
 	case HostCmd_CMD_HS_WAKEUP_REASON:
 		ret = wlan_cmd_hs_wakeup_reason(pmpriv, cmd_ptr, pdata_buf);
 		break;
+	case HostCmd_CMD_802_11_FW_WAKE_METHOD:
+		ret = wlan_cmd_802_11_fw_wakeup_method(
+			pmpriv, cmd_ptr, cmd_action, (t_u16 *)pdata_buf);
+		break;
 	case HostCmd_CMD_802_11_ROBUSTCOEX:
 		ret = wlan_cmd_robustcoex(pmpriv, cmd_ptr, cmd_action,
 					  (t_u16 *)pdata_buf);
@@ -5065,6 +5122,12 @@ mlan_status wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no,
 						 pdata_buf);
 		break;
 #endif
+#endif
+#if defined(PCIE)
+	case HostCmd_CMD_PCIE_ADMA_INIT:
+		ret = wlan_cmd_pcie_adma_init(pmpriv, cmd_ptr, cmd_action,
+					      pdata_buf);
+		break;
 #endif
 	case HostCmd_CMD_TX_RX_PKT_STATS:
 		ret = wlan_cmd_tx_rx_pkt_stats(pmpriv, cmd_ptr,
@@ -5171,6 +5234,10 @@ mlan_status wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no,
 		ret = wlan_cmd_cross_chip_synch(pmpriv, cmd_ptr, cmd_action,
 						pdata_buf);
 		break;
+	case HostCmd_CMD_TSP_CFG:
+		ret = wlan_cmd_tsp_config(pmpriv, cmd_ptr, cmd_action,
+					  pdata_buf);
+		break;
 	case HostCmd_CMD_DS_GET_SENSOR_TEMP:
 		wlan_cmd_get_sensor_temp(pmpriv, cmd_ptr, cmd_action);
 		break;
@@ -5189,6 +5256,17 @@ mlan_status wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no,
 	case HostCmd_CMD_CSI:
 		ret = wlan_cmd_csi(pmpriv, cmd_ptr, cmd_action, pdata_buf);
 		break;
+
+	case HostCmd_CMD_PEER_TX_RATE_QUERY:
+		ret = wlan_cmd_sta_tx_rate_req(pmpriv, cmd_ptr, cmd_action,
+					       pdata_buf);
+		break;
+
+	case HostCmd_CMD_MCLIENT_SCHEDULE_CFG:
+		ret = wlan_cmd_mclient_scheduling_cfg(pmpriv, cmd_ptr,
+						      cmd_action, pdata_buf);
+		break;
+
 	default:
 		PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no);
 		if (pioctl_req)
@@ -5343,6 +5421,9 @@ mlan_status wlan_ops_uap_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
 	case HostCmd_CMD_HS_WAKEUP_REASON:
 		ret = wlan_ret_hs_wakeup_reason(pmpriv, resp, pioctl_buf);
 		break;
+	case HostCmd_CMD_802_11_FW_WAKE_METHOD:
+		ret = wlan_ret_fw_wakeup_method(pmpriv, resp, pioctl_buf);
+		break;
 	case HostCmd_CMD_802_11_ROBUSTCOEX:
 		break;
 	case HostCmd_CMD_DMCS_CONFIG:
@@ -5523,6 +5604,12 @@ mlan_status wlan_ops_uap_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
 		PRINTM(MINFO, "PCIE host buffer configuration successful.\n");
 		break;
 #endif
+#endif
+#if defined(PCIE)
+	case HostCmd_CMD_PCIE_ADMA_INIT:
+		PRINTM(MINFO, "PCIE ADMA init successful.\n");
+		wlan_pcie_init_fw(pmpriv->adapter);
+		break;
 #endif
 	case HostCmd_CMD_TX_RX_PKT_STATS:
 		ret = wlan_ret_tx_rx_pkt_stats(pmpriv, resp, pioctl_buf);
@@ -5606,6 +5693,9 @@ mlan_status wlan_ops_uap_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
 	case HostCmd_CMD_CROSS_CHIP_SYNCH:
 		ret = wlan_ret_cross_chip_synch(pmpriv, resp, pioctl_buf);
 		break;
+	case HostCmd_CMD_TSP_CFG:
+		ret = wlan_ret_tsp_config(pmpriv, resp, pioctl_buf);
+		break;
 	case HostCmd_CMD_DS_GET_SENSOR_TEMP:
 		ret = wlan_ret_get_sensor_temp(pmpriv, resp, pioctl_buf);
 		break;
@@ -5629,6 +5719,14 @@ mlan_status wlan_ops_uap_process_cmdresp(t_void *priv, t_u16 cmdresp_no,
 			PRINTM(MCMND, "CSI DISABLE cmdresp\n");
 		}
 		break;
+
+	case HostCmd_CMD_PEER_TX_RATE_QUERY:
+		ret = wlan_ret_sta_tx_rate(pmpriv, resp, pioctl_buf);
+		break;
+
+	case HostCmd_CMD_MCLIENT_SCHEDULE_CFG:
+		break;
+
 	default:
 		PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n",
 		       resp->command);
@@ -6111,6 +6209,14 @@ mlan_status wlan_ops_uap_process_event(t_void *priv)
 		pevent->event_id = 0; /* clear to avoid resending at end of fcn
 				       */
 		break;
+
+	case EVENT_CHAN_SWITCH_TO_6G_BLOCK:
+		reason_code = wlan_le16_to_cpu(*(t_u16 *)(pmbuf->pbuf +
+							  pmbuf->data_offset +
+							  sizeof(eventcause)));
+		print_chan_switch_block_event(reason_code);
+		break;
+
 	case EVENT_TX_STATUS_REPORT:
 		PRINTM(MINFO, "EVENT: TX_STATUS\n");
 		pevent->event_id = MLAN_EVENT_ID_FW_TX_STATUS;
@@ -6212,6 +6318,10 @@ mlan_status wlan_ops_uap_process_event(t_void *priv)
 		break;
 #endif
 
+	case EVENT_PEER_PS_MODE_CHANGE:
+		wlan_process_sta_ps_change_event(priv, pmbuf);
+		break;
+
 	default:
 		pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
 		break;
diff --git a/mlan/mlan_uap_ioctl.c b/mlan/mlan_uap_ioctl.c
index 2a58f0c..4c06612 100644
--- a/mlan/mlan_uap_ioctl.c
+++ b/mlan/mlan_uap_ioctl.c
@@ -337,7 +337,10 @@ static mlan_status wlan_uap_bss_ioctl_reset(pmlan_adapter pmadapter,
 	 */
 	for (i = 0; i < pmadapter->max_mgmt_ie_index; i++)
 		memset(pmadapter, &pmpriv->mgmt_ie[i], 0, sizeof(custom_ie));
-	pmpriv->add_ba_param.timeout = MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
+
+	pmpriv->add_ba_param.timeout = pmadapter->tx_ba_timeout_support ?
+					       MLAN_DEFAULT_BLOCK_ACK_TIMEOUT :
+					       0;
 	pmpriv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE;
 	pmpriv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE;
 	pmpriv->user_rxwinsize = pmpriv->add_ba_param.rx_win_size;
@@ -2247,6 +2250,10 @@ mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
 			status = wlan_misc_ioctl_cross_chip_synch(pmadapter,
 								  pioctl_req);
 		}
+		if (misc->sub_command == MLAN_OID_MISC_TSP_CFG) {
+			status = wlan_misc_ioctl_tsp_config(pmadapter,
+							    pioctl_req);
+		}
 		if (misc->sub_command == MLAN_OID_MISC_GET_CHAN_REGION_CFG)
 			status = wlan_misc_chan_reg_cfg(pmadapter, pioctl_req);
 		if (misc->sub_command == MLAN_OID_MISC_OPER_CLASS_CHECK)
@@ -2375,6 +2382,8 @@ mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
 			status = wlan_config_mgmt_filter(pmadapter, pioctl_req);
 		if (pm->sub_command == MLAN_OID_PM_INFO)
 			status = wlan_get_pm_info(pmadapter, pioctl_req);
+		if (pm->sub_command == MLAN_OID_PM_CFG_FW_WAKEUP_METHOD)
+			status = wlan_fw_wakeup_method(pmadapter, pioctl_req);
 		break;
 	case MLAN_IOCTL_SNMP_MIB:
 		snmp = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
diff --git a/mlan/mlan_usb.c b/mlan/mlan_usb.c
index 9624fa1..6f62ea9 100644
--- a/mlan/mlan_usb.c
+++ b/mlan/mlan_usb.c
@@ -69,10 +69,10 @@ static const struct _mlan_card_info mlan_card_info_usb8997 = {
 
 #ifdef USB8978
 static const struct _mlan_card_info mlan_card_info_usb8978 = {
-	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
+	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K,
 	.v16_fw_api = 1,
 	.supp_ps_handshake = 1,
-	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_2X2,
+	.default_11n_tx_bf_cap = DEFAULT_11N_TX_BF_CAP_1X1,
 	.support_11mc = 1,
 };
 #endif
@@ -110,8 +110,8 @@ static const struct _mlan_card_info mlan_card_info_usbIW624 = {
 };
 #endif
 
-#ifdef USBIW615
-static const struct _mlan_card_info mlan_card_info_usbIW615 = {
+#ifdef USBIW610
+static const struct _mlan_card_info mlan_card_info_usbIW610 = {
 	.max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K,
 	.v16_fw_api = 1,
 	.v17_fw_api = 1,
@@ -228,6 +228,10 @@ static mlan_status wlan_usb_prog_fw_w_helper(pmlan_adapter pmadapter,
 #if defined(USB9098)
 	t_u32 revision_id = 0;
 #endif
+	t_u32 i = 0;
+	t_u32 fw_data_param = pmadapter->init_para.fw_data_cfg;
+	fw_data_t fw_data_list[MAX_FW_DATA_BLOCK] = {0};
+	t_u32 fw_data_param_num = 0, fw_data_index = 0;
 
 	ENTER();
 
@@ -269,6 +273,16 @@ static mlan_status wlan_usb_prog_fw_w_helper(pmlan_adapter pmadapter,
 			check_fw_status = MTRUE;
 	}
 #endif
+
+	if (fw_data_param) {
+		fw_data_param_num =
+			MIN(MAX_FW_DATA_BLOCK, bitcount(fw_data_param));
+		/** Get the custom Fw data */
+		if (MLAN_STATUS_SUCCESS !=
+		    wlan_get_custom_fw_data(pmadapter, (t_u8 *)fw_data_list))
+			goto cleanup;
+	}
+
 #if defined(USB9097)
 	if (IS_USB9097(pmadapter->card_type))
 		check_fw_status = MTRUE;
@@ -435,6 +449,25 @@ static mlan_status wlan_usb_prog_fw_w_helper(pmlan_adapter pmadapter,
 		FWSeqNum++;
 		PRINTM(MINFO, ".\n");
 
+		if (fw_data_param) {
+			for (i = fw_data_index; i < fw_data_param_num;) {
+				firmware = fw_data_list[i].fw_data_buffer;
+				/** make TotalBytes as 0 as allocated custom Fw
+				 * data buffers are not contiguous */
+				TotalBytes = 0;
+				fw_data_index++;
+				break;
+			}
+			/** custom Fw data download complete, restore Fw */
+			if (i >= fw_data_param_num) {
+				firmware = pmfw->pfw_buf;
+				fw_data_param = 0;
+				fw_data_index = 0;
+				FWSeqNum = 0;
+				TotalBytes = 0;
+			}
+		}
+
 		/* Add FW ending check for secure download */
 		if (((DnldCmd == FW_CMD_21) && (DataLength == 0)) ||
 		    (TotalBytes >= pmfw->fw_len))
@@ -828,9 +861,9 @@ mlan_status wlan_get_usb_device(pmlan_adapter pmadapter)
 		pmadapter->pcard_info = &mlan_card_info_usbIW624;
 		break;
 #endif
-#ifdef USBIW615
-	case CARD_TYPE_USBIW615:
-		pmadapter->pcard_info = &mlan_card_info_usbIW615;
+#ifdef USBIW610
+	case CARD_TYPE_USBIW610:
+		pmadapter->pcard_info = &mlan_card_info_usbIW610;
 		break;
 #endif
 	default:
@@ -1328,7 +1361,7 @@ static mlan_status wlan_usb_host_to_card(pmlan_private pmpriv, t_u8 type,
 	}
 	if (type == MLAN_TYPE_CMD
 #if defined(USB9098) || defined(USB9097) || defined(USBIW624) ||               \
-	defined(USB8997) || defined(USB8978)
+	defined(USB8997) || defined(USB8978) || defined(USBIW610)
 	    || type == MLAN_TYPE_VDLL
 #endif
 	) {
@@ -1389,9 +1422,13 @@ static mlan_status wlan_usb_evt_complete(pmlan_adapter pmadapter,
 					 mlan_buffer *pmbuf, mlan_status status)
 {
 	ENTER();
-	pmadapter->event_received = MFALSE;
+
+	wlan_request_event_lock(pmadapter);
+	if (pmadapter->event_received)
+		pmadapter->event_received = MFALSE;
 	pmadapter->event_cause = 0;
 	pmadapter->pmlan_buffer_event = MNULL;
+	wlan_release_event_lock(pmadapter);
 	pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
 						pmadapter->rx_cmd_ep, status);
 
diff --git a/mlan/mlan_util.h b/mlan/mlan_util.h
index 2efa6f4..f3ef222 100644
--- a/mlan/mlan_util.h
+++ b/mlan/mlan_util.h
@@ -68,6 +68,19 @@ static INLINE t_void util_init_list(pmlan_linked_list phead)
 	phead->pprev = phead->pnext = (pmlan_linked_list)phead;
 }
 
+/**
+ *  @brief This function initializes a list head without locking
+ *
+ *  @param phead		List head
+ *
+ *  @return			N/A
+ */
+static INLINE t_void util_list_head_reset(pmlan_list_head phead)
+{
+	/* Both next and prev point to self */
+	phead->pprev = phead->pnext = (pmlan_linked_list)phead;
+}
+
 /**
  *  @brief This function initializes a list
  *
@@ -106,6 +119,24 @@ static INLINE t_void util_free_list_head(
 		moal_free_lock(pmoal_handle, phead->plock);
 }
 
+/**
+ *  @brief This function peeks into a list without lock
+ *
+ *  @param phead		List head
+ *
+ *  @return			List node
+ */
+static INLINE pmlan_linked_list util_peek_list_nl(t_void *pmoal_handle,
+						  pmlan_list_head phead)
+{
+	pmlan_linked_list pnode = MNULL;
+
+	if (phead->pnext != (pmlan_linked_list)phead)
+		pnode = phead->pnext;
+
+	return pnode;
+}
+
 /**
  *  @brief This function peeks into a list
  *
@@ -124,13 +155,33 @@ util_peek_list(t_void *pmoal_handle, pmlan_list_head phead,
 
 	if (moal_spin_lock)
 		moal_spin_lock(pmoal_handle, phead->plock);
-	if (phead->pnext != (pmlan_linked_list)phead)
-		pnode = phead->pnext;
+
+	pnode = util_peek_list_nl(pmoal_handle, phead);
+
 	if (moal_spin_unlock)
 		moal_spin_unlock(pmoal_handle, phead->plock);
 	return pnode;
 }
 
+/**
+ *  @brief This function queues a node at the list tail without taking any lock
+ *
+ *  @param phead		List head
+ *  @param pnode		List node to queue
+ *
+ *  @return			N/A
+ */
+static INLINE t_void util_enqueue_list_tail_nl(t_void *pmoal_handle,
+					       pmlan_list_head phead,
+					       pmlan_linked_list pnode)
+{
+	pmlan_linked_list pold_last = phead->pprev;
+	pnode->pprev = pold_last;
+	pnode->pnext = (pmlan_linked_list)phead;
+
+	phead->pprev = pold_last->pnext = pnode;
+}
+
 /**
  *  @brief This function queues a node at the list tail
  *
@@ -146,15 +197,11 @@ static INLINE t_void util_enqueue_list_tail(
 	mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
 	mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
 {
-	pmlan_linked_list pold_last;
-
 	if (moal_spin_lock)
 		moal_spin_lock(pmoal_handle, phead->plock);
-	pold_last = phead->pprev;
-	pnode->pprev = pold_last;
-	pnode->pnext = (pmlan_linked_list)phead;
 
-	phead->pprev = pold_last->pnext = pnode;
+	util_enqueue_list_tail_nl(pmoal_handle, phead, pnode);
+
 	if (moal_spin_unlock)
 		moal_spin_unlock(pmoal_handle, phead->plock);
 }
@@ -187,6 +234,89 @@ static INLINE t_void util_enqueue_list_head(
 		moal_spin_unlock(pmoal_handle, phead->plock);
 }
 
+/**
+ *  @brief This function checks if the node points to itself
+ *
+ *  @param pnode		List node to check
+ *
+ *  @return			MTRUE if node points to itself only
+ */
+static INLINE t_bool util_is_node_itself(pmlan_linked_list pnode)
+{
+	return pnode->pprev == pnode && pnode->pnext == pnode;
+}
+
+/**
+ *  @brief This function checks if the node in some list
+ *
+ *  @param pnode		List node to check
+ *
+ *  @return			MTRUE if node is enqueued into some list
+ */
+static INLINE t_bool util_is_node_in_list(pmlan_linked_list pnode)
+{
+	return pnode->pprev && pnode->pnext && !util_is_node_itself(pnode);
+}
+
+/**
+ *  @brief This function checks if the pnode is valid node of list
+ *
+ *  @param phead		List`s head
+ *  @param pnode		List node to check
+ *
+ *  @return			MTRUE if node is enqueued into some list
+ */
+static INLINE t_bool util_is_list_node(pmlan_list_head phead,
+				       pmlan_linked_list pnode)
+{
+	return pnode && (pmlan_linked_list)phead != pnode;
+}
+
+/**
+ *  @brief This function removes a node from the list if the node was in the
+ * list
+ *
+ *  @param pnode		List node to remove
+ *
+ *  @return			N/A
+ */
+static INLINE t_void util_unlink_list_safe_nl(t_void *pmoal_handle,
+					      pmlan_linked_list pnode)
+{
+	if (util_is_node_in_list(pnode)) {
+		pmlan_linked_list pmy_prev;
+		pmlan_linked_list pmy_next;
+
+		pmy_prev = pnode->pprev;
+		pmy_next = pnode->pnext;
+		pmy_next->pprev = pmy_prev;
+		pmy_prev->pnext = pmy_next;
+
+		pnode->pnext = pnode->pprev = MNULL;
+	}
+}
+
+/**
+ *  @brief This function removes a node from the list
+ *
+ *  @param pnode		List node to remove
+ *
+ *  @return			N/A
+ */
+static INLINE t_void util_unlink_list_nl(t_void *pmoal_handle,
+					 pmlan_linked_list pnode)
+{
+	pmlan_linked_list pmy_prev;
+	pmlan_linked_list pmy_next;
+
+	pmy_prev = pnode->pprev;
+	pmy_next = pnode->pnext;
+	pmy_next->pprev = pmy_prev;
+	pmy_prev->pnext = pmy_next;
+
+	pnode->pnext = pnode->pprev = MNULL;
+}
+
 /**
  *  @brief This function removes a node from the list
  *
@@ -202,17 +332,11 @@ static INLINE t_void util_unlink_list(
 	mlan_status (*moal_spin_lock)(t_void *handle, t_void *plock),
 	mlan_status (*moal_spin_unlock)(t_void *handle, t_void *plock))
 {
-	pmlan_linked_list pmy_prev;
-	pmlan_linked_list pmy_next;
-
 	if (moal_spin_lock)
 		moal_spin_lock(pmoal_handle, phead->plock);
-	pmy_prev = pnode->pprev;
-	pmy_next = pnode->pnext;
-	pmy_next->pprev = pmy_prev;
-	pmy_prev->pnext = pmy_next;
 
-	pnode->pnext = pnode->pprev = MNULL;
+	util_unlink_list_nl(pmoal_handle, pnode);
+
 	if (moal_spin_unlock)
 		moal_spin_unlock(pmoal_handle, phead->plock);
 }
@@ -515,4 +639,26 @@ reflective_enum_lookup_name(const struct reflective_enum_element *elements,
 	return elem->name;
 }
 
+#define util_offsetof(struct_type, member_name)                                \
+	((t_ptr) & ((struct_type *)0)->member_name)
+
+#define util_container_of(ptr, struct_type, member_name)                       \
+	((struct_type *)((t_u8 *)(ptr)-util_offsetof(struct_type, member_name)))
+
+/**
+ *  @brief This function checks if t1 timestamp is before t2 timestamp
+ *
+ *  @param t1   t1 timestamp
+ *  @param t2   t2 timestamp
+ *
+ *  @return     MTRUE if t1 is before t2
+ */
+static INLINE t_bool util_is_time_before(t_u64 t1, t_u64 t2)
+{
+	t_s64 delta = t2 - t1;
+
+	// coverity[integer_overflow:SUPPRESS]
+	return delta > 0;
+}
+
 #endif /* !_MLAN_UTIL_H_ */
diff --git a/mlan/mlan_wmm.c b/mlan/mlan_wmm.c
index 06fc26b..ecde7e6 100644
--- a/mlan/mlan_wmm.c
+++ b/mlan/mlan_wmm.c
@@ -65,6 +65,10 @@ typedef MLAN_PACK_START enum _wmm_ac_e {
  */
 static const t_u8 wmm_aci_to_qidx_map[] = {WMM_AC_BE, WMM_AC_BK, WMM_AC_VI,
 					   WMM_AC_VO};
+
+/** AC to ACI mapping as per IEEE802.11 spec */
+static const t_u8 wmm_ac_to_aci_map[] = {AC_BK, AC_BE, AC_VI, AC_VO};
+
 /**
  * This table will be used to store the tid values based on ACs.
  * It is initialized to default values per TID.
@@ -448,6 +452,38 @@ static void wlan_wmm_cleanup_queues(pmlan_private priv)
 	LEAVE();
 }
 
+/**
+ *  @brief Delete all wmm_sta_table
+ *
+ *  @param priv     Pointer to the mlan_private driver data struct
+ *
+ *  @return         N/A
+ */
+static void wlan_wmm_delete_all_sta_entries(pmlan_private priv)
+{
+	pmlan_adapter pmadapter = priv->adapter;
+	t_void *const pmoal_handle = pmadapter->pmoal_handle;
+	mlan_linked_list *sta_entry;
+
+	while ((sta_entry =
+			util_peek_list_nl(pmoal_handle, &priv->wmm.all_stas))) {
+		struct wmm_sta_table *sta = util_container_of(
+			sta_entry, struct wmm_sta_table, all_stas_entry);
+
+		util_unlink_list_nl(pmoal_handle, &sta->all_stas_entry);
+		util_unlink_list_safe_nl(pmoal_handle,
+					 &sta->pending_stas_entry);
+		util_unlink_list_safe_nl(pmoal_handle, &sta->active_sta_entry);
+
+		pmadapter->callbacks.moal_mfree(pmoal_handle, (t_u8 *)sta);
+	}
+
+	util_list_head_reset(&priv->wmm.all_stas);
+
+	priv->wmm.selected_ra_list = MNULL;
+	pmadapter->ra_list_tracing.ra_list = MNULL;
+}
+
 /**
  *  @brief Delete all route address from RA list
  *
@@ -460,26 +496,30 @@ static void wlan_wmm_delete_all_ralist(pmlan_private priv)
 	raListTbl *ra_list;
 	int i;
 	pmlan_adapter pmadapter = priv->adapter;
+	t_void *const pmoal_handle = pmadapter->pmoal_handle;
 
 	ENTER();
 
 	for (i = 0; i < MAX_NUM_TID; ++i) {
 		PRINTM(MINFO, "RAList: Freeing buffers for TID %d\n", i);
 		while ((ra_list = (raListTbl *)util_peek_list(
-				pmadapter->pmoal_handle,
-				&priv->wmm.tid_tbl_ptr[i].ra_list, MNULL,
-				MNULL))) {
-			util_unlink_list(pmadapter->pmoal_handle,
+				pmoal_handle, &priv->wmm.tid_tbl_ptr[i].ra_list,
+				MNULL, MNULL))) {
+			util_unlink_list(pmoal_handle,
 					 &priv->wmm.tid_tbl_ptr[i].ra_list,
 					 (pmlan_linked_list)ra_list, MNULL,
 					 MNULL);
 
-			pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
+			if (util_is_node_in_list(&ra_list->pending_txq_entry))
+				util_unlink_list_nl(
+					pmoal_handle,
+					&ra_list->pending_txq_entry);
+
+			pmadapter->callbacks.moal_mfree(pmoal_handle,
 							(t_u8 *)ra_list);
 		}
 
-		util_init_list(
-			(pmlan_linked_list)&priv->wmm.tid_tbl_ptr[i].ra_list);
+		util_list_head_reset(&priv->wmm.tid_tbl_ptr[i].ra_list);
 		priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
 	}
 
@@ -792,6 +832,707 @@ static raListTbl *wlan_wmm_get_highest_priolist_ptr(pmlan_adapter pmadapter,
 	return MNULL;
 }
 
+/**
+ *  @brief Calculates byte budget based on time budget and currect PHY rate
+ *
+ *  @param time_budget_us   Time budget in usec
+ *  @param phy_rate_kbps    TX PHY rate in kbit/sec
+ *
+ *  @return                 byte budget
+ */
+static t_u32 wlan_wmm_get_byte_budget(t_u32 time_budget_us, t_u32 phy_rate_kbps)
+{
+	const t_u32 min_budget = MV_ETH_FRAME_LEN;
+	t_u64 byte_budget =
+		((t_u64)phy_rate_kbps * time_budget_us) / (8 * 1000u);
+
+	if (byte_budget > INT_MAX)
+		return INT_MAX;
+
+	if (byte_budget < min_budget)
+		return min_budget;
+
+	return byte_budget;
+}
+
+/**
+ *  @brief Allocate sta_table address
+ *
+ *  @param pmadapter       Pointer to the mlan_adapter structure
+ *  @param ra              Pointer to the route address
+ *
+ *  @return         sta_table
+ */
+static struct wmm_sta_table *
+wlan_wmm_allocate_sta_table(pmlan_adapter pmadapter, t_u8 *ra)
+{
+	struct wmm_sta_table *sta_table = MNULL;
+	int i;
+	const t_u32 default_rate = 200 * 1000;
+	const t_u32 default_queue_packets = 1024;
+
+	ENTER();
+
+	if (!pmadapter->mclient_tx_supported)
+		goto done;
+
+	if (pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle,
+					     sizeof(*sta_table), MLAN_MEM_DEF,
+					     (t_u8 **)&sta_table)) {
+		PRINTM(MERROR, "Fail to allocate sta_table\n");
+		goto done;
+	}
+
+	util_init_list(&sta_table->all_stas_entry);
+	util_init_list(&sta_table->pending_stas_entry);
+	util_init_list(&sta_table->active_sta_entry);
+	memcpy_ext(pmadapter, sta_table->ra, ra, MLAN_MAC_ADDR_LENGTH,
+		   MLAN_MAC_ADDR_LENGTH);
+
+	sta_table->budget.time_budget_init_us = pmadapter->init_para.tx_budget;
+	sta_table->budget.byte_budget_init = wlan_wmm_get_byte_budget(
+		sta_table->budget.time_budget_init_us, default_rate);
+	sta_table->budget.queue_packets = default_queue_packets;
+	sta_table->budget.phy_rate_kbps = default_rate;
+
+	sta_table->budget.mpdu_with_amsdu_pps_cap =
+		pmadapter->tx_mpdu_with_amsdu_pps;
+	sta_table->budget.mpdu_no_amsdu_pps_cap =
+		pmadapter->tx_mpdu_no_amsdu_pps;
+
+	sta_table->budget.mpdu_with_amsdu_budget_init =
+		((t_u64)sta_table->budget.mpdu_with_amsdu_pps_cap *
+		 sta_table->budget.time_budget_init_us) /
+		1000000;
+	sta_table->budget.mpdu_no_amsdu_budget_init =
+		((t_u64)sta_table->budget.mpdu_no_amsdu_pps_cap *
+		 sta_table->budget.time_budget_init_us) /
+		1000000;
+
+	for (i = 0; i < NELEMENTS(sta_table->budget.bytes); ++i) {
+		sta_table->budget.bytes[i] = sta_table->budget.byte_budget_init;
+		sta_table->budget.mpdus[i] =
+			sta_table->budget.mpdu_with_amsdu_budget_init;
+	}
+
+done:
+	LEAVE();
+
+	return sta_table;
+}
+
+/**
+ *  @brief Generates pseudorandom number
+ *
+ *  @return         random number
+ */
+static t_u32 wmm_get_random_num(void)
+{
+	static t_u32 state = 2463534242u;
+
+	state ^= state << 13;
+	state ^= state >> 17;
+	state ^= state << 5;
+
+	return state;
+}
+
+/**
+ *  @brief reset remaning AIFS to default value
+ *
+ *  @param txq_cont   Pointer to mlan_wmm_contention structure
+ *
+ *  @return           N/A
+ */
+static void wlan_wmm_txq_contention_reset_aifs(mlan_wmm_contention *txq_cont)
+{
+	txq_cont->remaining_aifs = txq_cont->param.aifsn * 9 + 16;
+}
+
+/**
+ *  @brief reset remaning backoff to default value
+ *
+ *  @param txq_cont   Pointer to mlan_wmm_contention structure
+ *
+ *  @return           N/A
+ */
+static void wlan_wmm_txq_contention_reset_backoff(mlan_wmm_contention *txq_cont)
+{
+	const t_u32 mask = (1u << txq_cont->ecw) - 1;
+	txq_cont->remaining_backoff = (wmm_get_random_num() & mask) * 9;
+}
+
+/**
+ *  @brief get remaning time till contention end in usec
+ *
+ *  @param txq_cont   Pointer to mlan_wmm_contention structure
+ *
+ *  @return           remaning time
+ */
+static t_u32 wlan_wmm_txq_get_remaining_time(mlan_wmm_contention *txq_cont)
+{
+	return txq_cont->remaining_aifs + txq_cont->remaining_backoff;
+}
+
+/**
+ *  @brief decrement contention timer by specified duration
+ *
+ *  @param txq_cont   Pointer to mlan_wmm_contention structure
+ *  @param duration   duration in usec
+ *
+ *  @return           MTRUE if timer reach 0
+ */
+static t_bool wlan_wmm_txq_count_donw(mlan_wmm_contention *txq_cont,
+				      t_u32 duration)
+{
+	if (txq_cont->remaining_aifs > 0) {
+		t_u32 del = MIN(txq_cont->remaining_aifs, duration);
+
+		txq_cont->remaining_aifs -= del;
+		duration -= del;
+	}
+
+	if (txq_cont->remaining_aifs == 0)
+		txq_cont->remaining_backoff -= duration;
+
+	// coverity[integer_overflow:SUPPRESS]
+	return txq_cont->remaining_backoff == 0 &&
+	       txq_cont->remaining_aifs == 0;
+}
+
+/**
+ *  @brief This function is called when txq_cont win contention
+ *
+ *  @param txq_cont   Pointer to mlan_wmm_contention structure
+ *
+ *  @return           N/A
+ */
+static void wlan_wmm_txq_win(mlan_wmm_contention *txq_cont)
+{
+	txq_cont->ecw = txq_cont->param.ecwmin;
+	wlan_wmm_txq_contention_reset_aifs(txq_cont);
+	wlan_wmm_txq_contention_reset_backoff(txq_cont);
+}
+
+/**
+ *  @brief This function is called when txq_cont lost contention
+ *
+ *  @param txq_cont   Pointer to mlan_wmm_contention structure
+ *
+ *  @return           N/A
+ */
+static void wlan_wmm_txq_lost(mlan_wmm_contention *txq_cont)
+{
+	wlan_wmm_txq_contention_reset_aifs(txq_cont);
+	if (txq_cont->move_cw_on_lost) {
+		txq_cont->ecw = MIN(txq_cont->ecw + 1, txq_cont->param.ecwmax);
+		wlan_wmm_txq_contention_reset_backoff(txq_cont);
+	}
+}
+
+/**
+ *  @brief This function is called when collision detected
+ *
+ *  @param txq_cont   Pointer to mlan_wmm_contention structure
+ *
+ *  @return           N/A
+ */
+static void wlan_wmm_txq_collision(mlan_wmm_contention *txq_cont)
+{
+	txq_cont->ecw = MIN(txq_cont->ecw + 1, txq_cont->param.ecwmax);
+	wlan_wmm_txq_contention_reset_aifs(txq_cont);
+	wlan_wmm_txq_contention_reset_backoff(txq_cont);
+}
+
+/**
+ *  @brief Setup contention parameters based on WMM structure
+ *
+ *  @param txq_cont   Pointer to mlan_wmm_contention structure
+ *  @param wmm_param   Pointer to IEEEtypes_WmmAcParameters_t structure
+ *  @param move_cw_on_lost   tells if CW should be doubled in case of lose
+ *                             in contention
+ *
+ *  @return           N/A
+ */
+static void
+wlan_wmm_txq_contention_setup(mlan_wmm_contention *txq_cont,
+			      t_bool move_cw_on_lost,
+			      const IEEEtypes_WmmAcParameters_t *wmm_param)
+{
+	txq_cont->param.aifsn = wmm_param->aci_aifsn.aifsn;
+	txq_cont->param.ecwmin = wmm_param->ecw.ecw_min;
+	txq_cont->param.ecwmax = wmm_param->ecw.ecw_max;
+	txq_cont->ecw = txq_cont->param.ecwmin;
+	txq_cont->move_cw_on_lost = move_cw_on_lost;
+	wlan_wmm_txq_contention_reset_aifs(txq_cont);
+	wlan_wmm_txq_contention_reset_backoff(txq_cont);
+}
+
+/**
+ *  @brief Get WMM contention winner
+ *
+ *  @param pmadapter   Pointer to pmlan_adapter structure
+ *  @param mlan        Pointer to mlan_private structure
+ *
+ *  @return           TX queue index, -1 if no pending data
+ */
+static int wlan_wmm_contention_get_winner(pmlan_adapter pmadapter,
+					  mlan_private *mlan)
+{
+	int queue;
+	t_u32 active_queues = 0;
+	t_u32 remaining_time = INT_MAX;
+	t_bool has_winner = MFALSE;
+	int winner_queue = -1;
+
+	for (queue = 0; queue < NELEMENTS(mlan->wmm.pending_txq); ++queue) {
+		pmlan_linked_list entry = util_peek_list_nl(
+			pmadapter->pmoal_handle, &mlan->wmm.pending_txq[queue]);
+
+		if (entry) {
+			t_u32 q_remaining_time =
+				wlan_wmm_txq_get_remaining_time(
+					&mlan->wmm.txq_contention[queue]);
+			remaining_time = MIN(remaining_time, q_remaining_time);
+			active_queues |= MBIT(queue);
+		}
+	}
+
+	for (queue = 0; queue < NELEMENTS(mlan->wmm.pending_txq); ++queue) {
+		if (active_queues & MBIT(queue)) {
+			mlan_wmm_contention *txq_cont =
+				&mlan->wmm.txq_contention[queue];
+			t_bool winner = wlan_wmm_txq_count_donw(txq_cont,
+								remaining_time);
+
+			if (winner && !has_winner) {
+				has_winner = MTRUE;
+				winner_queue = queue;
+				wlan_wmm_txq_win(txq_cont);
+			} else if (winner && has_winner) {
+				wlan_wmm_txq_collision(txq_cont);
+			} else {
+				wlan_wmm_txq_lost(txq_cont);
+			}
+		}
+	}
+
+	return winner_queue;
+}
+
+/**
+ *  @brief Initi contention parameters
+ *
+ *  @param mlan        Pointer to mlan_private structure
+ *  @param ac_params   Pointer to IEEEtypes_WmmAcParameters_t array
+ *
+ *  @return           N/A
+ */
+void wlan_wmm_contention_init(
+	mlan_private *mlan,
+	const IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES])
+{
+	int queue;
+
+	if (ac_params == MNULL)
+		return;
+
+	for (queue = 0; queue < NELEMENTS(mlan->wmm.queue_priority); ++queue) {
+		const mlan_wmm_ac_e ac = mlan->wmm.queue_priority[queue];
+		const wmm_ac_e aci = wmm_ac_to_aci_map[ac];
+		/* adjust BK`s contention logic to mimic legacy behaviour */
+		const t_bool move_cw_on_lost = aci == AC_BK;
+
+		wlan_wmm_txq_contention_setup(&mlan->wmm.txq_contention[queue],
+					      move_cw_on_lost, &ac_params[aci]);
+	}
+}
+
+/**
+ *  @brief get AC queue index for transmission
+ *
+ *  @param pmadapter   Pointer to pmlan_adapter structure
+ *  @param mlan        Pointer to mlan_private structure
+ *
+ *  @return           AC queue index to TX
+ */
+static int wlan_wmm_get_next_ac(pmlan_adapter pmadapter, mlan_private *mlan)
+{
+	return wlan_wmm_contention_get_winner(pmadapter, mlan);
+}
+
+/**
+ *  @brief checks if BSS is ready for TX
+ *
+ *  @param pmadapter   Pointer to pmlan_adapter structure
+ *  @param mlan        Pointer to mlan_private structure
+ *
+ *  @return           MTRUE when BSS is reasy for TX
+ */
+static t_bool wlan_wmm_is_bss_ready_for_tx(pmlan_adapter pmadapter,
+					   mlan_private *mlan)
+{
+	if ((mlan->port_ctrl_mode == MTRUE) && (mlan->port_open == MFALSE)) {
+		PRINTM(MINFO, "PORT_CLOSED Ignore pkts from BSS%d\n",
+		       mlan->bss_index);
+		return MFALSE;
+	}
+
+	if (mlan->tx_pause) {
+		PRINTM(MINFO, "TX PASUE Ignore pkts from BSS%d\n",
+		       mlan->bss_index);
+		return MFALSE;
+	}
+#if defined(USB)
+	if (!wlan_is_port_ready(pmadapter, mlan->port_index)) {
+		PRINTM(MINFO, "usb port is busy,Ignore pkts from BSS%d\n",
+		       mlan->bss_index);
+		return MFALSE;
+	}
+#endif
+
+	return MTRUE;
+}
+
+static mlan_private *wlan_wmm_get_next_mlan(pmlan_adapter pmadapter,
+					    mlan_bssprio_tbl *bssprio_tbl)
+{
+	mlan_bssprio_node *bss = bssprio_tbl->bssprio_cur;
+	const mlan_callbacks *const cb = &pmadapter->callbacks;
+	t_void *pmoal = pmadapter->pmoal_handle;
+	mlan_bssprio_node *const stop_point = bss;
+
+	do {
+		mlan_private *mlan;
+		t_u32 queue;
+
+		bssprio_tbl->bssprio_cur = bss;
+		if (bss == (mlan_bssprio_node *)&bssprio_tbl->bssprio_head)
+			goto next_bss;
+
+		mlan = bss->priv;
+
+		if (!wlan_wmm_is_bss_ready_for_tx(pmadapter, mlan)) {
+			goto next_bss;
+		}
+
+		cb->moal_spin_lock(pmoal, mlan->wmm.ra_list_spinlock);
+
+		for (queue = 0; queue < NELEMENTS(mlan->wmm.pending_txq);
+		     ++queue) {
+			if (util_peek_list_nl(pmoal,
+					      &mlan->wmm.pending_txq[queue])) {
+				bssprio_tbl->bssprio_cur =
+					bssprio_tbl->bssprio_cur->pnext;
+				return mlan;
+			}
+		}
+
+		cb->moal_spin_unlock(pmoal, mlan->wmm.ra_list_spinlock);
+
+	next_bss:
+		bss = bss->pnext;
+	} while (bss != stop_point);
+
+	return MNULL;
+}
+
+/**
+ *  @brief gets next BSS to TX
+ *
+ *  @param pmadapter   Pointer to pmlan_adapter structure
+ *
+ *  @return           mlan_private
+ */
+static mlan_private *wlan_wmm_get_next_bss(pmlan_adapter pmadapter)
+{
+	int i;
+	t_void *pmoal = pmadapter->pmoal_handle;
+	mlan_private *mlan = MNULL;
+	ENTER();
+
+	for (i = pmadapter->priv_num - 1; i >= 0 && mlan == MNULL; --i) {
+		mlan_bssprio_tbl *bssprio_tbl = &pmadapter->bssprio_tbl[i];
+
+		if (!util_peek_list_nl(pmoal, &bssprio_tbl->bssprio_head))
+			continue;
+
+		mlan = wlan_wmm_get_next_mlan(pmadapter, bssprio_tbl);
+	}
+
+	LEAVE();
+
+	return mlan;
+}
+
+/**
+ *  @brief helper function to refill budget
+ *
+ *  @param current_value   current budget value
+ *  @param init_value      Addition to bugget
+ *
+ *  @return            new budget value
+ */
+static t_s32 wlan_wmm_refill_budget(t_s32 current_value, t_u32 init_value)
+{
+	if (current_value > 0)
+		return init_value;
+
+	// coverity[integer_overflow:SUPPRESS]
+	return current_value + init_value;
+}
+
+/**
+ *  @brief checks if ra_list has budget to be scheduled for TX
+ *
+ *  @param pmadapter   Pointer to pmlan_adapter structure
+ *  @param mlan        Pointer to mlan_private structure
+ *  @param ra_list     Pointer to ra_list structure
+ *
+ *  @return           MTRUE when ra_list can be scheduled
+ */
+static t_bool wlan_wmm_process_ra_list_quoats(pmlan_adapter pmadapter,
+					      mlan_private *mlan,
+					      raListTbl *ra_list)
+{
+	struct wmm_sta_table *sta = ra_list->sta;
+	const t_u8 tid = ra_list->tid;
+	t_bool ready = MTRUE;
+
+	if (sta->budget.bytes[tid] <= 0 || sta->budget.mpdus[tid] <= 0) {
+		const t_u32 mpdu_budget_init =
+			ra_list->amsdu_in_ampdu ?
+				sta->budget.mpdu_with_amsdu_budget_init :
+				sta->budget.mpdu_no_amsdu_budget_init;
+		util_unlink_list_nl(pmadapter->pmoal_handle,
+				    &ra_list->pending_txq_entry);
+
+		util_enqueue_list_tail_nl(
+			pmadapter->pmoal_handle,
+			&mlan->wmm.pending_txq[ra_list->queue],
+			&ra_list->pending_txq_entry);
+
+		sta->budget.bytes[tid] = wlan_wmm_refill_budget(
+			sta->budget.bytes[tid], sta->budget.byte_budget_init);
+		sta->budget.mpdus[tid] = wlan_wmm_refill_budget(
+			sta->budget.mpdus[tid], mpdu_budget_init);
+
+		mlan->wmm.selected_ra_list = MNULL;
+
+		ready = MFALSE;
+	} else {
+		mlan->wmm.selected_ra_list = ra_list;
+	}
+
+	return ready;
+}
+
+/**
+ *  @brief gets next ra_list to TX
+ *
+ *  @param pmadapter   Pointer to pmlan_adapter structure
+ *  @param mlan        Pointer to mlan_private structure
+ *
+ *  @return           raListTbl
+ */
+static raListTbl *wlan_wmm_get_next_ra_list(pmlan_adapter pmadapter,
+					    mlan_private *mlan)
+{
+	int ac;
+	t_void *pmoal = pmadapter->pmoal_handle;
+
+	while ((ac = wlan_wmm_get_next_ac(pmadapter, mlan)) >= 0) {
+		pmlan_linked_list entry;
+
+		while ((entry = util_peek_list_nl(
+				pmoal, &mlan->wmm.pending_txq[ac])) != MNULL) {
+			raListTbl *ra_list;
+			t_bool has_data;
+
+			ra_list = util_container_of(entry, raListTbl,
+						    pending_txq_entry);
+			has_data = ra_list->total_pkts &&
+				   util_peek_list_nl(pmoal, &ra_list->buf_head);
+
+			/* ra_list can be empry since we re-queue it once we hit
+			 * budget limit */
+			if (!has_data) {
+				struct wmm_sta_table *sta = ra_list->sta;
+				const t_u32 mpdu_budget_init =
+					ra_list->amsdu_in_ampdu ?
+						sta->budget
+							.mpdu_with_amsdu_budget_init :
+						sta->budget
+							.mpdu_no_amsdu_budget_init;
+
+				sta->budget.bytes[ra_list->tid] =
+					sta->budget.byte_budget_init;
+				sta->budget.mpdus[ra_list->tid] =
+					mpdu_budget_init;
+
+				util_unlink_list_nl(
+					pmoal, &ra_list->pending_txq_entry);
+				continue;
+			}
+
+			if (wlan_wmm_process_ra_list_quoats(pmadapter, mlan,
+							    ra_list)) {
+				return ra_list;
+			}
+		}
+	}
+
+	return MNULL;
+}
+
+/**
+ *  @brief Track byte budget consumed by ra_list
+ *
+ *  @param ra_list   Pointer to raListTbl structure
+ *  @param pmbuf     Pointer to mlan_buffer structure
+ *
+ *  @return          N/A
+ */
+void wlan_wmm_consume_byte_budget(raListTbl *ra_list, mlan_buffer *pmbuf)
+{
+	struct wmm_sta_table *sta = ra_list->sta;
+
+	if (sta != MNULL) {
+		t_u32 data_len = pmbuf->data_len;
+
+		if (ra_list->ba_status != BA_STREAM_SETUP_COMPLETE) {
+			/*
+			 * Assumption that non-agg consumes 2 times more
+			 * airtime. It is not always true but we don't have
+			 * airtime feedback from FW anyway.
+			 */
+			data_len *= 2;
+		}
+
+		sta->budget.bytes[ra_list->tid] -= data_len;
+	}
+}
+
+/**
+ *  @brief Track MPDU budget consumed by ra_list
+ *
+ *  @param ra_list   Pointer to raListTbl structure
+ *  @param pmbuf     Pointer to mlan_buffer structure
+ *
+ *  @return          N/A
+ */
+void wlan_wmm_consume_mpdu_budget(raListTbl *ra_list)
+{
+	struct wmm_sta_table *sta = ra_list->sta;
+
+	if (sta != MNULL)
+		sta->budget.mpdus[ra_list->tid]--;
+}
+
+/**
+ *  @brief Debug function to track ra_list switching during scheduling
+ *
+ *  @param mlan      Pointer to mlan_private structure
+ *  @param ra_list   Pointer to raListTbl structure
+ *
+ *  @return          N/A
+ */
+static void wlan_wmm_track_ra_list_switch(mlan_private *mlan,
+					  raListTbl *ra_list)
+{
+	const int use_runtime_log = 1;
+	mlan_adapter *adapter = mlan->adapter;
+
+	if (ra_list != adapter->ra_list_tracing.ra_list) {
+		raListTbl *old_list = adapter->ra_list_tracing.ra_list;
+		t_u32 in_tx_ring = 0;
+#ifdef PCIE
+		if (IS_PCIE(mlan->adapter->card_type))
+			in_tx_ring = mlan->adapter->pcard_pcie->txbd_pending;
+#endif
+		if (use_runtime_log && old_list != MNULL) {
+			struct wmm_sta_table *old_sta = old_list->sta;
+
+			PRINTM(MSCH_D,
+			       "mclient: switch[ %u/%u : q size: %u/%u bb: r %d m %d ri %u mi %u %u p %u] %pM tid %u -> %pM tid %u",
+			       adapter->ra_list_tracing.pushed_pkg, in_tx_ring,
+			       old_list->total_pkts,
+			       old_sta->budget.queue_packets,
+			       old_sta->budget.bytes[old_list->tid],
+			       old_sta->budget.mpdus[old_list->tid],
+			       old_sta->budget.byte_budget_init,
+			       old_sta->budget.mpdu_no_amsdu_budget_init,
+			       old_sta->budget.mpdu_with_amsdu_budget_init,
+			       old_sta->budget.phy_rate_kbps / 1000,
+			       old_list->ra, old_list->tid, ra_list->ra,
+			       ra_list->tid);
+		}
+
+		adapter->ra_list_tracing.ra_list = ra_list;
+		adapter->ra_list_tracing.pushed_pkg = 0;
+	}
+
+	adapter->ra_list_tracing.pushed_pkg++;
+}
+
+/**
+ *  @brief gets next raListTbl for TX based on currect scheduling configuration
+ *
+ *  @param pmadapter      A pointer to mlan_adapter
+ *  @param priv           A pointer to mlan_private
+ *  @param tid            A pointer to return tid
+ *
+ *  @return             raListTbl
+ */
+static raListTbl *wlan_wmm_get_next_priolist_ptr(pmlan_adapter pmadapter,
+						 pmlan_private *priv, int *tid)
+{
+	mlan_private *mlan = pmadapter->selected_mlan_bss;
+	mlan_callbacks *cbs = &pmadapter->callbacks;
+	void *const pmoal_handle = pmadapter->pmoal_handle;
+	raListTbl *ra_list = MNULL;
+
+	if (!pmadapter->mclient_tx_supported)
+		return wlan_wmm_get_highest_priolist_ptr(pmadapter, priv, tid);
+
+	if (mlan) {
+		cbs->moal_spin_lock(pmoal_handle, mlan->wmm.ra_list_spinlock);
+	} else {
+		mlan = wlan_wmm_get_next_bss(pmadapter);
+	}
+
+	for (; mlan != MNULL; mlan = wlan_wmm_get_next_bss(pmadapter)) {
+		ra_list = mlan->wmm.selected_ra_list;
+
+		if (ra_list == MNULL || ra_list->total_pkts == 0) {
+			ra_list = wlan_wmm_get_next_ra_list(pmadapter, mlan);
+		} else if (!wlan_wmm_process_ra_list_quoats(pmadapter, mlan,
+							    ra_list)) {
+			pmadapter->selected_mlan_bss = MNULL;
+			cbs->moal_spin_unlock(pmoal_handle,
+					      mlan->wmm.ra_list_spinlock);
+			continue;
+		}
+
+		if (ra_list != MNULL) {
+			wlan_wmm_track_ra_list_switch(mlan, ra_list);
+
+			*priv = mlan;
+			*tid = ra_list->tid;
+
+			pmadapter->selected_mlan_bss = mlan;
+
+			return ra_list;
+		}
+
+		cbs->moal_spin_unlock(pmoal_handle, mlan->wmm.ra_list_spinlock);
+	}
+
+	pmadapter->selected_mlan_bss = MNULL;
+
+	return wlan_wmm_get_highest_priolist_ptr(pmadapter, priv, tid);
+}
+
 /**
  *  @brief This function gets the number of packets in the Tx queue
  *
@@ -846,6 +1587,8 @@ static INLINE void wlan_send_single_packet(pmlan_private priv, raListTbl *ptr,
 						&ptr->buf_head, MNULL, MNULL);
 	if (pmbuf) {
 		PRINTM(MINFO, "Dequeuing the packet %p %p\n", ptr, pmbuf);
+		wlan_wmm_consume_mpdu_budget(ptr);
+		wlan_wmm_consume_byte_budget(ptr, pmbuf);
 		priv->wmm.pkts_queued[ptrindex]--;
 		util_scalar_decrement(pmadapter->pmoal_handle,
 				      &priv->wmm.tx_pkts_queued, MNULL, MNULL);
@@ -901,9 +1644,9 @@ static INLINE void wlan_send_single_packet(pmlan_private priv, raListTbl *ptr,
 				priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr =
 					ptr;
 			}
-			pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
-				pmadapter->bssprio_tbl[priv->bss_priority]
-					.bssprio_cur->pnext;
+			wlan_advance_bss_on_pkt_push(
+				pmadapter,
+				&pmadapter->bssprio_tbl[priv->bss_priority]);
 			pmadapter->callbacks.moal_spin_unlock(
 				pmadapter->pmoal_handle,
 				priv->wmm.ra_list_spinlock);
@@ -1028,9 +1771,10 @@ static INLINE void wlan_send_processed_packet(pmlan_private priv,
 					ptr;
 				ptr->total_pkts--;
 			}
-			pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
-				pmadapter->bssprio_tbl[priv->bss_priority]
-					.bssprio_cur->pnext;
+
+			wlan_advance_bss_on_pkt_push(
+				pmadapter,
+				&pmadapter->bssprio_tbl[priv->bss_priority]);
 			priv->wmm.pkts_queued[ptrindex]--;
 			util_scalar_decrement(pmadapter->pmoal_handle,
 					      &priv->wmm.tx_pkts_queued, MNULL,
@@ -1064,7 +1808,8 @@ static int wlan_dequeue_tx_packet(pmlan_adapter pmadapter)
 
 	ENTER();
 
-	ptr = wlan_wmm_get_highest_priolist_ptr(pmadapter, &priv, &ptrindex);
+	ptr = wlan_wmm_get_next_priolist_ptr(pmadapter, &priv, &ptrindex);
+
 	if (!ptr) {
 		LEAVE();
 		return MLAN_STATUS_FAILURE;
@@ -1180,10 +1925,65 @@ static int wlan_dequeue_tx_packet(pmlan_adapter pmadapter)
 		}
 	}
 
+	if (ptr->sta && ptr->sta->ps_sleep) {
+		wlan_update_ralist_tx_pause(priv, ptr->ra, 1);
+	}
+
 	LEAVE();
 	return MLAN_STATUS_SUCCESS;
 }
 
+/**
+ *  @brief remove ra_list from pendiing TX queues
+ *
+ *  @param priv        A pointer to mlan_private
+ *  @param pmadapter   A pointer to pmlan_adapter
+ *  @param ra_list     A pointer to raListTbl
+ *
+ *  @return           N/A
+ */
+static void wlan_ralist_remove_from_pending_txq(pmlan_private priv,
+						pmlan_adapter pmadapter,
+						raListTbl *ra_list)
+{
+	mlan_adapter *adapter = priv->adapter;
+
+	if (util_is_node_in_list(&ra_list->pending_txq_entry))
+		util_unlink_list_nl(pmadapter->pmoal_handle,
+				    &ra_list->pending_txq_entry);
+
+	if (ra_list == priv->wmm.selected_ra_list)
+		priv->wmm.selected_ra_list = MNULL;
+
+	if (ra_list == adapter->ra_list_tracing.ra_list)
+		adapter->ra_list_tracing.ra_list = MNULL;
+
+	if (ra_list->sta)
+		util_unlink_list_safe_nl(pmadapter->pmoal_handle,
+					 &ra_list->sta->pending_stas_entry);
+}
+
+/**
+ *  @brief Add ra_list back to pendiing TX queue
+ *
+ *  @param priv        A pointer to mlan_private
+ *  @param pmadapter   A pointer to pmlan_adapter
+ *  @param ra_list     A pointer to raListTbl
+ *  @param tid         tid
+ *
+ *  @return           N/A
+ */
+static void wlan_ralist_add_to_pending_txq(pmlan_private priv,
+					   pmlan_adapter pmadapter,
+					   raListTbl *ra_list, t_u8 tid)
+{
+	t_u8 queue = wlan_wmm_select_queue(priv, tid);
+
+	util_enqueue_list_head(pmadapter->pmoal_handle,
+			       &priv->wmm.pending_txq[queue],
+			       &ra_list->pending_txq_entry, MNULL, MNULL);
+}
+
 /**
  *  @brief update tx_pause flag in ra_list
  *
@@ -1196,7 +1996,6 @@ static int wlan_dequeue_tx_packet(pmlan_adapter pmadapter)
  */
 t_u16 wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 *mac, t_u8 tx_pause)
 {
-	raListTbl *ra_list;
 	int i;
 	pmlan_adapter pmadapter = priv->adapter;
 	t_u32 pkt_cnt = 0;
@@ -1206,16 +2005,23 @@ t_u16 wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 *mac, t_u8 tx_pause)
 	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
 					    priv->wmm.ra_list_spinlock);
 	for (i = 0; i < MAX_NUM_TID; ++i) {
-		ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
-		if (ra_list && ra_list->tx_pause != tx_pause) {
-			pkt_cnt += ra_list->total_pkts;
-			ra_list->tx_pause = tx_pause;
-			if (tx_pause)
-				priv->wmm.pkts_paused[i] += ra_list->total_pkts;
-			else
-				priv->wmm.pkts_paused[i] -= ra_list->total_pkts;
+		raListTbl *ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
+		if (ra_list == MNULL || ra_list->tx_pause == tx_pause)
+			continue;
+
+		pkt_cnt += ra_list->total_pkts;
+		ra_list->tx_pause = tx_pause;
+		if (tx_pause) {
+			priv->wmm.pkts_paused[i] += ra_list->total_pkts;
+			wlan_ralist_remove_from_pending_txq(priv, pmadapter,
+							    ra_list);
+		} else {
+			priv->wmm.pkts_paused[i] -= ra_list->total_pkts;
+			wlan_ralist_add_to_pending_txq(priv, pmadapter, ra_list,
+						       i);
 		}
 	}
+
 	if (pkt_cnt) {
 		tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
 						  &priv->wmm.tx_pkts_queued,
@@ -1233,6 +2039,7 @@ t_u16 wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 *mac, t_u8 tx_pause)
 	}
 	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
 					      priv->wmm.ra_list_spinlock);
+
 	LEAVE();
 	return pkt_cnt;
 }
@@ -1503,6 +2310,7 @@ t_void wlan_clean_txrx(pmlan_private priv)
 	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
 					    priv->wmm.ra_list_spinlock);
 	wlan_wmm_cleanup_queues(priv);
+	wlan_wmm_delete_all_sta_entries(priv);
 	wlan_wmm_delete_all_ralist(priv);
 	memcpy_ext(pmadapter, tos_to_tid, ac_to_tid, sizeof(tos_to_tid),
 		   sizeof(tos_to_tid));
@@ -1715,9 +2523,17 @@ void wlan_ralist_add(mlan_private *priv, t_u8 *ra)
 	raListTbl *ra_list;
 	pmlan_adapter pmadapter = priv->adapter;
 	tdlsStatus_e status;
+	struct wmm_sta_table *sta = MNULL;
 
 	ENTER();
 
+	sta = wlan_wmm_allocate_sta_table(pmadapter, ra);
+	if (sta) {
+		util_enqueue_list_tail_nl(pmadapter->pmoal_handle,
+					  &priv->wmm.all_stas,
+					  &sta->all_stas_entry);
+	}
+
 	for (i = 0; i < MAX_NUM_TID; ++i) {
 		ra_list = wlan_wmm_allocate_ralist_node(pmadapter, ra);
 		PRINTM(MINFO, "Creating RA List %p for tid %d\n", ra_list, i);
@@ -1726,6 +2542,13 @@ void wlan_ralist_add(mlan_private *priv, t_u8 *ra)
 		ra_list->max_amsdu = 0;
 		ra_list->ba_status = BA_STREAM_NOT_SETUP;
 		ra_list->amsdu_in_ampdu = MFALSE;
+		ra_list->tid = i;
+		ra_list->queue = wlan_wmm_select_queue(priv, i);
+		ra_list->sta = sta;
+		if (sta)
+			sta->ra_lists[i] = ra_list;
+		util_init_list(&ra_list->pending_txq_entry);
+
 		if (queuing_ra_based(priv)) {
 			ra_list->is_wmm_enabled = wlan_is_wmm_enabled(priv, ra);
 			if (ra_list->is_wmm_enabled)
@@ -1826,6 +2649,15 @@ t_void wlan_init_wmm_param(pmlan_adapter pmadapter)
  */
 t_void wlan_wmm_init(pmlan_adapter pmadapter)
 {
+	static const IEEEtypes_WmmAcParameters_t default_ac_params[] = {
+		[AC_BE] = {.aci_aifsn = {.aifsn = 3, .aci = AC_BE},
+			   .ecw = {.ecw_min = 4, .ecw_max = 10}},
+		[AC_BK] = {.aci_aifsn = {.aifsn = 7, .aci = AC_BK},
+			   .ecw = {.ecw_min = 4, .ecw_max = 10}},
+		[AC_VI] = {.aci_aifsn = {.aifsn = 2, .aci = AC_VI},
+			   .ecw = {.ecw_min = 3, .ecw_max = 4}},
+		[AC_VO] = {.aci_aifsn = {.aifsn = 2, .aci = AC_VO},
+			   .ecw = {.ecw_min = 2, .ecw_max = 3}}};
 	int i, j;
 	pmlan_private priv;
 
@@ -1843,6 +2675,7 @@ t_void wlan_wmm_init(pmlan_adapter pmadapter)
 				priv->wmm.pkts_queued[i] = 0;
 				priv->wmm.pkts_paused[i] = 0;
 				priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL;
+				priv->wmm.selected_ra_list = MNULL;
 			}
 			priv->wmm.drv_pkt_delay_max = WMM_DRV_DELAY_MAX;
 
@@ -1857,6 +2690,8 @@ t_void wlan_wmm_init(pmlan_adapter pmadapter)
 					BA_STREAM_NOT_ALLOWED;
 			priv->add_ba_param.timeout =
 				MLAN_DEFAULT_BLOCK_ACK_TIMEOUT;
+			if (!pmadapter->tx_ba_timeout_support)
+				priv->add_ba_param.timeout = 0;
 #ifdef STA_SUPPORT
 			if (priv->bss_type == MLAN_BSS_TYPE_STA) {
 				priv->add_ba_param.tx_win_size =
@@ -1893,6 +2728,8 @@ t_void wlan_wmm_init(pmlan_adapter pmadapter)
 			memset(priv->adapter, priv->rx_seq, 0xff,
 			       sizeof(priv->rx_seq));
 			wlan_wmm_default_queue_priorities(priv);
+
+			wlan_wmm_contention_init(priv, default_ac_params);
 		}
 	}
 
@@ -2013,6 +2850,43 @@ raListTbl *wlan_wmm_get_ralist_node(pmlan_private priv, t_u8 tid, t_u8 *ra_addr)
 	return MNULL;
 }
 
+/**
+ *   @brief Get wmm_sta_table node
+ *
+ *   @param priv     Pointer to the mlan_private driver data struct
+ *   @param ra_addr  Pointer to the route address
+ *
+ *   @return         wmm_sta_table or MNULL
+ */
+static struct wmm_sta_table *wlan_wmm_get_sta(pmlan_private priv,
+					      const t_u8 *ra_addr)
+{
+	mlan_linked_list *sta_entry;
+	mlan_adapter *adapter = priv->adapter;
+
+	if (!adapter->mclient_tx_supported)
+		return MNULL;
+
+	ENTER();
+
+	for (sta_entry = util_peek_list_nl(adapter->pmoal_handle,
+					   &priv->wmm.all_stas);
+	     sta_entry && sta_entry != (void *)&priv->wmm.all_stas;
+	     sta_entry = sta_entry->pnext) {
+		struct wmm_sta_table *sta = util_container_of(
+			sta_entry, struct wmm_sta_table, all_stas_entry);
+
+		if (memcmp(adapter, sta->ra, ra_addr, MLAN_MAC_ADDR_LENGTH) ==
+		    0) {
+			LEAVE();
+			return sta;
+		}
+	}
+
+	LEAVE();
+	return MNULL;
+}
+
 /**
  *   @brief Check if RA list is valid or not
  *
@@ -2105,6 +2979,184 @@ int wlan_ralist_update(mlan_private *priv, t_u8 *old_ra, t_u8 *new_ra)
 	return update_count;
 }
 
+/**
+ *  @brief  Update TX PHY rate for STAs in sta_list
+ *
+ *  @param pmpriv     Pointer to the mlan_private driver data struct
+ *  @param sta_list   NULL terminated list of STAs
+ *
+ *  @return MLAN_STATUS_SUCCESS
+ */
+static mlan_status wlan_misc_get_sta_rate(pmlan_private pmpriv,
+					  t_u8 *sta_list[])
+{
+	HostCmd_CMD_802_11_STA_TX_RATE txRateReq = {0};
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	int i;
+
+	for (i = 0; i < NELEMENTS(txRateReq.entry) && sta_list[i]; ++i) {
+		memcpy_ext(pmpriv->adapter, txRateReq.entry[i].sta_mac,
+			   sta_list[i], MLAN_MAC_ADDR_LENGTH,
+			   MLAN_MAC_ADDR_LENGTH);
+	}
+
+	if (i > 0) {
+		txRateReq.num_entries = i;
+		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_PEER_TX_RATE_QUERY,
+				       HostCmd_ACT_GEN_GET, 0, MNULL,
+				       &txRateReq);
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief Trigger STAs TX rate update
+ *
+ *  @param pmadapter  Pointer to the pmlan_adapter driver data struct
+ *  @param priv       Pointer to the mlan_private driver data struct
+ *
+ *  @return N/A
+ */
+static void wlan_wmm_update_sta_txrate_info(pmlan_adapter pmadapter,
+					    pmlan_private priv)
+{
+	t_u8 *sta_list[MAX_STA_IN_TX_RATE_REQ + 1] = {0};
+	t_void *pmoal = pmadapter->pmoal_handle;
+	mlan_callbacks *cbs = &pmadapter->callbacks;
+	int idx = 0;
+	const int idx_limit = MAX_STA_IN_TX_RATE_REQ;
+	pmlan_linked_list list_entry;
+	t_u64 time_now;
+	static const t_u64 update_interval = 1000ull * 1000ull * 1000ull;
+
+	cbs->moal_get_host_time_ns(&time_now);
+
+	if (util_is_time_before(time_now, priv->wmm.next_rate_update)) {
+		return;
+	}
+
+	if (priv->wmm.is_rate_update_pending) {
+		return;
+	}
+
+	priv->wmm.next_rate_update = time_now + update_interval;
+
+	while (idx < idx_limit &&
+	       (list_entry = util_peek_list_nl(
+			pmoal, &priv->wmm.pending_stas)) != MNULL) {
+		struct wmm_sta_table *sta = util_container_of(
+			list_entry, struct wmm_sta_table, pending_stas_entry);
+		const t_bool is_bmcast = (sta->ra[0] & 0x01);
+
+		if (!is_bmcast) {
+			sta_list[idx++] = sta->ra;
+		}
+
+		util_unlink_list_nl(pmoal, list_entry);
+	}
+
+	if (idx > 0) {
+		priv->wmm.is_rate_update_pending = MTRUE;
+		wlan_misc_get_sta_rate(priv, sta_list);
+	}
+}
+
+/**
+ *  @brief Updates STAs activity
+ *
+ *  @param pmadapter  Pointer to the pmlan_adapter driver data struct
+ *  @param priv       Pointer to the mlan_private driver data struct
+ *  @param ra_list    Pointer to the raListTbl struct
+ *  @param sta_table  Pointer to the wmm_sta_table struct
+ *
+ *  @return N/A
+ */
+static t_void wlan_wmm_record_sta_tx(pmlan_adapter pmadapter,
+				     pmlan_private priv, raListTbl *ra_list,
+				     struct wmm_sta_table *sta_table)
+{
+	t_bool is_bmcast;
+	const t_u32 tx_active_threshold = 4;
+
+	if (!sta_table)
+		return;
+
+	is_bmcast = (sta_table->ra[0] & 0x01);
+	if (!is_bmcast && ra_list->total_pkts > tx_active_threshold &&
+	    !util_is_node_in_list(&sta_table->active_sta_entry)) {
+		util_enqueue_list_tail_nl(pmadapter->pmoal_handle,
+					  &priv->wmm.active_stas.list,
+					  &sta_table->active_sta_entry);
+		priv->wmm.active_stas.n_stas++;
+	}
+}
+
+/**
+ *  @brief Updates queue_packets budget for all active STAs
+ *
+ *  @param pmadapter  Pointer to the pmlan_adapter driver data struct
+ *  @param priv       Pointer to the mlan_private driver data struct
+ *
+ *  @return N/A
+ */
+static t_void wlan_wmm_update_queue_packets_budget(pmlan_adapter pmadapter,
+						   pmlan_private priv)
+{
+	t_void *pmoal = pmadapter->pmoal_handle;
+	pmlan_linked_list list_entry;
+	const t_u32 queue_packets_limit = pmadapter->init_para.max_tx_pending;
+	t_u64 total_capacity = 0;
+	t_u64 time_now;
+	mlan_callbacks *cbs = &pmadapter->callbacks;
+	static const t_u64 update_interval = 200ull * 1000ull * 1000ull;
+	const t_u32 min_sta_share = 128;
+	const t_u32 max_pending_tx_time_us = 200u * 1000u;
+
+	if (!pmadapter->mclient_tx_supported)
+		return;
+
+	cbs->moal_get_host_time_ns(&time_now);
+
+	if (util_is_time_before(time_now, priv->wmm.active_stas.next_update))
+		return;
+
+	priv->wmm.active_stas.n_stas = 0;
+	priv->wmm.active_stas.next_update = time_now + update_interval;
+
+	for (list_entry = util_peek_list_nl(pmoal, &priv->wmm.active_stas.list);
+	     util_is_list_node(&priv->wmm.active_stas.list, list_entry);
+	     list_entry = list_entry->pnext) {
+		struct wmm_sta_table *sta = util_container_of(
+			list_entry, struct wmm_sta_table, active_sta_entry);
+
+		total_capacity += sta->budget.byte_budget_init;
+	}
+
+	if (total_capacity == 0)
+		return;
+
+	while ((list_entry = util_peek_list_nl(
+			pmoal, &priv->wmm.active_stas.list)) != MNULL) {
+		struct wmm_sta_table *sta = util_container_of(
+			list_entry, struct wmm_sta_table, active_sta_entry);
+		const t_u64 sta_capacity = sta->budget.byte_budget_init;
+		const t_u32 max_pkts_by_airtime =
+			wlan_wmm_get_byte_budget(max_pending_tx_time_us,
+						 sta->budget.phy_rate_kbps) /
+			MV_ETH_FRAME_LEN;
+		t_u32 sta_share =
+			queue_packets_limit * sta_capacity / total_capacity;
+
+		sta_share = MAX(sta_share, min_sta_share);
+		sta_share = MIN(sta_share, queue_packets_limit * 7 / 8);
+		sta_share = MIN(sta_share, max_pkts_by_airtime);
+
+		sta->budget.queue_packets = sta_share;
+		util_unlink_list_nl(pmoal, list_entry);
+	}
+}
+
 /**
  *  @brief Add packet to WMM queue
  *
@@ -2118,6 +3170,7 @@ t_void wlan_wmm_add_buf_txqueue(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
 	pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
 	t_u32 tid;
 	raListTbl *ra_list;
+	struct wmm_sta_table *sta_table;
 	t_u8 ra[MLAN_MAC_ADDR_LENGTH], tid_down;
 	tdlsStatus_e status;
 #ifdef UAP_SUPPORT
@@ -2201,6 +3254,22 @@ t_void wlan_wmm_add_buf_txqueue(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
 		return;
 	}
 
+	sta_table = wlan_wmm_get_sta(priv, ra_list->ra);
+	wlan_wmm_record_sta_tx(pmadapter, priv, ra_list, sta_table);
+	wlan_wmm_update_queue_packets_budget(pmadapter, priv);
+
+	if (sta_table &&
+	    ra_list->total_pkts > sta_table->budget.queue_packets &&
+	    !(pmbuf->flags & MLAN_BUF_FLAG_TCP_PKT)) {
+		pmadapter->callbacks.moal_spin_unlock(
+			pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock);
+		wlan_write_data_complete(pmadapter, pmbuf,
+					 MLAN_STATUS_RESOURCE);
+		LEAVE();
+
+		return;
+	}
+
 	PRINTM_NETINTF(MDATA, priv);
 	PRINTM(MDATA,
 	       "Adding pkt %p (priority=%d, tid_down=%d) to ra_list %p\n",
@@ -2224,6 +3293,28 @@ t_void wlan_wmm_add_buf_txqueue(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
 			MLAN_SCALAR_COND_LESS_THAN, tos_to_tid_inv[tid_down],
 			tos_to_tid_inv[tid_down], MNULL, MNULL);
 	}
+
+	if (sta_table) {
+		if (!ra_list->tx_pause &&
+		    !util_is_node_in_list(&sta_table->pending_stas_entry)) {
+			util_enqueue_list_tail_nl(
+				pmadapter->pmoal_handle,
+				&priv->wmm.pending_stas,
+				&sta_table->pending_stas_entry);
+		}
+
+		wlan_wmm_update_sta_txrate_info(pmadapter, priv);
+
+		/* enqueue node-tid to pending AC */
+		if (!ra_list->tx_pause &&
+		    !util_is_node_in_list(&ra_list->pending_txq_entry)) {
+			t_u8 queue = wlan_wmm_select_queue(priv, tid_down);
+
+			util_enqueue_list_tail_nl(pmadapter->pmoal_handle,
+						  &priv->wmm.pending_txq[queue],
+						  &ra_list->pending_txq_entry);
+		}
+	}
 	/* Record the current time the packet was queued; used to determine
 	 *   the amount of time the packet was queued in the driver before it
 	 *   was sent to the firmware.  The delay is then sent along with the
@@ -2410,6 +3501,8 @@ mlan_status wlan_ret_wmm_get_status(pmlan_private priv, t_u8 *ptlv,
 
 	wlan_wmm_setup_queue_priorities(priv, pwmm_param_ie);
 	wlan_wmm_setup_ac_downgrade(priv);
+	if (pwmm_param_ie != MNULL)
+		wlan_wmm_contention_init(priv, pwmm_param_ie->ac_params);
 
 	if (send_wmm_event) {
 		wlan_recv_event(priv, MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE,
@@ -2710,14 +3803,17 @@ t_void wlan_drop_tx_pkts(pmlan_private priv)
 t_void wlan_wmm_delete_peer_ralist(pmlan_private priv, t_u8 *mac)
 {
 	raListTbl *ra_list;
+	struct wmm_sta_table *sta;
 	int i;
 	pmlan_adapter pmadapter = priv->adapter;
+	mlan_callbacks *cbs = &pmadapter->callbacks;
+	void *const pmoal_handle = pmadapter->pmoal_handle;
 	t_u32 pkt_cnt = 0;
 	t_u32 tx_pkts_queued = 0;
 
 	ENTER();
-	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
-					    priv->wmm.ra_list_spinlock);
+	cbs->moal_spin_lock(pmoal_handle, priv->wmm.ra_list_spinlock);
+
 	for (i = 0; i < MAX_NUM_TID; ++i) {
 		ra_list = wlan_wmm_get_ralist_node(priv, i, mac);
 		if (ra_list) {
@@ -2729,12 +3825,22 @@ t_void wlan_wmm_delete_peer_ralist(pmlan_private priv, t_u8 *mac)
 				pkt_cnt += ra_list->total_pkts;
 			wlan_wmm_del_pkts_in_ralist_node(priv, ra_list);
 
-			util_unlink_list(pmadapter->pmoal_handle,
+			if (ra_list == priv->wmm.selected_ra_list)
+				priv->wmm.selected_ra_list = MNULL;
+
+			if (ra_list == pmadapter->ra_list_tracing.ra_list)
+				pmadapter->ra_list_tracing.ra_list = MNULL;
+
+			if (util_is_node_in_list(&ra_list->pending_txq_entry))
+				util_unlink_list_nl(
+					pmoal_handle,
+					&ra_list->pending_txq_entry);
+
+			util_unlink_list(pmoal_handle,
 					 &priv->wmm.tid_tbl_ptr[i].ra_list,
 					 (pmlan_linked_list)ra_list, MNULL,
 					 MNULL);
-			pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
-							(t_u8 *)ra_list);
+			cbs->moal_mfree(pmoal_handle, (t_u8 *)ra_list);
 			if (priv->wmm.tid_tbl_ptr[i].ra_list_curr == ra_list)
 				priv->wmm.tid_tbl_ptr[i].ra_list_curr =
 					(raListTbl *)&priv->wmm.tid_tbl_ptr[i]
@@ -2742,9 +3848,8 @@ t_void wlan_wmm_delete_peer_ralist(pmlan_private priv, t_u8 *mac)
 		}
 	}
 	if (pkt_cnt) {
-		tx_pkts_queued = util_scalar_read(pmadapter->pmoal_handle,
-						  &priv->wmm.tx_pkts_queued,
-						  MNULL, MNULL);
+		tx_pkts_queued = util_scalar_read(
+			pmoal_handle, &priv->wmm.tx_pkts_queued, MNULL, MNULL);
 		tx_pkts_queued -= pkt_cnt;
 		util_scalar_write(priv->adapter->pmoal_handle,
 				  &priv->wmm.tx_pkts_queued, tx_pkts_queued,
@@ -2753,8 +3858,18 @@ t_void wlan_wmm_delete_peer_ralist(pmlan_private priv, t_u8 *mac)
 				  &priv->wmm.highest_queued_prio, HIGH_PRIO_TID,
 				  MNULL, MNULL);
 	}
-	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
-					      priv->wmm.ra_list_spinlock);
+
+	sta = wlan_wmm_get_sta(priv, mac);
+	if (sta) {
+		util_unlink_list_nl(pmoal_handle, &sta->all_stas_entry);
+		util_unlink_list_safe_nl(pmoal_handle,
+					 &sta->pending_stas_entry);
+		util_unlink_list_safe_nl(pmoal_handle, &sta->active_sta_entry);
+
+		cbs->moal_mfree(pmoal_handle, (t_u8 *)sta);
+	}
+
+	cbs->moal_spin_unlock(pmoal_handle, priv->wmm.ra_list_spinlock);
 	LEAVE();
 }
 
@@ -3869,3 +4984,306 @@ int wlan_get_wmm_tid_down(mlan_private *priv, int tid)
 {
 	return wlan_wmm_downgrade_tid(priv, tid);
 }
+
+#define ieee_mbit_rate(float_value) ((t_u32)(float_value * 1000u))
+
+/**
+ *  @brief The function gets PHY rate in kbit/s for HE PPDU.
+ *
+ *  @param bw     PPDU bandwith
+ *  @param gi     GI type
+ *  @param nss    number of spatial streams
+ *  @param mcs    MCS
+ *
+ *  @return            PHY rate in kbit per second
+ */
+static t_u32 wlam_wmm_get_he_rate(t_u32 bw, t_u32 gi, t_u32 nss, t_u32 mcs)
+{
+	const t_u32 gi_1x_0p8 = 0;
+	const t_u32 gi_2x_0p8 = 1;
+	const t_u32 gi_2x_1p6 = 2;
+
+	const t_u32 bw_20 = 0;
+	const t_u32 bw_40 = 1;
+	const t_u32 bw_160 = 3;
+	t_u32 rate;
+
+	static const t_u32 he_80_3p2_gi_mcS_to_rate[] = {
+		ieee_mbit_rate(30.6),  ieee_mbit_rate(61.3),
+		ieee_mbit_rate(91.9),  ieee_mbit_rate(122.5),
+		ieee_mbit_rate(183.8), ieee_mbit_rate(245),
+		ieee_mbit_rate(275.6), ieee_mbit_rate(306.3),
+		ieee_mbit_rate(367.5), ieee_mbit_rate(408.3),
+		ieee_mbit_rate(459.4), ieee_mbit_rate(510.4)};
+
+	if (mcs >= NELEMENTS(he_80_3p2_gi_mcS_to_rate))
+		return 0;
+
+	rate = he_80_3p2_gi_mcS_to_rate[mcs];
+
+	// 11ax scaling rules
+	// 1.6_gi_rate = 0.8_gi_rate / 1.059
+	// 3.2_gi_rate = 1.6_gi_rate / 1.112
+	// 160mhz_rate = 80mhz_rate * 2.0
+	// 40mhz_rate = 80mhz_rate / 2.09
+	// 20mhz_rate = 40mhz_rate / 2
+
+	if (gi == gi_1x_0p8 || gi == gi_2x_0p8) {
+		rate = (rate * 1112u) / 1000u;
+		rate = (rate * 1059u) / 1000u;
+	} else if (gi == gi_2x_1p6) {
+		rate = (rate * 1112u) / 1000u;
+	}
+
+	if (bw == bw_20) {
+		rate = (rate * 1000u) / 2090u;
+		rate /= 2;
+	} else if (bw == bw_40) {
+		rate = (rate * 1000u) / 2090u;
+	} else if (bw == bw_160) {
+		rate *= 2;
+	}
+
+	rate = rate * nss;
+
+	// coverity[integer_overflow:SUPPRESS]
+	return rate;
+}
+
+/**
+ *  @brief The function gets PHY rate in kbit/s for VHT PPDU.
+ *
+ *  @param bw     PPDU bandwith
+ *  @param sgi    short GI
+ *  @param nss    number of spatial streams
+ *  @param mcs    MCS
+ *
+ *  @return            PHY rate in kbit per second
+ */
+static t_u32 wlam_wmm_get_vht_rate(t_u32 bw, t_u32 sgi, t_u32 nss, t_u32 mcs)
+{
+	const t_u32 bw_20 = 0;
+	const t_u32 bw_40 = 1;
+	const t_u32 bw_160 = 3;
+	t_u32 rate;
+
+	static const t_u32 vht_80_lgi_mcs_to_rate[] = {
+		ieee_mbit_rate(29.3),  ieee_mbit_rate(58.5),
+		ieee_mbit_rate(87.8),  ieee_mbit_rate(117.0),
+		ieee_mbit_rate(175.5), ieee_mbit_rate(234.0),
+		ieee_mbit_rate(263.3), ieee_mbit_rate(292.5),
+		ieee_mbit_rate(351.0), ieee_mbit_rate(390.0)};
+
+	if (mcs >= NELEMENTS(vht_80_lgi_mcs_to_rate))
+		return 0;
+
+	rate = vht_80_lgi_mcs_to_rate[mcs];
+
+	// 11ac scaling rules:
+	// sgi_rate = lgi_rate * 1.111
+	// 160mhz_rate = 80_mhz_rate * 2.0
+	// 40mhz_rate = 80_mhz_rate / 2.166
+	// 20mhz_rate = 40mhz_rate / 2.077
+	// XSS_rate = 1ss_rate * NSS
+	if (sgi)
+		rate = (rate * 1111) / 1000;
+
+	if (bw == bw_20) {
+		rate = (rate * 1000u) / 2166u;
+		rate = (rate * 1000u) / 2077u;
+	} else if (bw == bw_40) {
+		rate = (rate * 1000u) / 2166u;
+	} else if (bw == bw_160) {
+		rate *= 2;
+	}
+
+	rate = rate * nss;
+
+	// coverity[integer_overflow:SUPPRESS]
+	return rate;
+}
+
+/**
+ *  @brief The function gets PHY rate in kbit/s for HT PPDU.
+ *
+ *  @param bw     PPDU bandwith
+ *  @param sgi    short GI
+ *  @param mcs    MCS
+ *
+ *  @return            PHY rate in kbit per second
+ */
+static t_u32 wlam_wmm_get_ht_rate(t_u32 bw, t_u32 sgi, t_u32 mcs)
+{
+	const t_u32 bw_40 = 1;
+	t_u32 rate;
+
+	static const t_u32 ht_20_lgi_mcs_to_rate[] = {
+		ieee_mbit_rate(6.5),  ieee_mbit_rate(13),  ieee_mbit_rate(19.5),
+		ieee_mbit_rate(26),   ieee_mbit_rate(39),  ieee_mbit_rate(52),
+		ieee_mbit_rate(58.5), ieee_mbit_rate(65),  ieee_mbit_rate(13),
+		ieee_mbit_rate(26),   ieee_mbit_rate(39),  ieee_mbit_rate(52),
+		ieee_mbit_rate(78),   ieee_mbit_rate(104), ieee_mbit_rate(117),
+		ieee_mbit_rate(130),
+	};
+
+	if (mcs >= NELEMENTS(ht_20_lgi_mcs_to_rate))
+		return 0;
+
+	rate = ht_20_lgi_mcs_to_rate[mcs];
+
+	// 11n scaling rules:
+	// sgi_rate = lgi_rate * 1.111
+	// 40mhz_rate = 20_mhz_rate * 2.077
+
+	if (sgi)
+		rate = (rate * 1111) / 1000;
+
+	if (bw == bw_40) {
+		rate = (rate * 2077u) / 1000;
+	}
+
+	// coverity[integer_overflow:SUPPRESS]
+	return rate;
+}
+
+/**
+ *  @brief The function gets PHY rate in kbit/s for legacy PPDU.
+ *
+ *  @param rate_idx    rate index
+ *
+ *  @return            PHY rate in kbit per second
+ */
+static t_u32 wlam_wmm_get_legacy_rate(t_u32 rate_idx)
+{
+	static const t_u32 legacy_rate_idx_to_rate[] = {
+		ieee_mbit_rate(1),  ieee_mbit_rate(2),	ieee_mbit_rate(5.5),
+		ieee_mbit_rate(11), ieee_mbit_rate(22), ieee_mbit_rate(6),
+		ieee_mbit_rate(9),  ieee_mbit_rate(12), ieee_mbit_rate(18),
+		ieee_mbit_rate(24), ieee_mbit_rate(36), ieee_mbit_rate(48),
+		ieee_mbit_rate(54), ieee_mbit_rate(72),
+	};
+
+	if (rate_idx >= NELEMENTS(legacy_rate_idx_to_rate))
+		return 0;
+
+	return legacy_rate_idx_to_rate[rate_idx];
+}
+
+/**
+ *  @brief The function sets byte tx_budget based on currect TX rate and
+ *          allocated airtime.
+ *
+ *  @param priv    Pointer to the pmlan_private driver data struct
+ *  @param sta     Pointer to the wmm_sta_table data struct
+ *  @param rate    STA`s TX rate
+ *
+ *  @return N/A
+ */
+static void wlan_wmm_adjust_sta_tx_budget(pmlan_private priv,
+					  struct wmm_sta_table *sta,
+					  HostCmd_TX_RATE_QUERY *rate)
+{
+	const t_u8 ppdu_type_legacy = 0;
+	const t_u8 ppdu_type_ht = 1;
+	const t_u8 ppdu_type_vht = 2;
+	const t_u8 ppdu_type_he = 3;
+	t_u32 phy_rate = 0;
+	t_u8 nss = (rate->tx_rate >> 4) + 1;
+	t_u8 mcs = (rate->tx_rate) & 0x0f;
+	t_u8 ppdu_format = rate->tx_rate_info & 0x3;
+	t_u8 ppdu_bw = (rate->tx_rate_info >> 2) & 0x3;
+	t_u8 ru_size = (rate->ext_tx_rate_info >> 1) & 0x7;
+	t_u8 dcm = (rate->ext_tx_rate_info) & 0x1;
+	t_u8 gi = (rate->tx_rate_info >> 4) & 0x1;
+
+	gi |= (rate->tx_rate_info >> 6) & 0x02;
+
+	if (ppdu_format == ppdu_type_he)
+		phy_rate = wlam_wmm_get_he_rate(ppdu_bw, gi, nss, mcs);
+	else if (ppdu_format == ppdu_type_vht)
+		phy_rate = wlam_wmm_get_vht_rate(ppdu_bw, gi, nss, mcs);
+	else if (ppdu_format == ppdu_type_ht)
+		phy_rate = wlam_wmm_get_ht_rate(ppdu_bw, gi, rate->tx_rate);
+	else if (ppdu_format == ppdu_type_legacy)
+		phy_rate = wlam_wmm_get_legacy_rate(rate->tx_rate);
+
+	if (phy_rate > 0) {
+		const t_u32 old_phy_rate = sta->budget.phy_rate_kbps;
+		sta->budget.byte_budget_init = wlan_wmm_get_byte_budget(
+			sta->budget.time_budget_init_us, phy_rate);
+		sta->budget.phy_rate_kbps = phy_rate;
+
+		if (old_phy_rate / phy_rate >= 2 ||
+		    phy_rate / old_phy_rate >= 2) {
+			PRINTM(MWARN,
+			       "mclient: %pM rate jump %u -> %u, phy type %u\n",
+			       sta->ra, old_phy_rate, phy_rate, ppdu_format);
+		}
+	}
+
+	if (phy_rate == 0) {
+		PRINTM(MERROR,
+		       "mclient_error: invalid rate %u, tx_rate %u, nss %u, mcs %u, ppdu_format %u, ppdu_bw %u, gi %u, dcm %u, ru_size %u, budget %d sta %pM\n",
+		       phy_rate, rate->tx_rate, nss, mcs, ppdu_format, ppdu_bw,
+		       gi, dcm, ru_size, sta->budget.byte_budget_init, sta->ra);
+	}
+}
+
+/**
+ *  @brief The function is called when TX rate command response received
+ *
+ *  @param priv    Pointer to the pmlan_private driver data struct
+ *  @param mac     STA`s MAC
+ *  @param rate    STA`s TX rate
+ *
+ *  @return N/A
+ */
+void wlan_wmm_update_sta_tx_rate(pmlan_private priv, t_u8 *mac,
+				 HostCmd_TX_RATE_QUERY *rate)
+{
+	struct wmm_sta_table *sta = wlan_wmm_get_sta(priv, mac);
+
+	if (sta) {
+		priv->wmm.is_rate_update_pending = MFALSE;
+		wlan_wmm_adjust_sta_tx_budget(priv, sta, rate);
+	}
+}
+
+/**
+ *  @brief The function is called when PS state change event is received
+ *
+ *  @param priv    Pointer to the pmlan_private driver data struct
+ *  @param mac     STA`s MAC
+ *  @param sleep   NTRUE is STA is in IEEE PS mode
+ *
+ *  @return N/A
+ */
+void wlan_update_sta_ps_state(pmlan_private priv, t_u8 *mac, t_u8 sleep)
+{
+	mlan_adapter *pmadapter = priv->adapter;
+	struct wmm_sta_table *sta;
+	t_bool resume_sta = MFALSE;
+	mlan_callbacks *cbs = &pmadapter->callbacks;
+
+	cbs->moal_spin_lock(pmadapter->pmoal_handle,
+			    priv->wmm.ra_list_spinlock);
+
+	sta = wlan_wmm_get_sta(priv, mac);
+	if (sta) {
+		if (!sleep)
+			resume_sta = MTRUE;
+
+		if (sta->ps_sleep == sleep) {
+			PRINTM(MWARN,
+			       "mclient-err: %pM already in same state %u\n",
+			       sta->ra, sta->ps_sleep);
+		}
+
+		sta->ps_sleep = sleep;
+	}
+
+	cbs->moal_spin_unlock(pmadapter->pmoal_handle,
+			      priv->wmm.ra_list_spinlock);
+	if (resume_sta)
+		wlan_update_ralist_tx_pause(priv, mac, 0);
+}
diff --git a/mlan/mlan_wmm.h b/mlan/mlan_wmm.h
index 6e9dd12..7322133 100644
--- a/mlan/mlan_wmm.h
+++ b/mlan/mlan_wmm.h
@@ -251,4 +251,20 @@ extern mlan_status wlan_ret_wmm_queue_config(pmlan_private pmpriv,
 
 mlan_status wlan_wmm_cfg_ioctl(pmlan_adapter pmadapter,
 			       pmlan_ioctl_req pioctl_req);
+
+void wlan_wmm_update_sta_tx_rate(pmlan_private priv, t_u8 *mac,
+				 HostCmd_TX_RATE_QUERY *rate);
+
+void wlan_wmm_consume_byte_budget(raListTbl *ra_list, mlan_buffer *pmbuf);
+void wlan_wmm_consume_mpdu_budget(raListTbl *ra_list);
+
+static INLINE void wlan_advance_bss_on_pkt_push(pmlan_adapter pmadapter,
+						mlan_bssprio_tbl *bssprio_tbl)
+{
+	if (pmadapter->mclient_tx_supported)
+		return;
+
+	bssprio_tbl->bssprio_cur = bssprio_tbl->bssprio_cur->pnext;
+}
+
 #endif /* !_MLAN_WMM_H_ */
diff --git a/mlinux/mlan_decl.h b/mlinux/mlan_decl.h
index c55d7e0..d1367d6 100644
--- a/mlinux/mlan_decl.h
+++ b/mlinux/mlan_decl.h
@@ -206,6 +206,8 @@ typedef t_s32 t_sval;
 #define MLAN_RATE_INDEX_MCS4 4
 /** Rate index for MCS 7 */
 #define MLAN_RATE_INDEX_MCS7 7
+/** Rate index for MCS 8 */
+#define MLAN_RATE_INDEX_MCS8 8
 /** Rate index for MCS 9 */
 #define MLAN_RATE_INDEX_MCS9 9
 /** Rate index for MCS11 */
@@ -395,14 +397,17 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_TYPE_IW624 0x0b
 /** Black bird card type */
 #define CARD_TYPE_AW693 0x0c
-/** IW615 card type */
-#define CARD_TYPE_IW615 0x0d
+/** IW610 card type */
+#define CARD_TYPE_IW610 0x0d
 
 /** 9098 A0 reverion num */
 #define CHIP_9098_REV_A0 1
 #define CHIP_9098_REV_A1 2
 /** 9097 CHIP REV */
 #define CHIP_9097_REV_B0 1
+/** Blackbird reverion num */
+#define CHIP_AW693_REV_A0 1
+#define CHIP_AW693_REV_A1 2
 
 #define INTF_MASK 0xff
 #define CARD_TYPE_MASK 0xff
@@ -432,8 +437,8 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_TYPE_SDIW624 (CARD_TYPE_IW624 | (INTF_SD << 8))
 /** SD_IW624 card type */
 #define CARD_TYPE_SDAW693 (CARD_TYPE_AW693 | (INTF_SD << 8))
-/** SD_IW615 card type */
-#define CARD_TYPE_SDIW615 (CARD_TYPE_IW615 | (INTF_SD << 8))
+/** SD_IW610 card type */
+#define CARD_TYPE_SDIW610 (CARD_TYPE_IW610 | (INTF_SD << 8))
 
 #define IS_SD8887(ct) (CARD_TYPE_SD8887 == (ct))
 #define IS_SD8897(ct) (CARD_TYPE_SD8897 == (ct))
@@ -447,7 +452,7 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define IS_SD8801(ct) (CARD_TYPE_SD8801 == (ct))
 #define IS_SDIW624(ct) (CARD_TYPE_SDIW624 == (ct))
 #define IS_SDAW693(ct) (CARD_TYPE_SDAW693 == (ct))
-#define IS_SDIW615(ct) (CARD_TYPE_SDIW615 == (ct))
+#define IS_SDIW610(ct) (CARD_TYPE_SDIW610 == (ct))
 
 /** SD8887 Card */
 #define CARD_SD8887 "SD8887"
@@ -473,8 +478,8 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_SDIW624 "SDIW624"
 /** SDAW693 Card */
 #define CARD_SDAW693 "SDAW693"
-/** SDIW615 Card */
-#define CARD_SDIW615 "SDIW615"
+/** SDIW610 Card */
+#define CARD_SDIW610 "SDIW610"
 #endif
 
 #ifdef PCIE
@@ -533,8 +538,8 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_TYPE_USB9097 (CARD_TYPE_9097 | (INTF_USB << 8))
 /** USBIW624 card type */
 #define CARD_TYPE_USBIW624 (CARD_TYPE_IW624 | (INTF_USB << 8))
-/** USBIW615 card type */
-#define CARD_TYPE_USBIW615 (CARD_TYPE_IW615 | (INTF_USB << 8))
+/** USBIW610 card type */
+#define CARD_TYPE_USBIW610 (CARD_TYPE_IW610 | (INTF_USB << 8))
 
 #define IS_USB8801(ct) (CARD_TYPE_USB8801 == (ct))
 #define IS_USB8897(ct) (CARD_TYPE_USB8897 == (ct))
@@ -543,7 +548,7 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define IS_USB9098(ct) (CARD_TYPE_USB9098 == (ct))
 #define IS_USB9097(ct) (CARD_TYPE_USB9097 == (ct))
 #define IS_USBIW624(ct) (CARD_TYPE_USBIW624 == (ct))
-#define IS_USBIW615(ct) (CARD_TYPE_USBIW615 == (ct))
+#define IS_USBIW610(ct) (CARD_TYPE_USBIW610 == (ct))
 
 /** USB8801 Card */
 #define CARD_USB8801 "USB8801"
@@ -559,14 +564,15 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define CARD_USB9097 "USBIW620"
 /** USBIW624 Card */
 #define CARD_USBIW624 "USBIW624"
-/** USBIW615 Card */
-#define CARD_USBIW615 "USBIW615"
+/** USBIW610 Card */
+#define CARD_USBIW610 "USBIW610"
 #endif
 
 #define IS_CARD8801(ct) (CARD_TYPE_8801 == ((ct)&0xf))
 #define IS_CARD8887(ct) (CARD_TYPE_8887 == ((ct)&0xf))
 #define IS_CARD8897(ct) (CARD_TYPE_8897 == ((ct)&0xf))
 #define IS_CARD8977(ct) (CARD_TYPE_8977 == ((ct)&0xf))
+#define IS_CARD8978(ct) (CARD_TYPE_8978 == ((ct)&0xf))
 #define IS_CARD8997(ct) (CARD_TYPE_8997 == ((ct)&0xf))
 #define IS_CARD8987(ct) (CARD_TYPE_8987 == ((ct)&0xf))
 #define IS_CARD9098(ct) (CARD_TYPE_9098 == ((ct)&0xf))
@@ -574,7 +580,7 @@ typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH];
 #define IS_CARD9177(ct) (CARD_TYPE_9177 == ((ct)&0xf))
 #define IS_CARDIW624(ct) (CARD_TYPE_IW624 == ((ct)&0xf))
 #define IS_CARDAW693(ct) (CARD_TYPE_AW693 == ((ct)&0xf))
-#define IS_CARDIW615(ct) (CARD_TYPE_IW615 == ((ct)&0xf))
+#define IS_CARDIW610(ct) (CARD_TYPE_IW610 == ((ct)&0xf))
 
 typedef struct _card_type_entry {
 	t_u16 card_type;
@@ -648,6 +654,8 @@ typedef enum {
 
 #define MLAN_BUF_FLAG_MC_AGGR_PKT MBIT(17)
 
+#define MLAN_BUF_FLAG_TCP_PKT MBIT(18)
+
 #define MLAN_BUF_FLAG_LLDE_PKT_FILTER MBIT(19)
 
 #ifdef DEBUG_LEVEL1
@@ -660,8 +668,8 @@ typedef enum {
 #define MEVENT MBIT(5)
 #define MINTR MBIT(6)
 #define MIOCTL MBIT(7)
-
 #define MREG_D MBIT(9)
+#define MREG MBIT(10)
 
 #define MMPA_D MBIT(15)
 #define MDAT_D MBIT(16)
@@ -670,7 +678,7 @@ typedef enum {
 #define MFW_D MBIT(19)
 #define MIF_D MBIT(20)
 #define MFWDP_D MBIT(21)
-
+#define MSCH_D MBIT(22)
 #define MENTRY MBIT(28)
 #define MWARN MBIT(29)
 #define MINFO MBIT(30)
@@ -1630,7 +1638,7 @@ typedef MLAN_PACK_START struct _tdls_each_link_status {
 	/** Key Length */
 	t_u8 key_length;
 	/** actual key */
-	t_u8 key[1];
+	t_u8 key[];
 } MLAN_PACK_END tdls_each_link_status;
 
 /** TDLS configuration data */
@@ -1757,7 +1765,7 @@ typedef MLAN_PACK_START struct _tdls_all_config {
 			/** number of links */
 			t_u8 active_links;
 			/** structure for link status */
-			tdls_each_link_status link_stats[1];
+			tdls_each_link_status link_stats[];
 		} MLAN_PACK_END tdls_link_status_resp;
 
 	} u;
@@ -2596,6 +2604,7 @@ typedef struct _mlan_callbacks {
 				     t_u8 antenna);
 	t_void (*moal_updata_peer_signal)(t_void *pmoal, t_u32 bss_index,
 					  t_u8 *peer_addr, t_s8 snr, t_s8 nflr);
+	mlan_status (*moal_get_host_time_ns)(t_u64 *time);
 	t_u64 (*moal_do_div)(t_u64 num, t_u32 base);
 	void (*moal_tp_accounting)(t_void *pmoal, t_void *buf,
 				   t_u32 drop_point);
@@ -2694,6 +2703,8 @@ typedef struct _mlan_device {
 #endif
 	/** Auto deep sleep */
 	t_u32 auto_ds;
+	/** Boot Time Config */
+	t_u32 bootup_cal_ctrl;
 	/** IEEE PS mode */
 	t_u32 ps_mode;
 	/** Max Tx buffer size */
@@ -2745,6 +2756,8 @@ typedef struct _mlan_device {
 	t_u8 uap_max_sta;
 	/** wacp mode */
 	t_u8 wacp_mode;
+	/** custom Fw data */
+	t_u32 fw_data_cfg;
 	/** drv mode */
 	t_u32 drv_mode;
 	/** dfs w53 cfg */
@@ -2763,8 +2776,12 @@ typedef struct _mlan_device {
 	t_u32 antcfg;
 	/** dmcs */
 	t_u8 dmcs;
+	t_u8 pref_dbc;
 	t_u32 reject_addba_req;
 
+	t_u32 max_tx_pending;
+	t_u16 tx_budget;
+	t_u8 mclient_scheduling;
 } mlan_device, *pmlan_device;
 
 /** MLAN API function prototype */
diff --git a/mlinux/mlan_ieee.h b/mlinux/mlan_ieee.h
index c4cf1e8..30a9184 100644
--- a/mlinux/mlan_ieee.h
+++ b/mlinux/mlan_ieee.h
@@ -71,6 +71,9 @@ typedef enum _WLAN_802_11_NETWORK_TYPE {
 typedef enum _IEEEtypes_Ext_ElementId_e {
 	HE_CAPABILITY = 35,
 	HE_OPERATION = 36,
+	MU_EDCA_PARAM_SET = 38,
+	MBSSID_CONFIG = 55,
+	NON_INHERITANCE = 56,
 	HE_6G_CAPABILITY = 59
 } IEEEtypes_Ext_ElementId_e;
 
@@ -260,7 +263,7 @@ typedef MLAN_PACK_START struct _IEEEtypes_FastBssTransElement_t {
 	/** SNonce */
 	t_u8 s_nonce[32];
 	/** sub element */
-	t_u8 sub_element[1];
+	t_u8 sub_element[];
 } MLAN_PACK_END IEEEtypes_FastBssTransElement_t;
 
 /*Category for FT*/
@@ -547,7 +550,7 @@ typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t {
 	/** Association ID */
 	IEEEtypes_AId_t a_id;
 	/** IE data buffer */
-	t_u8 ie_buffer[1];
+	t_u8 ie_buffer[];
 } MLAN_PACK_END IEEEtypes_AssocRsp_t, *pIEEEtypes_AssocRsp_t;
 
 /** 802.11 supported rates */
@@ -985,7 +988,7 @@ typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoSet_t {
 	/** Country code */
 	t_u8 country_code[COUNTRY_CODE_LEN];
 	/** Set of subbands */
-	IEEEtypes_SubbandSet_t sub_band[1];
+	IEEEtypes_SubbandSet_t sub_band[];
 } MLAN_PACK_END IEEEtypes_CountryInfoSet_t, *pIEEEtypes_CountryInfoSet_t;
 
 /** Data structure for Country IE full set */
@@ -1151,6 +1154,18 @@ typedef MLAN_PACK_START struct _IEEEtypes_MultiBSSID_t {
 	/** Optional Subelement data*/
 	t_u8 sub_elem_data[];
 } MLAN_PACK_END IEEEtypes_MultiBSSID_t, *pIEEEtypes_MultiBSSID_t;
+
+/** Multi BSSID Configuration IE */
+typedef MLAN_PACK_START struct _IEEEtypes_MBSSID_Config_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Element id extension */
+	t_u8 ext_id;
+	/** BSSID Count */
+	t_u8 bssid_cnt;
+	/** Full Set Rx Periodicity */
+	t_u8 fs_rx_periodicity;
+} MLAN_PACK_END IEEEtypes_MBSSID_Config_t, *pIEEEtypes_MBSSID_Config_t;
 /** 20/40 BSS Coexistence IE */
 typedef MLAN_PACK_START struct _IEEEtypes_2040BSSCo_t {
 	/** Generic IE header */
@@ -1466,6 +1481,32 @@ typedef MLAN_PACK_START struct _IEEEtypes_HeOp_t {
 	t_u8 option[9];
 } MLAN_PACK_END IEEEtypes_HeOp_t;
 
+/** MU EDCA Parameter Set */
+typedef MLAN_PACK_START struct _IEEEtypes_MUEDCAParamSet_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** Extended Tag */
+	t_u8 ext_tag;
+	/** QOS Information */
+	t_u8 qos_info;
+	/** MUAC BE Paramter Record */
+	t_u8 muac_be[3];
+	/** MUAC BK Paramter Record */
+	t_u8 muac_bk[3];
+	/** MUAC VI Paramter Record */
+	t_u8 muac_vi[3];
+	/** MUAC VO Paramter Record */
+	t_u8 muac_vo[3];
+} MLAN_PACK_END IEEEtypes_MUEDCAParamSet_t, *pIEEEtypes_MUEDCAParamSet_t;
+
+/** IEEE format IE */
+typedef MLAN_PACK_START struct _IEEEtypes_Element_t {
+	/** Generic IE header */
+	IEEEtypes_Header_t ieee_hdr;
+	/** IE data */
+	t_u8 data[];
+} MLAN_PACK_END IEEEtypes_Element_t, *pIEEEtypes_Element_t;
+
 /** default channel switch count */
 #define DEF_CHAN_SWITCH_COUNT 5
 
@@ -2094,6 +2135,10 @@ typedef struct _BSSDescriptor_t {
 	t_u8 multi_bssid_ap;
 	/** the mac address of multi-bssid AP */
 	mlan_802_11_mac_addr multi_bssid_ap_addr;
+	/** Multi BSSID Configuration IE */
+	IEEEtypes_MBSSID_Config_t *pmbssid_config;
+	/** Multi BSSID Configuration IE offset */
+	t_u16 mbssid_config_offset;
 	/** 20/40 BSS Coexistence IE */
 	IEEEtypes_2040BSSCo_t *pbss_co_2040;
 	/** 20/40 BSS Coexistence Offset */
@@ -2174,7 +2219,10 @@ typedef struct _BSSDescriptor_t {
 	IEEEtypes_MobilityDomain_t *pmd_ie;
 	/** Mobility domain IE offset in the beacon buffer */
 	t_u16 md_offset;
-
+	/** MU EDCA Parameter IE */
+	IEEEtypes_MUEDCAParamSet_t *pmuedca_ie;
+	/** MU EDCA Parameter IE offset */
+	t_u16 muedca_offset;
 	/** Pointer to the returned scan response */
 	t_u8 *pbeacon_buf;
 	/** Length of the stored scan response */
diff --git a/mlinux/mlan_ioctl.h b/mlinux/mlan_ioctl.h
index bfb383f..38518c6 100644
--- a/mlinux/mlan_ioctl.h
+++ b/mlinux/mlan_ioctl.h
@@ -164,6 +164,7 @@ enum _mlan_ioctl_req_id {
 	MLAN_OID_PM_CFG_DEEP_SLEEP = 0x00090004,
 	MLAN_OID_PM_CFG_SLEEP_PD = 0x00090005,
 	MLAN_OID_PM_CFG_PS_CFG = 0x00090006,
+	MLAN_OID_PM_CFG_FW_WAKEUP_METHOD = 0x00090007,
 	MLAN_OID_PM_CFG_SLEEP_PARAMS = 0x00090008,
 #ifdef UAP_SUPPORT
 	MLAN_OID_PM_CFG_PS_MODE = 0x00090009,
@@ -375,6 +376,7 @@ enum _mlan_ioctl_req_id {
 	MLAN_OID_MISC_CROSS_CHIP_SYNCH = 0x0020008B,
 	MLAN_OID_MISC_RF_TEST_CONFIG_TRIGGER_FRAME = 0x0020008C,
 	MLAN_OID_MISC_OFDM_DESENSE_CFG = 0x0020008D,
+	MLAN_OID_MISC_TSP_CFG = 0x002008C,
 	MLAN_OID_MISC_REORDER_FLUSH_TIME = 0x0020008F,
 	MLAN_OID_MISC_NAV_MITIGATION = 0x00200090,
 	MLAN_OID_MISC_LED_CONFIG = 0x00200091,
@@ -383,6 +385,8 @@ enum _mlan_ioctl_req_id {
 	MLAN_OID_MISC_GPIO_CFG = 0x00200094,
 	MLAN_OID_MISC_REGION_POWER_CFG = 0x00200095,
 	MLAN_OID_MISC_OTP_MAC_RD_WR = 0x00200097,
+	MLAN_OID_MISC_OTP_CAL_DATA_RD_WR = 0x00200098,
+	MLAN_OID_MISC_AUTH_ASSOC_TIMEOUT_CONFIG = 0x00200099,
 };
 
 /** Sub command size */
@@ -519,7 +523,7 @@ typedef struct {
 	 * Buffer marker for multiple wlan_ioctl_get_scan_table_entry
 	 * structures. Each struct is padded to the nearest 32 bit boundary.
 	 */
-	t_u8 scan_table_entry_buf[1];
+	t_u8 scan_table_entry_buf[];
 } wlan_ioctl_get_scan_table_info;
 
 /**
@@ -576,7 +580,7 @@ typedef struct _mlan_user_scan {
 	/** Length of scan_cfg_buf */
 	t_u32 scan_cfg_len;
 	/** Buffer of scan config */
-	t_u8 scan_cfg_buf[1];
+	t_u8 scan_cfg_buf[];
 } mlan_user_scan, *pmlan_user_scan;
 
 /** Type definition of mlan_scan_req */
@@ -1763,6 +1767,8 @@ typedef struct _mlan_ds_get_stats {
 	t_u32 gdma_abort_cnt;
 	/** Rx Reset MAC Count */
 	t_u32 g_reset_rx_mac_cnt;
+	/** SDMA FSM stuck Count*/
+	t_u32 SdmaStuckCnt;
 	// Ownership error counters
 	/*Error Ownership error count*/
 	t_u32 dwCtlErrCnt;
@@ -3395,6 +3401,15 @@ typedef struct _mlan_ds_hs_wakeup_reason {
 	t_u16 hs_wakeup_reason;
 } mlan_ds_hs_wakeup_reason;
 
+/** Type definition of mlan_fw_wakeup_params for
+ * MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+typedef struct _mlan_fw_wakeup_params {
+	/** FW wakeup method */
+	t_u16 method;
+	/** GPIO pin NO.*/
+	t_u8 gpio_pin;
+} mlan_fw_wakeup_params, *pmlan_fw_wakeup_params;
+
 /** Type definition of mlan_ds_ps_cfg for MLAN_OID_PM_CFG_PS_CFG */
 typedef struct _mlan_ds_bcn_timeout {
 	/** Beacon miss timeout period window */
@@ -3425,6 +3440,8 @@ typedef struct _mlan_ds_pm_cfg {
 		t_u32 sleep_period;
 		/** PS configuration parameters for MLAN_OID_PM_CFG_PS_CFG */
 		mlan_ds_ps_cfg ps_cfg;
+		/** FW wakeup method for MLAN_OID_PM_CFG_FW_WAKEUP_METHOD */
+		mlan_fw_wakeup_params fw_wakeup_params;
 		/** PS configuration parameters for MLAN_OID_PM_CFG_SLEEP_PARAMS
 		 */
 		mlan_ds_sleep_params sleep_params;
@@ -4177,6 +4194,9 @@ typedef struct _mlan_ds_11ax_rutxpwr_cmd {
 	/** column,row are 3 for every subband table,however column are 7 for FC
 	 * and 6 for other SOCs */
 	t_u8 col;
+	/** row are 3 for every subband table,total row for MAC1 is 12 and MAC2
+	 * id 3 ( consider only 2G support */
+	t_u8 row;
 	/**ru tx data */
 	t_s8 rutxSubPwr[89];
 } mlan_ds_11ax_rutxpwr_cmd, *pmlan_ds_11ax_rutxpwr_cmd;
@@ -4264,6 +4284,8 @@ typedef struct MLAN_PACK_START _mlan_ds_twt_setup {
 	t_u16 twt_mantissa;
 	/** TWT Request Type, 0: REQUEST_TWT, 1: SUGGEST_TWT*/
 	t_u8 twt_request;
+	/** TWT link lost timeout threshold */
+	t_u16 bcnMiss_threshold;
 } MLAN_PACK_END mlan_ds_twt_setup, *pmlan_ds_twt_setup;
 
 /** Type definition of mlan_ds_twt_teardown for MLAN_OID_11AX_TWT_CFG */
@@ -4415,14 +4437,14 @@ enum _mlan_reg_type {
 	defined(PCIE9097) || defined(USB9097) || defined(SDIW624) ||           \
 	defined(SDAW693) || defined(PCIEAW693) || defined(PCIEIW624) ||        \
 	defined(USBIW624) || defined(SD9097) || defined(SD9177) ||             \
-	defined(SDIW615) || defined(USBIW615)
+	defined(SDIW610) || defined(USBIW610)
 	MLAN_REG_CIU = 8,
 #endif
 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
 	defined(PCIE9097) || defined(USB9097) || defined(SDIW624) ||           \
 	defined(SDAW693) || defined(PCIEAW693) || defined(PCIEIW624) ||        \
-	defined(USBIW624) || defined(SD9097) || defined(SDIW615) ||            \
-	defined(USBIW615)
+	defined(USBIW624) || defined(SD9097) || defined(SDIW610) ||            \
+	defined(USBIW610)
 	MLAN_REG_MAC2 = 0x81,
 	MLAN_REG_BBP2 = 0x82,
 	MLAN_REG_RF2 = 0x83,
@@ -5659,7 +5681,7 @@ typedef MLAN_PACK_START struct _mlan_ds_misc_tx_rx_histogram {
 	/** Size of Tx/Rx info */
 	t_u16 size;
 	/** Store Tx/Rx info */
-	t_u8 value[1];
+	t_u8 value[];
 } MLAN_PACK_END mlan_ds_misc_tx_rx_histogram;
 
 #define RX_PKT_INFO MBIT(1)
@@ -5917,6 +5939,7 @@ typedef struct _mlan_ds_misc_chan_trpc_cfg {
 #define MFG_CMD_CONFIG_MAC_HE_TB_TX 0x110A
 #define MFG_CMD_CONFIG_TRIGGER_FRAME 0x110C
 #define MFG_CMD_OTP_MAC_ADD 0x108C
+#define MFG_CMD_OTP_CAL_DATA 0x121A
 
 /** MFG CMD generic cfg */
 struct MLAN_PACK_START mfg_cmd_generic_cfg {
@@ -6227,6 +6250,24 @@ typedef MLAN_PACK_START struct _mfg_cmd_otp_mac_addr_rd_wr_t {
 	t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
 } MLAN_PACK_END mfg_cmd_otp_mac_addr_rd_wr_t;
 
+#define CAL_DATA_LEN 1400
+typedef MLAN_PACK_START struct _mfg_cmd_otp_cal_data_rd_wr_t {
+	/** MFG command code */
+	t_u32 mfg_cmd;
+	/** Action */
+	t_u16 action;
+	/** Device ID */
+	t_u16 device_id;
+	/** MFG Error code */
+	t_u32 error;
+	/** CAL Data write status */
+	t_u32 cal_data_status;
+	/** CAL Data Length*/
+	t_u32 cal_data_len;
+	/** Destination MAC Address */
+	t_u8 cal_data[CAL_DATA_LEN];
+} MLAN_PACK_END mfg_cmd_otp_cal_data_rd_wr_t;
+
 typedef struct _mlan_ds_misc_chnrgpwr_cfg {
 	/** length */
 	t_u16 length;
@@ -6244,6 +6285,22 @@ typedef struct _mlan_ds_misc_cfp_tbl {
 	chan_freq_power_t cfp_tbl[];
 } mlan_ds_misc_cfp_tbl;
 
+/** channel attribute */
+typedef struct _chan_attr {
+	/** channel number */
+	t_u8 channel;
+	/** channel flags */
+	t_u8 flags;
+} chan_attr_t;
+
+/** channel flags table */
+typedef struct _mlan_ds_chan_attr {
+	/** Data length */
+	t_u16 data_len;
+	/** Data */
+	chan_attr_t chan_attr[MLAN_MAX_CHANNEL_NUM];
+} MLAN_PACK_END mlan_ds_chan_attr;
+
 /** mlan_ds_mc_aggr_cfg for MLAN_OID_MISC_MC_AGGR_CFG */
 typedef struct _mlan_ds_mc_aggr_cfg {
 	/** action */
@@ -6301,6 +6358,33 @@ typedef struct _mlan_ds_cross_chip_synch {
 	t_u32 init_tsf_high;
 } mlan_ds_cross_chip_synch;
 
+#define MAX_RFUS 2
+#define MAX_PATHS 2
+typedef struct _mlan_ds_tsp_cfg {
+	/** TSP config action 0-GET, 1-SET */
+	t_u16 action;
+	/** TSP enable/disable tsp algothrim */
+	t_u16 enable;
+	/** TSP config power backoff */
+	t_s32 backoff;
+	/** TSP config high threshold */
+	t_s32 high_thrshld;
+	/** TSP config low threshold */
+	t_s32 low_thrshld;
+	/** TSP config DUTY_CYC_STEP */
+	t_s32 duty_cyc_step;
+	/** TSP config DUTY_CYC_MIN */
+	t_s32 duty_cyc_min;
+	/** TSP config HIGH_THRESHOLD_TEMP */
+	t_s32 high_thrshld_temp;
+	/** TSP config LOW_THRESHOLD_TEMP */
+	t_s32 low_thrshld_temp;
+	/** TSP CAU TSEN register */
+	t_s32 reg_cau_val;
+	/** TSP RFU registers */
+	t_s32 reg_rfu_temp[MAX_RFUS][MAX_PATHS];
+} MLAN_PACK_END mlan_ds_tsp_cfg;
+
 typedef struct _mlan_ds_reorder_flush_time {
 	/** AC BK/BE_flush time*/
 	t_u16 flush_time_ac_be_bk;
@@ -6322,6 +6406,36 @@ typedef struct _mlan_ds_ed_mac_cfg {
 	t_u32 ed_bitmap_txq_lock;
 } mlan_ds_ed_mac_cfg;
 
+/** valid range for mlan_ds_auth_assoc_timeout_cfg */
+#define AUTH_TIMEOUT_MIN 500
+#define AUTH_TIMEOUT_MAX 2400
+#define AUTH_RETRY_TIMEOUT_ACK_MIN 50
+#define AUTH_RETRY_TIMEOUT_ACK_MAX 300
+#define AUTH_RETRY_TIMEOUT_NO_ACK_MIN 40
+#define AUTH_RETRY_TIMEOUT_NO_ACK_MAX 80
+#define ASSOC_TIMEOUT_MIN 200
+#define ASSOC_TIMEOUT_MAX 1500
+#define REASSOC_TIMEOUT_MIN 100
+#define REASSOC_TIMEOUT_MAX 1500
+#define ASSOC_RETRY_TIMEOUT_MIN 50
+#define ASSOC_RETRY_TIMEOUT_MAX 150
+
+/** Auth Assoc timeout configuration parameters */
+typedef struct _mlan_ds_auth_assoc_timeout_cfg {
+	/** auth timeout */
+	t_u16 auth_timeout;
+	/** Auth retry timeout if received ack */
+	t_u16 auth_retry_timeout_if_ack;
+	/** Auth retry timeout if ack is not received */
+	t_u16 auth_retry_timeout_if_no_ack;
+	/** assoc timeout */
+	t_u16 assoc_timeout;
+	/** reassoc timeout */
+	t_u16 reassoc_timeout;
+	/** assoc/reassoc frame retry timeout if ack received */
+	t_u16 retry_timeout;
+} mlan_ds_auth_assoc_timeout_cfg;
+
 /** Type definition of mlan_ds_misc_cfg for MLAN_IOCTL_MISC_CFG */
 typedef struct _mlan_ds_misc_cfg {
 	/** Sub-command */
@@ -6469,6 +6583,7 @@ typedef struct _mlan_ds_misc_cfg {
 		mlan_ds_misc_cck_desense_cfg cck_desense_cfg;
 		mlan_ds_misc_chan_trpc_cfg trpc_cfg;
 		mlan_ds_misc_chnrgpwr_cfg rgchnpwr_cfg;
+		mlan_ds_chan_attr chan_attr_cfg;
 
 		mlan_ds_band_steer_cfg band_steer_cfg;
 		mlan_ds_beacon_stuck_param_cfg beacon_stuck_cfg;
@@ -6478,6 +6593,7 @@ typedef struct _mlan_ds_misc_cfg {
 		struct mfg_Cmd_HE_TBTx_t mfg_he_power;
 		mfg_Cmd_IEEEtypes_CtlBasicTrigHdr_t mfg_tx_trigger_config;
 		mfg_cmd_otp_mac_addr_rd_wr_t mfg_otp_mac_addr_rd_wr;
+		mfg_cmd_otp_cal_data_rd_wr_t mfg_otp_cal_data_rd_wr;
 		mlan_ds_misc_arb_cfg arb_cfg;
 		mlan_ds_misc_cfp_tbl cfp;
 		t_u8 range_ext_mode;
@@ -6493,12 +6609,32 @@ typedef struct _mlan_ds_misc_cfg {
 		t_u32 ips_ctrl;
 		mlan_ds_ch_load ch_load;
 		mlan_ds_cross_chip_synch cross_chip_synch;
+		mlan_ds_tsp_cfg tsp_cfg;
 		mlan_ds_reorder_flush_time flush_time;
 		mlan_ds_ed_mac_cfg edmac_cfg;
 		mlan_ds_gpio_cfg_ops gpio_cfg_ops;
+		mlan_ds_auth_assoc_timeout_cfg auth_assoc_cfg;
 	} param;
 } mlan_ds_misc_cfg, *pmlan_ds_misc_cfg;
 
+typedef struct _mlan_cfpinfo {
+	t_u8 nss : 2;
+	t_u8 is2g_present : 1;
+	t_u8 is5g_present : 1;
+	t_u8 is6g_present : 1;
+	t_u8 reserved : 3;
+	t_u8 rows_2g;
+	t_u8 cols_2g;
+	t_u8 rows_5g;
+	t_u8 cols_5g;
+	t_u8 rows_6g;
+	t_u8 cols_6g;
+	t_u8 region_code;
+	t_u8 environment;
+	t_u8 country_code[2];
+	t_u16 action;
+} mlan_cfpinfo;
+
 /** Hotspot status enable */
 #define HOTSPOT_ENABLED MBIT(0)
 /** Hotspot status disable */
diff --git a/mlinux/moal_cfg80211.c b/mlinux/moal_cfg80211.c
index a9a17ff..aee41d0 100644
--- a/mlinux/moal_cfg80211.c
+++ b/mlinux/moal_cfg80211.c
@@ -30,6 +30,10 @@
 /********************************************************
  *				Local Variables
  ********************************************************/
+
+/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */
+#define PACKET_ADDR4_POS (2 + 2 + 6 + 6 + 6 + 2)
+
 /** Supported rates to be advertised to the cfg80211 */
 static struct ieee80211_rate cfg80211_rates[] = {
 	{
@@ -82,54 +86,59 @@ static struct ieee80211_rate cfg80211_rates[] = {
 	},
 };
 
+/** Kernel picks the min of the register max power and the regulatory max.
+      So to register the max chip capability the default max power for all
+   channels is set to 23 dbm which is the max of the typical max tx pwr out
+   range among all chips*/
+
 /** Channel definitions for 2 GHz to be advertised to cfg80211 */
 static struct ieee80211_channel cfg80211_channels_2ghz[] = {
-	{.center_freq = 2412, .hw_value = 1, .max_power = 20},
-	{.center_freq = 2417, .hw_value = 2, .max_power = 20},
-	{.center_freq = 2422, .hw_value = 3, .max_power = 20},
-	{.center_freq = 2427, .hw_value = 4, .max_power = 20},
-	{.center_freq = 2432, .hw_value = 5, .max_power = 20},
-	{.center_freq = 2437, .hw_value = 6, .max_power = 20},
-	{.center_freq = 2442, .hw_value = 7, .max_power = 20},
-	{.center_freq = 2447, .hw_value = 8, .max_power = 20},
-	{.center_freq = 2452, .hw_value = 9, .max_power = 20},
-	{.center_freq = 2457, .hw_value = 10, .max_power = 20},
-	{.center_freq = 2462, .hw_value = 11, .max_power = 20},
-	{.center_freq = 2467, .hw_value = 12, .max_power = 20},
-	{.center_freq = 2472, .hw_value = 13, .max_power = 20},
-	{.center_freq = 2484, .hw_value = 14, .max_power = 20},
+	{.center_freq = 2412, .hw_value = 1, .max_power = 23},
+	{.center_freq = 2417, .hw_value = 2, .max_power = 23},
+	{.center_freq = 2422, .hw_value = 3, .max_power = 23},
+	{.center_freq = 2427, .hw_value = 4, .max_power = 23},
+	{.center_freq = 2432, .hw_value = 5, .max_power = 23},
+	{.center_freq = 2437, .hw_value = 6, .max_power = 23},
+	{.center_freq = 2442, .hw_value = 7, .max_power = 23},
+	{.center_freq = 2447, .hw_value = 8, .max_power = 23},
+	{.center_freq = 2452, .hw_value = 9, .max_power = 23},
+	{.center_freq = 2457, .hw_value = 10, .max_power = 23},
+	{.center_freq = 2462, .hw_value = 11, .max_power = 23},
+	{.center_freq = 2467, .hw_value = 12, .max_power = 23},
+	{.center_freq = 2472, .hw_value = 13, .max_power = 23},
+	{.center_freq = 2484, .hw_value = 14, .max_power = 23},
 };
 
 /** Channel definitions for 5 GHz to be advertised to cfg80211 */
 static struct ieee80211_channel cfg80211_channels_5ghz[] = {
-	{.center_freq = 5180, .hw_value = 36, .max_power = 20},
-	{.center_freq = 5200, .hw_value = 40, .max_power = 20},
-	{.center_freq = 5220, .hw_value = 44, .max_power = 20},
-	{.center_freq = 5240, .hw_value = 48, .max_power = 20},
-	{.center_freq = 5260, .hw_value = 52, .max_power = 20},
-	{.center_freq = 5280, .hw_value = 56, .max_power = 20},
-	{.center_freq = 5300, .hw_value = 60, .max_power = 20},
-	{.center_freq = 5320, .hw_value = 64, .max_power = 20},
-	{.center_freq = 5500, .hw_value = 100, .max_power = 20},
-	{.center_freq = 5520, .hw_value = 104, .max_power = 20},
-	{.center_freq = 5540, .hw_value = 108, .max_power = 20},
-	{.center_freq = 5560, .hw_value = 112, .max_power = 20},
-	{.center_freq = 5580, .hw_value = 116, .max_power = 20},
-	{.center_freq = 5600, .hw_value = 120, .max_power = 20},
-	{.center_freq = 5620, .hw_value = 124, .max_power = 20},
-	{.center_freq = 5640, .hw_value = 128, .max_power = 20},
-	{.center_freq = 5660, .hw_value = 132, .max_power = 20},
-	{.center_freq = 5680, .hw_value = 136, .max_power = 20},
-	{.center_freq = 5700, .hw_value = 140, .max_power = 20},
-	{.center_freq = 5720, .hw_value = 144, .max_power = 20},
-	{.center_freq = 5745, .hw_value = 149, .max_power = 20},
-	{.center_freq = 5765, .hw_value = 153, .max_power = 20},
-	{.center_freq = 5785, .hw_value = 157, .max_power = 20},
-	{.center_freq = 5805, .hw_value = 161, .max_power = 20},
-	{.center_freq = 5825, .hw_value = 165, .max_power = 20},
-	{.center_freq = 5845, .hw_value = 169, .max_power = 20},
-	{.center_freq = 5865, .hw_value = 173, .max_power = 20},
-	{.center_freq = 5885, .hw_value = 177, .max_power = 20},
+	{.center_freq = 5180, .hw_value = 36, .max_power = 23},
+	{.center_freq = 5200, .hw_value = 40, .max_power = 23},
+	{.center_freq = 5220, .hw_value = 44, .max_power = 23},
+	{.center_freq = 5240, .hw_value = 48, .max_power = 23},
+	{.center_freq = 5260, .hw_value = 52, .max_power = 23},
+	{.center_freq = 5280, .hw_value = 56, .max_power = 23},
+	{.center_freq = 5300, .hw_value = 60, .max_power = 23},
+	{.center_freq = 5320, .hw_value = 64, .max_power = 23},
+	{.center_freq = 5500, .hw_value = 100, .max_power = 23},
+	{.center_freq = 5520, .hw_value = 104, .max_power = 23},
+	{.center_freq = 5540, .hw_value = 108, .max_power = 23},
+	{.center_freq = 5560, .hw_value = 112, .max_power = 23},
+	{.center_freq = 5580, .hw_value = 116, .max_power = 23},
+	{.center_freq = 5600, .hw_value = 120, .max_power = 23},
+	{.center_freq = 5620, .hw_value = 124, .max_power = 23},
+	{.center_freq = 5640, .hw_value = 128, .max_power = 23},
+	{.center_freq = 5660, .hw_value = 132, .max_power = 23},
+	{.center_freq = 5680, .hw_value = 136, .max_power = 23},
+	{.center_freq = 5700, .hw_value = 140, .max_power = 23},
+	{.center_freq = 5720, .hw_value = 144, .max_power = 23},
+	{.center_freq = 5745, .hw_value = 149, .max_power = 23},
+	{.center_freq = 5765, .hw_value = 153, .max_power = 23},
+	{.center_freq = 5785, .hw_value = 157, .max_power = 23},
+	{.center_freq = 5805, .hw_value = 161, .max_power = 23},
+	{.center_freq = 5825, .hw_value = 165, .max_power = 23},
+	{.center_freq = 5845, .hw_value = 169, .max_power = 23},
+	{.center_freq = 5865, .hw_value = 173, .max_power = 23},
+	{.center_freq = 5885, .hw_value = 177, .max_power = 23},
 };
 
 struct ieee80211_supported_band cfg80211_band_2ghz = {
@@ -174,6 +183,10 @@ int woal_11ax_cfg(moal_private *priv, t_u8 action, mlan_ds_11ax_he_cfg *he_cfg,
 #endif
 #endif
 
+static t_u8 *woal_remove_11ax_ies(moal_private *priv, t_u8 *ie, t_u8 len,
+				  t_u8 *new_ie_len, t_u32 ie_out_len,
+				  t_u8 *skipped_len);
+
 /**
  * @brief Get the private structure from wiphy
  *
@@ -1137,6 +1150,10 @@ int woal_cfg80211_change_virtual_intf(struct wiphy *wiphy,
 	mlan_ioctl_req *req = NULL;
 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
 	t_u8 bss_role;
+#endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
+	moal_private *dfs_priv =
+		woal_get_priv_bss_type(priv->phandle, MLAN_BSS_TYPE_DFS);
 #endif
 	mlan_status status = MLAN_STATUS_SUCCESS;
 
@@ -1156,6 +1173,22 @@ int woal_cfg80211_change_virtual_intf(struct wiphy *wiphy,
 	 */
 	if (priv->wdev->iftype == NL80211_IFTYPE_AP &&
 	    type == NL80211_IFTYPE_STATION) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
+		if (dfs_priv && dfs_priv->radar_background) {
+			PRINTM(MMSG, "Cancel background radar detection\n");
+			woal_11h_cancel_chan_report_ioctl(dfs_priv,
+							  MOAL_IOCTL_WAIT);
+			dfs_priv->chan_rpt_pending = MFALSE;
+			dfs_priv->radar_background = MFALSE;
+			woal_update_channels_dfs_state(
+				dfs_priv, dfs_priv->chan_rpt_req.chanNum,
+				dfs_priv->chan_rpt_req.bandcfg.chanWidth,
+				DFS_USABLE);
+			memset(&dfs_priv->chan_rpt_req, 0,
+			       sizeof(mlan_ds_11h_chan_rep_req));
+			cfg80211_background_cac_abort(wiphy);
+		}
+#endif
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
 		if (priv->phandle->is_cac_timer_set &&
 		    priv->bss_index == priv->phandle->cac_bss_index) {
@@ -2685,6 +2718,10 @@ static int woal_mgmt_tx(moal_private *priv, const u8 *buf, size_t len,
 	t_u8 tx_seq_num = 0;
 	mlan_ioctl_req *ioctl_req = NULL;
 	mlan_ds_misc_cfg *misc = NULL;
+	t_u8 *new_ie = NULL;
+	t_u8 new_ie_len = 0;
+	t_u16 fc, type, stype;
+	t_u8 skipped_len = 0;
 
 	ENTER();
 
@@ -2695,7 +2732,32 @@ static int woal_mgmt_tx(moal_private *priv, const u8 *buf, size_t len,
 
 	/* pkt_type + tx_control */
 #define HEADER_SIZE 8
-	packet_len = (t_u16)(len + MLAN_MAC_ADDR_LENGTH);
+	if (!woal_secure_add(&len, MLAN_MAC_ADDR_LENGTH, &packet_len,
+			     TYPE_UINT16)) {
+		PRINTM(MERROR, "packet_len is invalid\n");
+	}
+
+	/* Remove 11ax IEs and reduce IE length if band support disabled
+	 * and assoc response includes 11ax IEs
+	 */
+	if (chan && ((chan->band == NL80211_BAND_2GHZ &&
+		      !(priv->phandle->fw_bands & BAND_GAX)) ||
+		     (chan->band == NL80211_BAND_5GHZ &&
+		      !(priv->phandle->fw_bands & BAND_AAX)))) {
+		fc = le16_to_cpu(((struct ieee80211_mgmt *)buf)->frame_control);
+		type = fc & IEEE80211_FCTL_FTYPE;
+		stype = fc & IEEE80211_FCTL_STYPE;
+		if ((type == IEEE80211_FTYPE_MGMT &&
+		     (stype == IEEE80211_STYPE_ASSOC_RESP ||
+		      stype == IEEE80211_STYPE_REASSOC_RESP))) {
+			new_ie = woal_remove_11ax_ies(priv, (t_u8 *)buf, len,
+						      &new_ie_len, MAX_IE_SIZE,
+						      &skipped_len);
+		}
+	}
+
+	if (new_ie && skipped_len)
+		packet_len -= skipped_len;
 
 	if (priv->phandle->cmd_tx_data) {
 		ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
@@ -2736,8 +2798,6 @@ static int woal_mgmt_tx(moal_private *priv, const u8 *buf, size_t len,
 	moal_memcpy_ext(priv->phandle, pbuf + sizeof(pkt_type), &tx_control,
 			sizeof(tx_control), remain_len);
 	remain_len -= sizeof(tx_control);
-	/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */
-#define PACKET_ADDR4_POS (2 + 2 + 6 + 6 + 6 + 2)
 	pkt_len = woal_cpu_to_le16(packet_len);
 	moal_memcpy_ext(priv->phandle, pbuf + HEADER_SIZE, &pkt_len,
 			sizeof(pkt_len), remain_len);
@@ -2750,11 +2810,22 @@ static int woal_mgmt_tx(moal_private *priv, const u8 *buf, size_t len,
 				PACKET_ADDR4_POS,
 			addr, MLAN_MAC_ADDR_LENGTH, remain_len);
 	remain_len -= MLAN_MAC_ADDR_LENGTH;
-	moal_memcpy_ext(priv->phandle,
-			pbuf + HEADER_SIZE + sizeof(packet_len) +
-				PACKET_ADDR4_POS + MLAN_MAC_ADDR_LENGTH,
-			buf + PACKET_ADDR4_POS, len - PACKET_ADDR4_POS,
-			remain_len);
+
+	if (!new_ie_len) {
+		// coverity[overrun:SUPPRESS]
+		moal_memcpy_ext(priv->phandle,
+				pbuf + HEADER_SIZE + sizeof(packet_len) +
+					PACKET_ADDR4_POS + MLAN_MAC_ADDR_LENGTH,
+				buf + PACKET_ADDR4_POS, len - PACKET_ADDR4_POS,
+				remain_len);
+	} else {
+		/* new IEs post cleanup of 11ax IEs received from kernel */
+		// coverity[overrun:SUPPRESS]
+		moal_memcpy_ext(priv->phandle,
+				pbuf + HEADER_SIZE + sizeof(packet_len) +
+					PACKET_ADDR4_POS + MLAN_MAC_ADDR_LENGTH,
+				new_ie, new_ie_len, remain_len);
+	}
 
 	DBG_HEXDUMP(MDAT_D, "Mgmt Tx", pbuf,
 		    HEADER_SIZE + packet_len + sizeof(packet_len));
@@ -2891,6 +2962,9 @@ done:
 		}
 	}
 
+	if (new_ie)
+		kfree(new_ie);
+
 	LEAVE();
 	return ret;
 }
@@ -3461,10 +3535,21 @@ done:
 int woal_cfg80211_set_qos_map(struct wiphy *wiphy, struct net_device *dev,
 			      struct cfg80211_qos_map *qos_map)
 {
-	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	moal_private *priv = NULL;
 	int i, j, ret = 0;
 
 	ENTER();
+	if (!dev) {
+		PRINTM(MERROR, "netdev pointer is NULL \n");
+		ret = -EINVAL;
+		goto done;
+	}
+	priv = (moal_private *)woal_get_netdev_priv(dev);
+	if (!priv) {
+		PRINTM(MERROR, "failed to retrieve netdev priv\n");
+		ret = -EINVAL;
+		goto done;
+	}
 	/**clear dscp map*/
 	if (!qos_map) {
 		memset(priv->dscp_map, 0xFF, sizeof(priv->dscp_map));
@@ -3501,7 +3586,7 @@ int woal_cfg80211_set_qos_map(struct wiphy *wiphy, struct net_device *dev,
 
 		qos_map_ie.ieee_hdr.element_id = QOS_MAPPING;
 		qos_map_ie.ieee_hdr.len =
-			2 * qos_map->num_des + sizeof(qos_map->up);
+			(t_u8)(2 * qos_map->num_des + sizeof(qos_map->up));
 		qos_map_ies_len =
 			qos_map_ie.ieee_hdr.len + sizeof(qos_map_ie.ieee_hdr);
 
@@ -3672,6 +3757,145 @@ static t_u8 woal_find_ie(const t_u8 *ie, int len, const t_u8 *spec_ie,
 	return MFALSE;
 }
 
+/*
+ * @brief  search for given IE
+ *
+ * @param ie             A pointer to IE
+ * @param ie_len         IE length
+ * @param eid            Element id to be searched
+ * @param ext_eid        Element extension id to be searched
+ *
+ * @return               true - success, false - otherwise
+ */
+static bool woal_search_ie(t_u8 *ie, t_u8 ie_len, t_u8 eid, t_u8 ext_eid)
+{
+	IEEEtypes_Header_t *pheader = NULL;
+	t_u8 *pos = NULL;
+	t_u8 ret_len = 0;
+	t_u8 ret = false;
+	t_u8 id = 0;
+
+	ENTER();
+
+	pos = (t_u8 *)ie;
+	ret_len = ie_len;
+	while (ret_len >= 2) {
+		pheader = (IEEEtypes_Header_t *)pos;
+		if ((t_u8)(pheader->len + sizeof(IEEEtypes_Header_t)) >
+		    ret_len) {
+			PRINTM(MMSG, "invalid IE length = %d left len %d\n",
+			       pheader->len, ret_len);
+			break;
+		}
+
+		if (ext_eid && pheader->element_id == ext_eid) {
+			id = *(pos + 2);
+			if (id == eid) {
+				ret = true;
+				break;
+			}
+		} else if (pheader->element_id == eid) {
+			ret = true;
+			break;
+		}
+
+		ret_len -= pheader->len + sizeof(IEEEtypes_Header_t);
+		pos += pheader->len + sizeof(IEEEtypes_Header_t);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/*
+ * @brief  remove 11ax IEs if band support is disabled
+ *
+ * @param priv           A pointer moal_private structure
+ * @param buf            Frame buffer
+ * @param len            Frame length
+ * @param new_ie         A pointer to newly generated IE
+ * @param new_ie_len     Length of newly generated IE
+ * @param skipped_len    Length of IEs removed
+ *
+ * @return               new ie buffer - success, NULL - otherwise
+ */
+static t_u8 *woal_remove_11ax_ies(moal_private *priv, t_u8 *ie, t_u8 len,
+				  t_u8 *new_ie_len, t_u32 ie_out_len,
+				  t_u8 *skipped_len)
+{
+	int left_len = 0;
+	const t_u8 *pos = NULL;
+	int length = 0;
+	t_u8 id = 0;
+	t_u8 ext_id = 0;
+
+	t_u8 *new_ie = NULL;
+	t_u8 min_ie_len = PACKET_ADDR4_POS + sizeof(IEEEtypes_CapInfo_t) +
+			  sizeof(IEEEtypes_StatusCode_t) +
+			  sizeof(IEEEtypes_AId_t);
+
+	/* search for 11ax IE in IE buffer */
+	if (!woal_search_ie(ie + min_ie_len, len - min_ie_len, HE_CAPABILITY,
+			    EXTENSION) &&
+	    !woal_search_ie(ie + min_ie_len, len - min_ie_len, HE_OPERATION,
+			    EXTENSION))
+		return NULL;
+
+	new_ie = kzalloc(len, GFP_KERNEL);
+	if (!new_ie) {
+		PRINTM(MERROR, "Failed to allocate memory for New IE\n");
+		return NULL;
+	}
+
+	/* copy fixed parameters of assoc response */
+	moal_memcpy_ext(priv->phandle, new_ie, ie + PACKET_ADDR4_POS,
+			sizeof(IEEEtypes_AssocRsp_t),
+			sizeof(IEEEtypes_AssocRsp_t));
+	*new_ie_len += sizeof(IEEEtypes_AssocRsp_t);
+
+	pos = ie + min_ie_len;
+	left_len = len - min_ie_len;
+
+	/* HE IE will be fileter out */
+	while (left_len >= 2) {
+		length = *(pos + 1);
+		id = *pos;
+
+		/* length exceeds remaining IE length */
+		if ((length + 2) > left_len)
+			break;
+
+		switch (id) {
+		case EXTENSION:
+			ext_id = *(pos + 2);
+			if (ext_id == HE_CAPABILITY || ext_id == HE_OPERATION ||
+			    ext_id == HE_6G_CAPABILITY) {
+				*skipped_len +=
+					length + sizeof(IEEEtypes_Header_t);
+				break;
+			}
+		// fall through
+		default:
+			if ((*new_ie_len + length + 2) < (int)ie_out_len) {
+				moal_memcpy_ext(priv->phandle,
+						new_ie + *new_ie_len, pos,
+						length + 2,
+						ie_out_len - *new_ie_len);
+				*new_ie_len += length + 2;
+			} else {
+				PRINTM(MERROR,
+				       "IE len exceeds, failed to copy %d IE\n",
+				       id);
+			}
+			break;
+		}
+		pos += (length + 2);
+		left_len -= (length + 2);
+	}
+
+	return new_ie;
+}
+
 /**
  * @brief Filter specific IE in ie buf
  *
@@ -3761,6 +3985,11 @@ static t_u16 woal_filter_beacon_ies(moal_private *priv, const t_u8 *ie,
 		case WAPI_IE:
 			break;
 		case EXTENSION:
+			/* skip 11ax, 6G if bands are not enabled */
+			if (!(priv->phandle->fw_bands & BAND_GAX) ||
+			    !(priv->phandle->fw_bands & BAND_AAX))
+				break;
+
 			ext_id = *(pos + 2);
 			if ((ext_id == HE_CAPABILITY || ext_id == HE_OPERATION)
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
@@ -3898,8 +4127,7 @@ static t_u16 woal_filter_beacon_ies(moal_private *priv, const t_u8 *ie,
 			}
 			break;
 		case REGULATORY_CLASS:
-			break;
-			// fall thru to default to add IE
+			/* FALLTHRU */
 		default:
 			if ((out_len + length + 2) < (int)ie_out_len) {
 				moal_memcpy_ext(priv->phandle, ie_out + out_len,
@@ -4729,8 +4957,12 @@ Note: bits not mentioned below are set to 0.
 ===
 HE MAC Cap:
 Bit0:  1  (+HTC HE Support)
+Bit1:	1 (TWT requester support)
+Bit2:	1 (TWT responder support)
+Bit20:	1 (Broadcast TWT support)
 Bit25: 1  (OM Control Support. But uAP does not support
 	   Tx OM received from the STA, as it does not support UL OFDMA)
+Bit28-27: Max. A-MPDU Length Exponent Extension
 
 HE PHY Cap:
 Bit1-7: 0x2 (Supported Channel Width Set.
@@ -4761,7 +4993,7 @@ Bit75: 0x1 (Rx 1024-QAM Support < 242-tone RU)
 #define UAP_HE_MAC_CAP0_MASK 0x06
 #define UAP_HE_MAC_CAP1_MASK 0x00
 #define UAP_HE_MAC_CAP2_MASK 0x10
-#define UAP_HE_MAC_CAP3_MASK 0x02
+#define UAP_HE_MAC_CAP3_MASK 0x1a
 #define UAP_HE_MAC_CAP4_MASK 0x00
 #define UAP_HE_MAC_CAP5_MASK 0x00
 #define UAP_HE_PHY_CAP0_MASK 0x04
@@ -4781,8 +5013,12 @@ Bit75: 0x1 (Rx 1024-QAM Support < 242-tone RU)
 ===
 HE MAC Cap:
 Bit0:   1  (+HTC HE Support)
+Bit1:	1 (TWT requester support)
+Bit2:	1 (TWT responder support)
+Bit20:	1 (Broadcast TWT support)
 Bit25: 1  (OM Control Support. Note: uAP does not support
 	Tx OM received from the STA, as it does not support UL OFDMA)
+Bit28-27: Max. A-MPDU Length Exponent Extension
 
 HE PHY Cap:
 Bit1-7: 0x1 (Supported Channel Width Set)
@@ -4807,10 +5043,10 @@ Bit58: 0x1 (HE SU PPDU and HE MU PPDU with 4xHE-LTF+0.8usGI)
 Bit59-61: 0x1 (Max Nc)
 Bit75: 0x1 (Rx 1024-QAM Support < 242-tone RU)
 */
-#define UAP_HE_2G_MAC_CAP0_MASK 0x00
+#define UAP_HE_2G_MAC_CAP0_MASK 0x06
 #define UAP_HE_2G_MAC_CAP1_MASK 0x00
-#define UAP_HE_2G_MAC_CAP2_MASK 0x00
-#define UAP_HE_2G_MAC_CAP3_MASK 0x02
+#define UAP_HE_2G_MAC_CAP2_MASK 0x10
+#define UAP_HE_2G_MAC_CAP3_MASK 0x1a
 #define UAP_HE_2G_MAC_CAP4_MASK 0x00
 #define UAP_HE_2G_MAC_CAP5_MASK 0x00
 #define UAP_HE_2G_PHY_CAP0_MASK 0x02
@@ -4892,16 +5128,17 @@ void woal_cfg80211_setup_he_cap(moal_private *priv,
 	t_u8 extra_mcs_size = 0;
 	int ppe_threshold_len = 0;
 	mlan_ds_11ax_he_capa *phe_cap = NULL;
-	t_u8 hw_hecap_len;
+	t_u8 hw_hecap_len = 0;
 
 	memset(&fw_info, 0, sizeof(mlan_fw_info));
 
 	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
-	if (band->band == NL80211_BAND_5GHZ) {
+	if (band->band == NL80211_BAND_5GHZ && fw_info.fw_bands & BAND_AAX) {
 		phe_cap = (mlan_ds_11ax_he_capa *)fw_info.hw_he_cap;
 		hw_hecap_len = fw_info.hw_hecap_len;
 		woal_uap_update_11ax_ie(BAND_5GHZ, phe_cap);
-	} else {
+	} else if (band->band == NL80211_BAND_2GHZ &&
+		   fw_info.fw_bands & BAND_GAX) {
 		phe_cap = (mlan_ds_11ax_he_capa *)fw_info.hw_2g_he_cap;
 		hw_hecap_len = fw_info.hw_2g_hecap_len;
 		woal_uap_update_11ax_ie(BAND_2GHZ, phe_cap);
diff --git a/mlinux/moal_cfg80211.h b/mlinux/moal_cfg80211.h
index 29a7674..06268e6 100644
--- a/mlinux/moal_cfg80211.h
+++ b/mlinux/moal_cfg80211.h
@@ -110,6 +110,8 @@ void woal_host_mlme_disconnect(pmoal_private priv, u16 reason_code, u8 *sa);
 void woal_host_mlme_work_queue(struct work_struct *work);
 void woal_host_mlme_process_assoc_resp(moal_private *priv,
 				       mlan_ds_assoc_info *assoc_info);
+void woal_host_mlme_process_assoc_timeout(moal_private *priv,
+					  struct cfg80211_bss *bss);
 #endif
 #endif
 
diff --git a/mlinux/moal_cfg80211_util.c b/mlinux/moal_cfg80211_util.c
index d181f60..f485aa2 100644
--- a/mlinux/moal_cfg80211_util.c
+++ b/mlinux/moal_cfg80211_util.c
@@ -2890,6 +2890,659 @@ int woal_deinit_wifi_hal(moal_private *priv)
 	return 0;
 }
 
+/**
+ * @brief Prints the scancfg params from the mlan_ds_scan struct
+ *
+ * @param scan	A pointer to mlan_ds_scan struct
+ *
+ * @return      void
+ */
+static void woal_print_scancfg_params(mlan_ds_scan *scan)
+{
+	if (!scan)
+		return;
+	PRINTM(MCMND,
+	       "scancfg params: scan_type = 0x%x, scan_mode = 0x%x, scan_probe = 0x%x \n",
+	       scan->param.scan_cfg.scan_type, scan->param.scan_cfg.scan_mode,
+	       scan->param.scan_cfg.scan_probe);
+
+	PRINTM(MCMND, "scancfg params: passive_to_active_scan = 0x%x \n",
+	       scan->param.scan_cfg.passive_to_active_scan);
+
+	PRINTM(MCMND,
+	       "scancfg params: specific_scan_time = 0x%x, active_scan_time = 0x%x, passive_scan_time = 0x%x \n",
+	       scan->param.scan_cfg.scan_time.specific_scan_time,
+	       scan->param.scan_cfg.scan_time.active_scan_time,
+	       scan->param.scan_cfg.scan_time.passive_scan_time);
+
+	PRINTM(MCMND, "scancfg params: ext_scan = 0x%x\n",
+	       scan->param.scan_cfg.ext_scan);
+	PRINTM(MCMND, "scancfg params: scan_chan_gap = 0x%x\n",
+	       scan->param.scan_cfg.scan_chan_gap);
+}
+
+/**
+ * @brief Parse the vendor cmd input data based on attribute len
+ * 	  and copy each attrubute into a output buffer/integer array
+ *
+ * @param data			A pointer to input data buffer
+ * @param data_len		Input data buffer total len
+ * @param user_buff		A pointer to output data buffer after the
+ * parsing
+ * @param buff_len		Maximum no. of data attributes to be parsed
+ * @param user_data_len		No. of data attributes that are parsed
+ *
+ * @return      0: success  -1: fail
+ */
+static int woal_parse_vendor_cmd_attributes(t_u8 *data, t_u32 data_len,
+					    t_u32 *user_buff, t_u32 buff_len,
+					    t_u16 *user_data_len)
+{
+	t_u16 i = 0, j = 0, len = 0;
+
+	len = strlen(data);
+	for (i = 0, j = 0; (i < data_len) && (j < buff_len); ++j) {
+		t_u32 value = 0, value1 = 0;
+		t_u8 attr_len = 0;
+		attr_len = (t_u8) * (data + i);
+		++i;
+		if (attr_len > 0) {
+			t_u8 k = 0;
+			for (k = 0; k < attr_len; ++k) {
+				value1 = (t_u8) * (data + i + k);
+				value = (value << 8) + value1;
+			}
+			i = i + k;
+		} else {
+			PRINTM(MERROR, "\nIn parse_args: Invalid attr_len \n");
+			*user_data_len = 0;
+			return -1;
+		}
+		user_buff[j] = value;
+	}
+	*user_data_len = j;
+	return 0;
+}
+
+/**
+ * @brief Vendor cmd to trigger the scancfg params.
+ *	Set/Get the scancfg params to/from driver
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  -1: fail
+ */
+static int woal_cfg80211_subcmd_set_get_scancfg(struct wiphy *wiphy,
+						struct wireless_dev *wdev,
+						const void *data, int len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_ds_scan *scan = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	t_s32 user_data[9];
+	t_s32 ret = 0;
+	t_u16 user_data_len = 0;
+	t_u16 ret_length = 1;
+	t_u8 get_data = 0, get_val = 0;
+	t_u8 *data_buff = (t_u8 *)data;
+	t_u8 *pos = NULL;
+	ENTER();
+
+	if (len < 1) {
+		PRINTM(MERROR, "vendor cmd: scancfg - Invalid data length!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (len == 1) {
+		PRINTM(MMSG, "vendor cmd: Get scancfg params!\n");
+		get_val = (t_u8) * (data_buff);
+
+		/* Get scancfg works if an input argument passed is 00 */
+		if (get_val) {
+			PRINTM(MERROR,
+			       "vendor cmd: Get scancfg failed due to Invalid argument!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		get_data = 1;
+	} else if (len > 1) {
+		PRINTM(MMSG, "Vendor cmd: Set scancfg params!\n");
+		memset((char *)user_data, 0, sizeof(user_data));
+
+		/* vendor cmd : the user_data_len is set only for set cmd */
+		if (woal_parse_vendor_cmd_attributes(data_buff, len, user_data,
+						     ARRAY_SIZE(user_data),
+						     &user_data_len)) {
+			PRINTM(MMSG,
+			       "vendor cmd: Couldn't parse the scancfg params!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
+	if (req == NULL) {
+		PRINTM(MERROR,
+		       "vendor cmd: Could not allocate mlan ioctl request, scancfg!\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	scan = (mlan_ds_scan *)req->pbuf;
+	scan->sub_command = MLAN_OID_SCAN_CONFIG;
+	req->req_id = MLAN_IOCTL_SCAN;
+
+	/* Validate each scancfg parameters */
+	if (user_data_len) {
+		DBG_HEXDUMP(MCMD_D, "scancfg input dump: ", (t_u8 *)user_data,
+			    (user_data_len * sizeof(t_u32)));
+		moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, user_data,
+				sizeof(user_data),
+				sizeof(scan->param.scan_cfg));
+		if (scan->param.scan_cfg.scan_type > MLAN_SCAN_TYPE_PASSIVE) {
+			PRINTM(MERROR,
+			       "vendor cmd:Invalid argument for scan type\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (scan->param.scan_cfg.scan_mode > MLAN_SCAN_MODE_ANY) {
+			PRINTM(MERROR,
+			       "vendor cmd:Invalid argument for scan mode\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (scan->param.scan_cfg.scan_probe > MAX_PROBES) {
+			PRINTM(MERROR,
+			       "vendor cmd:Invalid argument for scan probes\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if ((scan->param.scan_cfg.scan_time.specific_scan_time >
+		     MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME) ||
+		    (scan->param.scan_cfg.scan_time.active_scan_time >
+		     MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME) ||
+		    (scan->param.scan_cfg.scan_time.passive_scan_time >
+		     MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME)) {
+			PRINTM(MERROR, "Invalid argument for scan time\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (scan->param.scan_cfg.passive_to_active_scan >
+		    MLAN_PASS_TO_ACT_SCAN_DIS) {
+			PRINTM(MERROR,
+			       "Invalid argument for Passive to Active Scan\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (scan->param.scan_cfg.ext_scan > MLAN_EXT_SCAN_ENH) {
+			PRINTM(MERROR, "Invalid argument for extended scan\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (scan->param.scan_cfg.scan_chan_gap >
+		    MRVDRV_MAX_SCAN_CHAN_GAP_TIME) {
+			PRINTM(MERROR,
+			       "Invalid argument for scan channel gap\n");
+			ret = -EINVAL;
+			goto done;
+		}
+
+		req->action = MLAN_ACT_SET;
+		if (scan->param.scan_cfg.scan_time.specific_scan_time)
+			priv->phandle->user_scan_cfg = MTRUE;
+		PRINTM(MINFO, "vendor cmd: SET ioctl request for scanfg\n");
+		woal_print_scancfg_params(scan);
+	} else {
+		PRINTM(MINFO, "vendor cmd: GET ioctl request for scanfg\n");
+		req->action = MLAN_ACT_GET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		PRINTM(MMSG, "Set/Get scancfg ioctl successfull\n");
+		if (!user_data_len) {
+			moal_memcpy_ext(priv->phandle, user_data,
+					&scan->param.scan_cfg,
+					sizeof(scan->param.scan_cfg),
+					sizeof(user_data));
+			DBG_HEXDUMP(MCMD_D, "scancfg dump: ", (t_u8 *)user_data,
+				    sizeof(user_data));
+			ret_length = sizeof(mlan_scan_cfg);
+		}
+	} else {
+		PRINTM(MERROR, "Set/Get scancfg ioctl failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, ret_length);
+	if (!skb) {
+		PRINTM(MERROR,
+		       "vendor cmd: allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	/* Get scancfg if an input argument passed is 00 */
+	if (!user_data_len && get_data == 1) {
+		PRINTM(MINFO, "vendor cmd: copying the response into buffer\n");
+		scan = (mlan_ds_scan *)req->pbuf;
+		pos = skb_put(skb, sizeof(mlan_scan_cfg));
+		moal_memcpy_ext(priv->phandle, pos, &scan->param.scan_cfg,
+				sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
+		woal_print_scancfg_params(scan);
+	}
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(ret))
+		PRINTM(MERROR, "vendor cmd: reply failed with ret:%d \n", ret);
+
+done:
+	if (status != MLAN_STATUS_PENDING && req)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
+/*
+ * @brief A common function copies an user data(from integer array) into
+ * different types of structures. Declare a layout based on each member size of
+ * a strucure within the caller().
+ *
+ * @param phandle		A pointer to moal handler
+ * @param dest_struct		Final destination strucuture
+ * @param src_data		A pointer to input user data/integer array
+ * @param src_data_len		Input user data length
+ * @param dest_struct_len	Destination data structure length
+ * @param layout		A pointer to integer array/layout describing struct
+ * member
+ * *
+ * @return      0: success  -1: fail
+ * */
+static void
+woal_memcpy_user_intarray_to_struct(moal_handle *phandle, void *dest_struct,
+				    t_u32 *src_data, t_u32 src_data_len,
+				    t_u32 dest_struct_len, t_u32 *layout)
+{
+	t_u8 *dest = (t_u8 *)dest_struct;
+	t_u16 i = 0;
+
+	if (!dest_struct || !src_data) {
+		PRINTM(MERROR, "dest/src pointer is null\n");
+	}
+
+	for (i = 0; (layout[i] > 0 && i < src_data_len); ++i) {
+		moal_memcpy_ext(phandle, dest, src_data, layout[i], layout[i]);
+		dest += layout[i];
+		if (layout[i] > sizeof(t_u32)) {
+			src_data += layout[i] / sizeof(t_u32);
+			src_data += (layout[i] % sizeof(t_u32)) ? 1 : 0;
+		} else
+			src_data += 1;
+	}
+}
+
+/*
+ * @brief A common function directly copies different type of structures into
+ * user data buffer(integere array). Declare a layout based on each member size
+ * of a strucure within the caller function.
+ *
+ * @param phandle		A pointer to moal handler
+ * @param dest_data		A pointer to destination data buffer/integer
+ * array
+ * @param src_struct		A pointer to source structure
+ * @param src_struct_len	Source data structure length
+ * @param dest_data_len		Destination user data length
+ * @param layout		A pointer to integer array/layout describing struct
+ * member
+ * *
+ * @return      0: success  -1: fail
+ * */
+static void
+woal_memcpy_struct_to_user_intarray(moal_handle *phandle, t_u32 *dest_data,
+				    void *src_struct, t_u32 src_struct_len,
+				    t_u32 dest_data_len, t_u32 *layout)
+{
+	t_u8 *src = (t_u8 *)src_struct;
+	t_u16 i = 0;
+
+	if (!dest_data || !src_struct) {
+		PRINTM(MERROR, "dest/src pointer is null\n");
+	}
+
+	for (i = 0; (layout[i] > 0 && i < dest_data_len); ++i) {
+		moal_memcpy_ext(phandle, dest_data, src, layout[i], layout[i]);
+		src += layout[i];
+		if (layout[i] > sizeof(t_u32)) {
+			dest_data += layout[i] / sizeof(t_u32);
+			dest_data += (layout[i] % sizeof(t_u32)) ? 1 : 0;
+		} else
+			dest_data += 1;
+	}
+}
+
+/**
+ * @brief Prints the addba params from the woal_print_addba_param
+ *
+ * @param scan	A pointer to woal_print_addba_param struct
+ *
+ * @return      void
+ */
+static void woal_print_addba_params(mlan_ds_11n_addba_param *addba)
+{
+	if (!addba) {
+		PRINTM(MERROR, "addba param is null\n");
+		return;
+	}
+
+	PRINTM(MCMND,
+	       "ADDBA: timeout:%d txwinsize:%d rxwinsize:%d txamsdu=%d, rxamsdu=%d\n",
+	       addba->timeout, addba->txwinsize, addba->rxwinsize,
+	       addba->txamsdu, addba->rxamsdu);
+	return;
+}
+
+/**
+ * @brief API to trigger the addba params.
+ *	It sets or gets the addba params
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  -1: fail
+ */
+static int woal_cfg80211_subcmd_set_get_addbaparams(struct wiphy *wiphy,
+						    struct wireless_dev *wdev,
+						    const void *data, int len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_ds_11n_cfg *cfg_addba = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	t_u32 user_data[5];
+	/* Define layout as per required structure */
+	t_u32 layout[5] = {sizeof(t_u32), sizeof(t_u32), sizeof(t_u32),
+			   sizeof(char), sizeof(char)};
+	t_s32 ret = 0;
+	t_u16 user_data_len = 0;
+	t_u16 ret_length = 1;
+	t_u8 get_data = 0, get_val = 0;
+	t_u8 *data_buff = (t_u8 *)data;
+	t_u8 *pos = NULL;
+	ENTER();
+
+	if (len < 1) {
+		PRINTM(MERROR,
+		       "vendor cmd: addbaparams - Invalid data length!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (len == 1) {
+		PRINTM(MMSG, "vendor cmd: Get addbaparams!\n");
+		get_val = (t_u8) * (data_buff);
+
+		/* Get addbaparams works if an input argument passed is 00 */
+		if (get_val) {
+			PRINTM(MERROR,
+			       "vendor cmd: Get addbaparams failed due to Invalid argument!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		get_data = 1;
+		memset((char *)user_data, 0, sizeof(user_data));
+	} else if (len > 1) {
+		PRINTM(MMSG, "Vendor cmd: Set addbaparams !\n");
+		memset((char *)user_data, 0, sizeof(user_data));
+
+		/* vendor cmd : the user_data_len is set only for set cmd */
+		if (woal_parse_vendor_cmd_attributes(data_buff, len, user_data,
+						     ARRAY_SIZE(user_data),
+						     &user_data_len)) {
+			PRINTM(MERROR,
+			       "vendor cmd: Couldn't parse the addbaparams!\n");
+			ret = -EINVAL;
+			goto done;
+		}
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
+	if (req == NULL) {
+		PRINTM(MERROR,
+		       "vendor cmd: Could not allocate mlan ioctl request, addbaparams!\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	cfg_addba = (mlan_ds_11n_cfg *)req->pbuf;
+	cfg_addba->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
+	req->req_id = MLAN_IOCTL_11N_CFG;
+
+	/* Validate each addbaparams parameters */
+	if (user_data_len) {
+		DBG_HEXDUMP(MCMD_D,
+			    "addbaparams input dump: ", (t_u8 *)user_data,
+			    (user_data_len * sizeof(t_u32)));
+		/* To copy an user data in an integer array format into strcture
+		 */
+		woal_memcpy_user_intarray_to_struct(
+			priv->phandle, (void *)&cfg_addba->param.addba_param,
+			user_data, ARRAY_SIZE(user_data),
+			sizeof(cfg_addba->param.addba_param), layout);
+
+		woal_print_addba_params(&cfg_addba->param.addba_param);
+		if (cfg_addba->param.addba_param.timeout >
+		    MLAN_DEFAULT_BLOCK_ACK_TIMEOUT) {
+			PRINTM(MERROR, "Incorrect addba timeout value.\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (cfg_addba->param.addba_param.txwinsize >
+		    MLAN_AMPDU_MAX_TXWINSIZE) {
+			PRINTM(MERROR, "Incorrect Tx window size.\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (cfg_addba->param.addba_param.rxwinsize >
+		    MLAN_AMPDU_MAX_RXWINSIZE) {
+			PRINTM(MERROR, "Incorrect Rx window size.\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (cfg_addba->param.addba_param.txamsdu > 1 ||
+		    cfg_addba->param.addba_param.rxamsdu > 1) {
+			PRINTM(MERROR, "Incorrect Tx/Rx amsdu.\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		req->action = MLAN_ACT_SET;
+		PRINTM(MINFO,
+		       "vendor cmd: SET ioctl request for addbaparams\n");
+	} else {
+		PRINTM(MINFO,
+		       "vendor cmd: GET ioctl request for addbaparams\n");
+		req->action = MLAN_ACT_GET;
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		PRINTM(MMSG, "Set/Get addbaparams ioctl successfull\n");
+		if (!user_data_len) {
+			/* To copy an strcture members into user data/integer
+			 * array separately */
+			woal_memcpy_struct_to_user_intarray(
+				priv->phandle, user_data,
+				(void *)&cfg_addba->param.addba_param,
+				sizeof(cfg_addba->param.addba_param),
+				ARRAY_SIZE(user_data), layout);
+			woal_print_addba_params(&cfg_addba->param.addba_param);
+			ret_length = sizeof(user_data);
+		}
+	} else {
+		PRINTM(MERROR, "Set/Get addbaparams ioctl failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, ret_length);
+	if (!skb) {
+		PRINTM(MERROR,
+		       "vendor cmd: allocate memory fail for vendor cmd\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Get addbaparams if an input data argument is 00 */
+	if (!user_data_len && get_data == 1) {
+		PRINTM(MINFO, "vendor cmd: copying the response into buffer\n");
+		DBG_HEXDUMP(MCMD_D, "addbaparams dump: ", (t_u8 *)user_data,
+			    sizeof(user_data));
+		cfg_addba = (mlan_ds_11n_cfg *)req->pbuf;
+		pos = skb_put(skb, sizeof(user_data));
+		moal_memcpy_ext(priv->phandle, pos, user_data,
+				sizeof(user_data), sizeof(user_data));
+	}
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(ret))
+		PRINTM(MERROR, "vendor cmd: reply failed with ret:%d \n", ret);
+
+done:
+	if (status != MLAN_STATUS_PENDING && req)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
+/**
+ * @brief API to trigger the vendor cmd related to
+ * hostcmd/sys_cfg_80211d_country_ie. It sets/get/clear the function/operation
+ * that is specific the hostcmd.
+ *
+ * @param wiphy    A pointer to wiphy struct
+ * @param wdev     A pointer to wireless_dev struct
+ * @param data     a pointer to data
+ * @param  len     data length
+ *
+ * @return      0: success  -1: fail
+ */
+static int woal_cfg80211_subcmd_hostcmd(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len)
+{
+	struct net_device *dev = wdev->netdev;
+	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	struct sk_buff *skb = NULL;
+	HostCmd_DS_GEN cmd_info;
+	t_s32 ret = 0;
+	t_u16 ret_length = 1;
+	t_u16 action = 0;
+	t_u8 get_data = 0;
+	t_u8 *data_buff = (t_u8 *)data;
+	t_u8 *pos = NULL;
+	ENTER();
+
+	if (len < (sizeof(HostCmd_DS_GEN) + sizeof(action))) {
+		PRINTM(MERROR, "vendor cmd: Invalid hostcmd!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	moal_memcpy_ext(priv->phandle, &cmd_info, data_buff,
+			sizeof(HostCmd_DS_GEN), sizeof(HostCmd_DS_GEN));
+	action = (u16) * (data_buff + sizeof(cmd_info));
+
+	PRINTM(MMSG, "vendor cmd: hostcmd len=%d, action=%d\n", len, action);
+	if (action == 0)
+		get_data = 1;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		PRINTM(MERROR,
+		       "vendor cmd: Could not allocate mlan ioctl memory, hostcmd!\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misc_cfg->sub_command = MLAN_OID_MISC_HOST_CMD;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	req->action = action;
+	misc_cfg->param.hostcmd.len = woal_le16_to_cpu(cmd_info.size);
+
+	/* Copy the entire command data into hostcmd cmd buffer */
+	moal_memcpy_ext(priv->phandle, misc_cfg->param.hostcmd.cmd, data_buff,
+			misc_cfg->param.hostcmd.len, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	DBG_HEXDUMP(MCMD_D, "vendor cmd: hostcmd cmd dump",
+		    (t_u8 *)misc_cfg->param.hostcmd.cmd,
+		    misc_cfg->param.hostcmd.len);
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status == MLAN_STATUS_SUCCESS) {
+		PRINTM(MMSG, "Set/Clear/Get hostcmd ioctl successfull\n");
+		if (get_data) {
+			ret_length = misc_cfg->param.hostcmd.len;
+			PRINTM(MMSG, "vendor cmd: hostcmd GET, len=%d\n",
+			       ret_length);
+		}
+	} else {
+		PRINTM(MERROR, "Set/Clear/Get hostcmd ioctl failed!\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Allocate skb for cmd reply*/
+	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, ret_length);
+	if (!skb) {
+		PRINTM(MERROR, "vendor cmd: memory allocation failed \n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (get_data && ret_length > 1) {
+		PRINTM(MINFO, "vendor cmd: copying the response into buffer\n");
+		DBG_HEXDUMP(MCMD_D, "vendor cmd: hostcmd dump",
+			    (t_u8 *)misc_cfg->param.hostcmd.cmd, ret_length);
+		pos = skb_put(skb, ret_length);
+		moal_memcpy_ext(priv->phandle, pos, misc_cfg->param.hostcmd.cmd,
+				misc_cfg->param.hostcmd.len,
+				misc_cfg->param.hostcmd.len);
+	}
+
+	ret = cfg80211_vendor_cmd_reply(skb);
+	if (unlikely(ret))
+		PRINTM(MERROR, "vendor cmd: reply failed with ret:%d \n", ret);
+done:
+	if (status != MLAN_STATUS_PENDING && req)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
 /**
  * @brief vendor command to get link layer statistic
  *
@@ -5679,6 +6332,42 @@ static const struct wiphy_vendor_command vendor_commands[] = {
 #if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
 		.policy = woal_attr_policy,
 		.maxattr = ATTR_WIFI_MAX,
+#endif
+	},
+	{
+		.info = {
+				.vendor_id = MRVL_VENDOR_ID,
+				.subcmd = SUBCMD_SET_GET_SCANCFG,
+			},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			 WIPHY_VENDOR_CMD_NEED_NETDEV,
+		.doit = woal_cfg80211_subcmd_set_get_scancfg,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+	},
+	{
+		.info = {
+				.vendor_id = MRVL_VENDOR_ID,
+				.subcmd = SUBCMD_SET_GET_ADDBAPARAMS,
+			},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			 WIPHY_VENDOR_CMD_NEED_NETDEV,
+		.doit = woal_cfg80211_subcmd_set_get_addbaparams,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+		.policy = VENDOR_CMD_RAW_DATA,
+#endif
+	},
+	{
+		.info = {
+				.vendor_id = MRVL_VENDOR_ID,
+				.subcmd = SUBCMD_SET_GET_CLR_HOSTCMD,
+			},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			 WIPHY_VENDOR_CMD_NEED_NETDEV,
+		.doit = woal_cfg80211_subcmd_hostcmd,
+#if KERNEL_VERSION(5, 3, 0) <= CFG80211_VERSION_CODE
+		.policy = VENDOR_CMD_RAW_DATA,
 #endif
 	},
 	{
diff --git a/mlinux/moal_cfg80211_util.h b/mlinux/moal_cfg80211_util.h
index 25b512e..a9fe931 100644
--- a/mlinux/moal_cfg80211_util.h
+++ b/mlinux/moal_cfg80211_util.h
@@ -736,6 +736,9 @@ enum vendor_sub_command {
 	sub_cmd_set_packet_filter = 0x0011,
 	sub_cmd_get_packet_filter_capability,
 	sub_cmd_nd_offload = 0x0100,
+	SUBCMD_SET_GET_SCANCFG = 0x0200,
+	SUBCMD_SET_GET_ADDBAPARAMS = 0x0201,
+	SUBCMD_SET_GET_CLR_HOSTCMD = 0x0202,
 	SUBCMD_RTT_GET_CAPA = 0x1100,
 	SUBCMD_RTT_RANGE_REQUEST,
 	SUBCMD_RTT_RANGE_CANCEL,
diff --git a/mlinux/moal_eth_ioctl.c b/mlinux/moal_eth_ioctl.c
index 2893275..dddad2a 100644
--- a/mlinux/moal_eth_ioctl.c
+++ b/mlinux/moal_eth_ioctl.c
@@ -69,15 +69,16 @@ Change log:
 /** Bands supported in Infra mode */
 static t_u16 SupportedInfraBand[] = {
 	BAND_B,
-	BAND_B | BAND_G,
 	BAND_G,
 	BAND_GN,
-	BAND_B | BAND_G | BAND_GN,
+	BAND_B | BAND_G,
 	BAND_G | BAND_GN,
+	BAND_B | BAND_GN,
+	BAND_B | BAND_G | BAND_GN,
 	BAND_A,
 	BAND_B | BAND_A,
-	BAND_B | BAND_G | BAND_A,
 	BAND_G | BAND_A,
+	BAND_B | BAND_G | BAND_A,
 	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN,
 	BAND_A | BAND_G | BAND_AN | BAND_GN,
 	BAND_A | BAND_AN,
@@ -85,6 +86,7 @@ static t_u16 SupportedInfraBand[] = {
 	BAND_B | BAND_G | BAND_GN | BAND_GAC,
 	BAND_G | BAND_GN | BAND_GAC,
 	BAND_GN | BAND_GAC | BAND_GAX,
+	BAND_GN | BAND_GAX,
 	BAND_B | BAND_G | BAND_GN | BAND_GAC | BAND_GAX,
 	BAND_G | BAND_GN | BAND_GAC | BAND_GAX,
 	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC,
@@ -92,10 +94,17 @@ static t_u16 SupportedInfraBand[] = {
 	BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC,
 	BAND_A | BAND_AN | BAND_AAC,
 	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_AAX,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_AAX |
+		BAND_GAX,
 	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_GAC |
 		BAND_AAX,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_GAC |
+		BAND_AAX | BAND_GAX,
+	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_GAC |
+		BAND_GAX,
 	BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC | BAND_AAX,
 	BAND_A | BAND_AN | BAND_AAC | BAND_AAX,
+	BAND_B | BAND_G | BAND_GN | BAND_GAX,
 };
 
 /********************************************************
@@ -155,8 +164,9 @@ mlan_status parse_arguments(t_u8 *pos, int *data, int datalen,
 				is_hex = 0;
 			} else {
 				if (woal_atoi(&data[j], cdata) !=
-				    MLAN_STATUS_SUCCESS)
-					;
+				    MLAN_STATUS_SUCCESS) {
+					PRINTM(MERROR, " fail on woal_atoi()");
+				}
 			}
 			j++;
 			k = 0;
@@ -896,7 +906,8 @@ static int woal_setget_priv_bandcfg(moal_private *priv, t_u8 *respbuf,
 		     i++)
 			if (infra_band == SupportedInfraBand[i])
 				break;
-		if (i == sizeof(SupportedInfraBand)) {
+		if (i == (sizeof(SupportedInfraBand) /
+			  sizeof(SupportedInfraBand[0]))) {
 			ret = -EINVAL;
 			goto error;
 		}
@@ -2209,8 +2220,18 @@ static int woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf,
 	mlan_status status = MLAN_STATUS_SUCCESS;
 	txrate_setting *rate_setting = NULL;
 
+	t_u32 vht_mcs_limit = MLAN_RATE_INDEX_MCS9;
+	t_u32 he_mcs_limit = MLAN_RATE_INDEX_MCS11;
+	t_u32 nss_limit = MLAN_RATE_NSS2;
+
 	ENTER();
 
+	if (IS_CARDIW610(priv->phandle->card_type)) {
+		vht_mcs_limit = MLAN_RATE_INDEX_MCS8;
+		he_mcs_limit = MLAN_RATE_INDEX_MCS9;
+		nss_limit = MLAN_RATE_NSS1;
+	}
+
 	if (strlen(respbuf) == (strlen(CMD_NXP) + strlen(PRIV_CMD_TXRATECFG))) {
 		/* GET operation */
 		user_data_len = 0;
@@ -2263,6 +2284,15 @@ static int woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf,
 			/* auto */
 			rate->param.rate_cfg.is_rate_auto = 1;
 		} else {
+			if (data[0] == MLAN_RATE_FORMAT_LG ||
+			    data[0] == MLAN_RATE_FORMAT_HT) {
+				if (user_data_len > 2) {
+					PRINTM(MERROR,
+					       "Invalid number of arguments\n");
+					ret = -EINVAL;
+					goto done;
+				}
+			}
 			/* fixed rate */
 			PRINTM(MINFO, "SET: txratefg format: 0x%x\n", data[0]);
 			if ((data[0] != AUTO_RATE) &&
@@ -2282,9 +2312,9 @@ static int woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf,
 				    ((data[0] == MLAN_RATE_FORMAT_HT) &&
 				     (data[1] != 32) && (data[1] > 15)) ||
 				    ((data[0] == MLAN_RATE_FORMAT_VHT) &&
-				     (data[1] > MLAN_RATE_INDEX_MCS9)) ||
+				     (data[1] > vht_mcs_limit)) ||
 				    ((data[0] == MLAN_RATE_FORMAT_HE) &&
-				     (data[1] > MLAN_RATE_INDEX_MCS11))) {
+				     (data[1] > he_mcs_limit))) {
 					PRINTM(MERROR,
 					       "Invalid index selection\n");
 					ret = -EINVAL;
@@ -2299,8 +2329,9 @@ static int woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf,
 			if (data[0] == 2 || data[0] == 3) {
 				PRINTM(MINFO, "SET: txratefg nss: 0x%x\n",
 				       data[2]);
-				/* NSS is supported up to 2 */
-				if ((data[2] <= 0) || (data[2] >= 3)) {
+				/* NSS is supported up to 1 for IW610, and up to
+				 * 2 for other chips */
+				if ((data[2] <= 0) || (data[2] > nss_limit)) {
 					PRINTM(MERROR,
 					       "Invalid nss selection\n");
 					ret = -EINVAL;
@@ -2316,15 +2347,50 @@ static int woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf,
 				       data[3]);
 
 /* HE Preamble type */
-//#define HE_SU_PREAMBLE 0
+#define HE_SU_PREAMBLE 0
 #define HE_ER_PREAMBLE 1
 
 /* HE ER SU Type */
 #define HE_ER_SU_BANDWIDTH_TONE242 0
 #define HE_ER_SU_BANDWIDTH_TONE106 1
+#define HE_SU_BANDWIDTH_MAX 3
 
 				rate_setting = (txrate_setting *)&data[3];
 
+				if (IS_CARDIW610(priv->phandle->card_type)) {
+					if (rate_setting->stbc != 0) {
+						PRINTM(MERROR,
+						       "This chip does not support STBC\n");
+						ret = -EINVAL;
+						goto done;
+					}
+					if (rate_setting->adv_coding != 0) {
+						PRINTM(MERROR,
+						       "This chip does not support LDPC\n");
+						ret = -EINVAL;
+						goto done;
+					}
+					if (data[0] == MLAN_RATE_FORMAT_HE &&
+					    rate_setting->preamble ==
+						    HE_ER_PREAMBLE) {
+						if (rate_setting->bandwidth >
+						    HE_ER_SU_BANDWIDTH_TONE106) {
+							PRINTM(MERROR,
+							       "BW setting for this ER rate is not supported for this 20MHz only chip\n");
+							ret = -EINVAL;
+							goto done;
+						}
+					} else {
+						if (rate_setting->bandwidth !=
+						    0) {
+							PRINTM(MERROR,
+							       "BW setting is not supported for this 20MHz only chip\n");
+							ret = -EINVAL;
+							goto done;
+						}
+					}
+				}
+
 				if (data[0] == MLAN_RATE_FORMAT_HE) {
 					if (rate_setting->preamble ==
 					    HE_ER_PREAMBLE) {
@@ -2357,7 +2423,17 @@ static int woal_setget_priv_txratecfg(moal_private *priv, t_u8 *respbuf,
 							ret = -EINVAL;
 							goto done;
 						}
+					} else if (rate_setting->preamble ==
+						   HE_SU_PREAMBLE) {
+						if (rate_setting->bandwidth >
+						    HE_SU_BANDWIDTH_MAX) {
+							PRINTM(MERROR,
+							       "Invalid Bandwidth for HE SU Preamble\n");
+							ret = -EINVAL;
+							goto done;
+						}
 					}
+
 					if ((rate_setting->dcm) &&
 					    (rate_setting->stbc == 0)) {
 						if ((data[1] ==
@@ -3028,16 +3104,15 @@ done:
 /**
  *  @brief easymesh uap Set/Get multi AP mode handler
  *
- *  @param priv     A pointer to moal_private structure
- *  @param req      A pointer to ifreq structure
- *  @return         0 --success, otherwise fail
+ *  @param priv       A pointer to moal_private structure
+ *  @param respbuf    A pointer to response buffer
+ *  @param respbuflen Length of response buffer
+ *
+ *  @return           MultiAP mode for GET, 0 -- success, otherwise fail for SET
  */
 static int woal_uap_set_multiap_mode(moal_private *priv, t_u8 *respbuf,
 				     t_u32 respbuflen)
 {
-	mlan_ioctl_req *req = NULL;
-	mlan_ds_misc_cfg *misc = NULL;
-	mlan_status status = MLAN_STATUS_SUCCESS;
 	int mode[1] = {0};
 	int ret = 0;
 	int header_len = 0;
@@ -3054,22 +3129,20 @@ static int woal_uap_set_multiap_mode(moal_private *priv, t_u8 *respbuf,
 	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_SETMODE);
 	user_data_len = strlen(respbuf) - header_len;
 
-	/* Allocate an IOCTL request buffer */
-	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
-	if (req == NULL) {
-		ret = -ENOMEM;
-		goto done;
-	}
-
-	/* Fill request buffer */
-	misc = (mlan_ds_misc_cfg *)req->pbuf;
-	misc->sub_command = MLAN_OID_MISC_MULTI_AP_CFG;
-	req->req_id = MLAN_IOCTL_MISC_CFG;
-
 	if ((int)strlen(respbuf) == header_len) {
 		/* GET operation */
 		user_data_len = 0;
-		req->action = MLAN_ACT_GET;
+		if (priv->multi_ap_flag == EASY_MESH_MULTI_AP_BH_AND_FH_BSS)
+			mode[0] = EASY_MESH_MULTI_AP_BSS_MODE_3;
+		else if (priv->multi_ap_flag == EASY_MESH_MULTI_AP_BH_BSS)
+			mode[0] = EASY_MESH_MULTI_AP_BSS_MODE_2;
+		else if (priv->multi_ap_flag == EASY_MESH_MULTI_AP_FH_BSS)
+			mode[0] = EASY_MESH_MULTI_AP_BSS_MODE_1;
+		PRINTM(MINFO, "[EM:%s:%d] setmode to 0x%x\n", __func__,
+		       __LINE__, mode[0]);
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)mode,
+				sizeof(mode), respbuflen);
+		ret = sizeof(mode);
 	} else {
 		/* SET operation */
 		parse_arguments(respbuf + header_len, mode, ARRAY_SIZE(mode),
@@ -3098,35 +3171,9 @@ static int woal_uap_set_multiap_mode(moal_private *priv, t_u8 *respbuf,
 			priv->multi_ap_flag = EASY_MESH_MULTI_AP_FH_BSS;
 		PRINTM(MINFO, "[EM:%s:%d] priv->multi_ap_flag 0x%x\n", __func__,
 		       __LINE__, priv->multi_ap_flag);
-
-		req->action = MLAN_ACT_SET;
 	}
 
-	/* Send IOCTL request to MLAN */
-	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
-	if (status != MLAN_STATUS_SUCCESS) {
-		ret = -EFAULT;
-		goto done;
-	}
-
-	if (req->action == MLAN_ACT_GET) {
-		if (priv->multi_ap_flag == EASY_MESH_MULTI_AP_BH_AND_FH_BSS)
-			mode[0] = EASY_MESH_MULTI_AP_BSS_MODE_3;
-		else if (priv->multi_ap_flag == EASY_MESH_MULTI_AP_BH_BSS)
-			mode[0] = EASY_MESH_MULTI_AP_BSS_MODE_2;
-		else if (priv->multi_ap_flag == EASY_MESH_MULTI_AP_FH_BSS)
-			mode[0] = EASY_MESH_MULTI_AP_BSS_MODE_1;
-
-		PRINTM(MINFO, "[EM:%s:%d] setmode to 0x%x\n", __func__,
-		       __LINE__, mode[0]);
-		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)mode,
-				sizeof(mode), respbuflen);
-		ret = sizeof(mode);
-	}
 done:
-	if (status != MLAN_STATUS_PENDING)
-		kfree(req);
-
 	LEAVE();
 	return ret;
 }
@@ -4077,6 +4124,8 @@ static int woal_priv_get_cfpinfo(moal_private *priv, t_u8 *respbuf,
 	int ret = 0;
 	mlan_ioctl_req *req = NULL;
 	mlan_ds_misc_cfg *cfp_misc = NULL;
+	mlan_cfpinfo *c = NULL;
+	t_u32 header_len = 0;
 	mlan_status status = MLAN_STATUS_SUCCESS;
 
 	ENTER();
@@ -4095,6 +4144,11 @@ static int woal_priv_get_cfpinfo(moal_private *priv, t_u8 *respbuf,
 		goto done;
 	}
 
+	/* Check whether user has requested 6GHz or MAC2 tables */
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CFPINFO);
+	if (respbuflen >= (header_len + sizeof(mlan_cfpinfo)))
+		c = (mlan_cfpinfo *)(respbuf + header_len);
+
 	/* Fill request buffer */
 	cfp_misc = (mlan_ds_misc_cfg *)req->pbuf;
 	cfp_misc->sub_command = MLAN_OID_MISC_CFP_INFO;
@@ -4311,8 +4365,7 @@ static int woal_priv_assocessid(moal_private *priv, t_u8 *respbuf,
 	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
 		PRINTM(MERROR, "Acquire semaphore error, woal_set_essid\n");
 		ret = -EBUSY;
-		LEAVE();
-		return ret;
+		goto setessid_ret;
 	}
 
 	if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
@@ -4889,6 +4942,8 @@ static int woal_priv_set_get_drvdbg(moal_private *priv, t_u8 *respbuf,
 	       (drvdbg & MCMD_D) ? "X" : "");
 	printk(KERN_ALERT "MDAT_D (%08x) %s\n", MDAT_D,
 	       (drvdbg & MDAT_D) ? "X" : "");
+	printk(KERN_ALERT "MREG   (%08x) %s\n", MREG,
+	       (drvdbg & MREG) ? "X" : "");
 	printk(KERN_ALERT "MREG_D (%08x) %s\n", MREG_D,
 	       (drvdbg & MREG_D) ? "X" : "");
 	printk(KERN_ALERT "MIOCTL (%08x) %s\n", MIOCTL,
@@ -5269,6 +5324,7 @@ static int woal_priv_hssetpara(moal_private *priv, t_u8 *respbuf,
 	int data[15] = {0};
 	int user_data_len = 0;
 	int ret = 0;
+	t_u8 *buf = NULL;
 
 	ENTER();
 
@@ -5291,12 +5347,22 @@ static int woal_priv_hssetpara(moal_private *priv, t_u8 *respbuf,
 	}
 
 	if (user_data_len >= 1 && user_data_len <= 15) {
+		buf = kzalloc(CMD_BUF_LEN, GFP_ATOMIC);
+		if (!buf) {
+			PRINTM(MERROR, "Could not allocate buffer\n");
+			goto done;
+		}
+
+		memcpy(buf,
+		       respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_HSSETPARA)),
+		       CMD_BUF_LEN -
+			       (strlen(CMD_NXP) + strlen(PRIV_CMD_HSSETPARA)));
+
 		snprintf(respbuf, CMD_BUF_LEN, "%s%s%s", CMD_NXP,
-			 PRIV_CMD_HSCFG,
-			 respbuf + (strlen(CMD_NXP) +
-				    strlen(PRIV_CMD_HSSETPARA)));
+			 PRIV_CMD_HSCFG, buf);
 		respbuflen = strlen(respbuf);
 		ret = woal_priv_hscfg(priv, respbuf, respbuflen, MFALSE);
+		kfree(buf);
 		goto done;
 	}
 done:
@@ -5424,6 +5490,166 @@ done:
 	return ret;
 }
 
+/**
+ * @brief Set/Get auth_assoc timeout configuration parameters
+ *
+ * @param priv         A pointer to moal_private structure
+ * @param respbuf      A pointer to response buffer
+ * @param respbuflen   Available length of response buffer
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int woal_priv_set_get_auth_assoc_timeout_cfg(moal_private *priv,
+						    t_u8 *respbuf,
+						    t_u32 respbuflen)
+{
+	int ret = 0;
+	int user_data_len = 0;
+	int data[6];
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(data, 0, sizeof(data));
+	if (strlen(respbuf) ==
+	    (strlen(CMD_NXP) + strlen(PRIV_CMD_AUTH_ASSOC_TIMEOUT_CFG))) {
+		/* GET operation */
+		user_data_len = 0;
+	} else {
+		/* SET operation */
+		memset((char *)data, 0, sizeof(data));
+		parse_arguments(respbuf + strlen(CMD_NXP) +
+					strlen(PRIV_CMD_AUTH_ASSOC_TIMEOUT_CFG),
+				data, ARRAY_SIZE(data), &user_data_len);
+		if (sizeof(int) * user_data_len != sizeof(data)) {
+			PRINTM(MERROR,
+			       "auth_assoc_timeout_cfg: invalid numder of arguments provided\n");
+			LEAVE();
+			return -EINVAL;
+		}
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_AUTH_ASSOC_TIMEOUT_CONFIG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+
+	if (user_data_len) {
+		// SET operation
+		if (data[0] < AUTH_TIMEOUT_MIN || data[0] > AUTH_TIMEOUT_MAX) {
+			PRINTM(MERROR,
+			       "Invalid auth_timeout configuration provided,"
+			       "	valid range: %d-%d",
+			       AUTH_TIMEOUT_MIN, AUTH_TIMEOUT_MAX);
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.auth_assoc_cfg.auth_timeout = (u16)data[0];
+
+		if (data[1] < AUTH_RETRY_TIMEOUT_ACK_MIN ||
+		    data[1] > AUTH_RETRY_TIMEOUT_ACK_MAX) {
+			PRINTM(MERROR,
+			       "Invalid auth_retry_timeout_if_ack configuration provided, "
+			       "valid range: %d-%d",
+			       AUTH_RETRY_TIMEOUT_ACK_MIN,
+			       AUTH_RETRY_TIMEOUT_ACK_MAX);
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.auth_assoc_cfg.auth_retry_timeout_if_ack =
+			(u16)data[1];
+
+		if (data[2] < AUTH_RETRY_TIMEOUT_NO_ACK_MIN ||
+		    data[2] > AUTH_RETRY_TIMEOUT_NO_ACK_MAX) {
+			PRINTM(MERROR,
+			       "Invalid auth_retry_timeout_if_no_ack configuration provided, "
+			       "valid range: %d-%d",
+			       AUTH_RETRY_TIMEOUT_NO_ACK_MIN,
+			       AUTH_RETRY_TIMEOUT_NO_ACK_MAX);
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.auth_assoc_cfg.auth_retry_timeout_if_no_ack =
+			(u16)data[2];
+
+		if (data[3] < ASSOC_TIMEOUT_MIN ||
+		    data[3] > ASSOC_TIMEOUT_MAX) {
+			PRINTM(MERROR,
+			       "Invalid assoc_timeout configuration provided, "
+			       "valid range: %d-%d",
+			       ASSOC_TIMEOUT_MIN, ASSOC_TIMEOUT_MAX);
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.auth_assoc_cfg.assoc_timeout = (u16)data[3];
+
+		if (data[4] < REASSOC_TIMEOUT_MIN ||
+		    data[4] > REASSOC_TIMEOUT_MAX) {
+			PRINTM(MERROR,
+			       "Invalid reassoc_timeout configuration provided, "
+			       "valid range: %d-%d",
+			       REASSOC_TIMEOUT_MIN, REASSOC_TIMEOUT_MAX);
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.auth_assoc_cfg.reassoc_timeout = (u16)data[4];
+
+		if (data[5] < ASSOC_RETRY_TIMEOUT_MIN ||
+		    data[5] > ASSOC_RETRY_TIMEOUT_MAX) {
+			PRINTM(MERROR,
+			       "Invalid retry_timeout configuration provided, "
+			       "valid range: %d-%d",
+			       ASSOC_RETRY_TIMEOUT_MIN,
+			       ASSOC_RETRY_TIMEOUT_MAX);
+			ret = -EINVAL;
+			goto done;
+		}
+		misc->param.auth_assoc_cfg.retry_timeout = (u16)data[5];
+
+		req->action = MLAN_ACT_SET;
+	} else {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+	}
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+	if (user_data_len) {
+		// For SET opearion store auth_timeout in driver as driver
+		// handles auth_timeout
+		priv->auth_tx_wait_time =
+			misc->param.auth_assoc_cfg.auth_timeout;
+	}
+
+	// get auth_timeout from driver
+	misc->param.auth_assoc_cfg.auth_timeout = priv->auth_tx_wait_time;
+	data[0] = misc->param.auth_assoc_cfg.auth_timeout;
+	data[1] = misc->param.auth_assoc_cfg.auth_retry_timeout_if_ack;
+	data[2] = misc->param.auth_assoc_cfg.auth_retry_timeout_if_no_ack;
+	data[3] = misc->param.auth_assoc_cfg.assoc_timeout;
+	data[4] = misc->param.auth_assoc_cfg.reassoc_timeout;
+	data[5] = misc->param.auth_assoc_cfg.retry_timeout;
+	moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)data, sizeof(data),
+			respbuflen);
+	ret = sizeof(data);
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
 /**
  * @brief Get Netlink Number
  *
@@ -6140,8 +6366,7 @@ static int woal_priv_set_essid(moal_private *priv, t_u8 *respbuf,
 					       0);
 				ret = MLAN_STATUS_SUCCESS;
 
-				LEAVE();
-				return ret;
+				goto setessid_ret;
 			}
 		}
 #endif
@@ -7825,7 +8050,9 @@ static int woal_priv_get_txpwrlimit(moal_private *priv, t_u8 *respbuf,
 	    (trpc_cfg->sub_band != 0x21) && (trpc_cfg->sub_band != 0x22) &&
 	    (trpc_cfg->sub_band != 0x23) && (trpc_cfg->sub_band != 0x24) &&
 	    (trpc_cfg->sub_band != 0x25) && (trpc_cfg->sub_band != 0x26) &&
-	    (trpc_cfg->sub_band != 0x27)) {
+	    (trpc_cfg->sub_band != 0x27) &&
+	    (IS_CARDAW693(priv->phandle->card_type) &&
+	     (trpc_cfg->sub_band != 0x80))) {
 		PRINTM(MERROR, "Invalid subband=0x%x\n", trpc_cfg->sub_band);
 		ret = -EINVAL;
 		goto done;
@@ -12321,9 +12548,7 @@ static int woal_channel_switch(moal_private *priv, t_u8 block_tx,
 		} else if (band_width == CHANNEL_BW_80MHZ) {
 			pbwchansw_ie->new_channel_width = 1;
 			pbwchansw_ie->new_channel_center_freq0 =
-				center_freq_idx - 4;
-			pbwchansw_ie->new_channel_center_freq1 =
-				center_freq_idx + 4;
+				center_freq_idx;
 		} else if (band_width == CHANNEL_BW_160MHZ) {
 			pbwchansw_ie->new_channel_width = 2;
 			pbwchansw_ie->new_channel_center_freq0 =
@@ -13611,18 +13836,17 @@ static int woal_priv_set_get_tx_rx_ant(moal_private *priv, t_u8 *respbuf,
 		}
 		if (priv->phandle->feature_control & FEATURE_CTRL_STREAM_2X2) {
 			radio->param.ant_cfg.tx_antenna = data[0];
-			radio->param.ant_cfg.rx_antenna = data[0];
+			if (data[0] == RF_ANTENNA_AUTO) {
+				radio->param.ant_cfg.rx_antenna = 0;
+				if (data[1] > 0xffff) {
+					ret = -EINVAL;
+					goto done;
+				}
+			} else {
+				radio->param.ant_cfg.rx_antenna = data[0];
+			}
 			if (user_data_len == 2)
 				radio->param.ant_cfg.rx_antenna = data[1];
-#if defined(STA_CFG80211) || defined(UAP_CFG80211)
-			if (IS_CARD9098(priv->phandle->card_type) ||
-			    IS_CARD9097(priv->phandle->card_type) ||
-			    IS_CARDIW624(priv->phandle->card_type) ||
-			    IS_CARDAW693(priv->phandle->card_type)) {
-				woal_cfg80211_notify_antcfg(
-					priv, priv->phandle->wiphy, radio);
-			}
-#endif
 		} else {
 			radio->param.ant_cfg_1x1.antenna = data[0];
 			if (user_data_len == 2) {
@@ -13638,9 +13862,24 @@ static int woal_priv_set_get_tx_rx_ant(moal_private *priv, t_u8 *respbuf,
 	}
 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
 	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to set new antenna config\n");
 		ret = -EFAULT;
 		goto done;
 	}
+
+	/* Notify the CFG80211 layer only on SUCCESS from FW */
+	if ((status == MLAN_STATUS_SUCCESS) && (req->action == MLAN_ACT_SET)) {
+#if defined(STA_CFG80211) || defined(UAP_CFG80211)
+		if (IS_CARD9098(priv->phandle->card_type) ||
+		    IS_CARD9097(priv->phandle->card_type) ||
+		    IS_CARDIW624(priv->phandle->card_type) ||
+		    IS_CARDAW693(priv->phandle->card_type)) {
+			woal_cfg80211_notify_antcfg(priv, priv->phandle->wiphy,
+						    radio);
+		}
+#endif
+	}
+
 	if (!user_data_len) {
 		if (priv->phandle->feature_control & FEATURE_CTRL_STREAM_2X2) {
 			data[0] = radio->param.ant_cfg.tx_antenna;
@@ -14606,6 +14845,90 @@ static int woal_priv_bypassed_packet(moal_private *priv, t_u8 *respbuf,
 	return ret;
 }
 
+/**
+ * @brief               Set/Get module configuration
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ *  @return             Number of bytes written, negative for failure.
+ */
+static int woal_priv_fw_wakeup_method(moal_private *priv, t_u8 *respbuf,
+				      t_u32 respbuflen)
+{
+	int header_len = 0, user_data_len = 0;
+	int ret = 0, data[2];
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_FW_WAKEUP_METHOD);
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		user_data_len = 0;
+		req->action = MLAN_ACT_GET;
+	} else {
+		/* SET operation */
+		parse_arguments(respbuf + header_len, data,
+				sizeof(data) / sizeof(int), &user_data_len);
+		if (user_data_len > 2) {
+			PRINTM(MERROR, "Invalid parameter number\n");
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] != FW_WAKEUP_METHOD_INTERFACE &&
+		    data[0] != FW_WAKEUP_METHOD_GPIO) {
+			PRINTM(MERROR, "Invalid FW wake up method:%d\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == FW_WAKEUP_METHOD_GPIO) {
+			if (user_data_len == 1) {
+				PRINTM(MERROR,
+				       "Please provide gpio pin number for FW_WAKEUP_METHOD gpio\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			pm_cfg->param.fw_wakeup_params.gpio_pin = data[1];
+		}
+
+		req->action = MLAN_ACT_SET;
+		pm_cfg->param.fw_wakeup_params.method = data[0];
+	}
+
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_FW_WAKEUP_METHOD;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = ((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.method;
+	data[1] =
+		((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.gpio_pin;
+	moal_memcpy_ext(priv->phandle, respbuf, &data, sizeof(data),
+			respbuflen);
+	ret = sizeof(int) * 2;
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
 /**
  * @brief               Set Robustcoex gpiocfg
  * @param priv          Pointer to moal_private structure
@@ -15920,6 +16243,155 @@ done:
 	return ret;
 }
 
+/**
+ * @brief               Set/Get TSP config parameters
+ * @param priv          Pointer to moal_private structure
+ * @param respbuf       Pointer to response buffer
+ * @param resplen       Response buffer length
+ *
+ * @return              Number of bytes written, negative for failure.
+ */
+static int woal_priv_tsp_config(moal_private *priv, t_u8 *respbuf,
+				t_u32 respbuflen)
+{
+	mlan_ds_tsp_cfg *tsp_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_ds_misc_cfg *misc_cfg = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+	int data[8] = {0};
+	int header_len = 0;
+	int user_data_len = 0;
+	int ret = 0;
+
+	ENTER();
+
+	if (!priv || !priv->phandle) {
+		PRINTM(MERROR, "priv or handle is null\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!respbuf) {
+		PRINTM(MERROR, "response buffer is not available!\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_TSP_CFG);
+
+	memset(data, 0, sizeof(data));
+	parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data),
+			&user_data_len);
+
+	if (user_data_len > 8) {
+		PRINTM(MERROR, "invalid parameters\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/* Fill request buffer */
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
+	misc_cfg->sub_command = MLAN_OID_MISC_TSP_CFG;
+	tsp_cfg = &misc_cfg->param.tsp_cfg;
+	memset(tsp_cfg, 0, sizeof(mlan_ds_tsp_cfg));
+
+	if ((int)strlen(respbuf) == header_len) {
+		/* GET operation */
+		req->action = MLAN_ACT_GET;
+		user_data_len = 0;
+	} else {
+		req->action = MLAN_ACT_SET;
+		if (data[0] == 0) {
+			tsp_cfg->enable = (t_u16)data[0];
+		} else if (data[0] < 0 || data[0] > 1) {
+			PRINTM(MERROR, "err: Invalid TSP enable value\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (data[1] < 0 || data[1] > 10) {
+			PRINTM(MERROR,
+			       "err: Invalid TSP power backoff value\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (data[2] < 0 || data[2] > 300) {
+			PRINTM(MERROR,
+			       "err: Invalid TSP high power threshold value\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (data[3] < 0 || data[3] > 300) {
+			PRINTM(MERROR,
+			       "err: Invalid TSP low power threshold value\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (data[3] > data[2]) {
+			PRINTM(MERROR,
+			       "err: TSP low_thrshld value is greater than high_thrshld\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (data[4] < 1 || data[4] > 100) {
+			PRINTM(MERROR, "err: Invalid Duty Cycle Step value\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (data[5] < 0 || data[5] > 100) {
+			PRINTM(MERROR, "err: Invalid Duty Cycle Min value\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (data[6] < -100 || data[6] > 150) {
+			PRINTM(MERROR,
+			       "err: Invalid High Threshold Temperature value\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (data[7] < -100 || data[7] > 150) {
+			PRINTM(MERROR,
+			       "err: Invalid Low Threshold Temperature value\n");
+			ret = -EINVAL;
+			goto done;
+		} else if (data[7] > data[6]) {
+			PRINTM(MERROR,
+			       "err: TSP Low Threshold Temperature is greater than High Threshold Temperature value\n");
+			ret = -EINVAL;
+			goto done;
+		} else {
+			tsp_cfg->enable = (t_u16)data[0];
+			tsp_cfg->backoff = (t_s32)data[1];
+			tsp_cfg->high_thrshld = (t_s32)data[2];
+			tsp_cfg->low_thrshld = (t_s32)data[3];
+			tsp_cfg->duty_cyc_step = (t_s32)data[4];
+			tsp_cfg->duty_cyc_min = (t_s32)data[5];
+			tsp_cfg->high_thrshld_temp = (t_s32)data[6];
+			tsp_cfg->low_thrshld_temp = (t_s32)data[7];
+		}
+	}
+
+	/* Send IOCTL request to MLAN */
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	if (!user_data_len) {
+		/* Copy back to userspace call */
+		moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)tsp_cfg,
+				sizeof(mlan_ds_tsp_cfg), respbuflen);
+		ret = sizeof(mlan_ds_tsp_cfg);
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+
+	LEAVE();
+	return ret;
+}
+
 /**
  * @brief               Set/Get cross chip sync config parameters
  * @param priv          Pointer to moal_private structure
@@ -20700,6 +21172,14 @@ int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req)
 			len = woal_priv_set_get_scancfg(priv, buf,
 							priv_cmd.total_len);
 			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_AUTH_ASSOC_TIMEOUT_CFG,
+				    strlen(PRIV_CMD_AUTH_ASSOC_TIMEOUT_CFG)) ==
+			   0) {
+			/* Auth, Assoc configuration */
+			len = woal_priv_set_get_auth_assoc_timeout_cfg(
+				priv, buf, priv_cmd.total_len);
+			goto handled;
 		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_GETNLNUM,
 				    strlen(PRIV_CMD_GETNLNUM)) == 0) {
 			/* Scan configuration */
@@ -21301,6 +21781,11 @@ int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req)
 			len = woal_priv_cross_chip_synch(priv, buf,
 							 priv_cmd.total_len);
 			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_TSP_CFG,
+				    strlen(PRIV_CMD_TSP_CFG)) == 0) {
+			len = woal_priv_tsp_config(priv, buf,
+						   priv_cmd.total_len);
+			goto handled;
 		} else if (strnicmp(buf + strlen(CMD_NXP),
 				    PRIV_CMD_CH_LOAD_RESULTS,
 				    strlen(PRIV_CMD_CH_LOAD_RESULTS)) == 0) {
@@ -21437,6 +21922,13 @@ int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req)
 			len = woal_priv_bypassed_packet(priv, buf,
 							priv_cmd.total_len);
 			goto handled;
+		} else if (strnicmp(buf + strlen(CMD_NXP),
+				    PRIV_CMD_FW_WAKEUP_METHOD,
+				    strlen(PRIV_CMD_FW_WAKEUP_METHOD)) == 0) {
+			/* Set/Get fw wake up method */
+			len = woal_priv_fw_wakeup_method(priv, buf,
+							 priv_cmd.total_len);
+			goto handled;
 #ifdef WIFI_DIRECT_SUPPORT
 #if defined(UAP_CFG80211)
 		} else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_CFG_NOA,
@@ -21692,7 +22184,7 @@ int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req)
 		} else if (strnicmp(buf + strlen(CMD_NXP),
 				    PRIV_CMD_GET_CFG_CHAN_LIST,
 				    strlen(PRIV_CMD_GET_CFG_CHAN_LIST)) == 0) {
-			/* Get txpwrlimit */
+			/* Get channel list */
 			if (IS_STA_OR_UAP_CFG80211(cfg80211_wext))
 				len = woal_priv_getcfgchanlist(
 					priv, buf, priv_cmd.total_len);
diff --git a/mlinux/moal_eth_ioctl.h b/mlinux/moal_eth_ioctl.h
index 1a98fd2..91a4d11 100644
--- a/mlinux/moal_eth_ioctl.h
+++ b/mlinux/moal_eth_ioctl.h
@@ -238,6 +238,7 @@ typedef struct _chan_stats {
 #define PRIV_CMD_TX_BF_CFG "httxbfcfg"
 #define PRIV_CMD_PORT_CTRL "port_ctrl"
 #define PRIV_CMD_PB_BYPASS "pb_bypass"
+#define PRIV_CMD_FW_WAKEUP_METHOD "fwwakeupmethod"
 #ifdef SDIO
 #define PRIV_CMD_SD_CMD53_RW "sdcmd53rw"
 #endif
@@ -305,6 +306,7 @@ typedef struct _chan_stats {
 #define PRIV_CMD_CH_LOAD "getchload"
 #define PRIV_CMD_CH_LOAD_RESULTS "getloadresults"
 #define PRIV_CMD_CROSS_CHIP_SYNCH "crosssynch"
+#define PRIV_CMD_TSP_CFG "wlan_tsp_cfg"
 
 #define PRIV_CMD_ARB_CFG "arb"
 
@@ -413,6 +415,8 @@ typedef struct _ssu_params_cfg {
 #define PRIV_CMD_BTWT_AP_CONFIG_GET "btwt_AP_config_get"
 
 #define PRIV_CMD_LPM "lpm"
+/** Private command: auth/assoc timeout cfg*/
+#define PRIV_CMD_AUTH_ASSOC_TIMEOUT_CFG "auth_assoc_timeout_cfg"
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
 int woal_do_ioctl(struct net_device *dev, struct ifreq *req, void __user *data,
diff --git a/mlinux/moal_init.c b/mlinux/moal_init.c
index 6bfbfd0..f790666 100644
--- a/mlinux/moal_init.c
+++ b/mlinux/moal_init.c
@@ -60,13 +60,14 @@ static int disable_regd_by_driver = 1;
 /** Region alpha2 string */
 static char *reg_alpha2;
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
-static int country_ie_ignore;
-static int beacon_hints;
+static int country_ie_ignore = 1;
+static int beacon_hints = 1;
 #endif
 #endif
 static int cfg80211_drcs;
 
 static int dmcs;
+static int pref_dbc;
 
 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
@@ -81,13 +82,18 @@ static int drcs_chantime_mode;
 /** Auto deep sleep */
 static int auto_ds;
 
-/** net_rx mode*/
-static int net_rx;
+/** net_rx mode */
+static int net_rx = 1;
 /** amsdu deaggr mode */
 static int amsdu_deaggr = 1;
 
+static int tx_budget = 2600;
+static int mclient_scheduling = 1;
+
 static int ext_scan;
 
+/** Boot Time config */
+static int bootup_cal_ctrl = 0;
 /** IEEE PS mode */
 static int ps_mode;
 /** passive to active scan */
@@ -117,6 +123,9 @@ static int uap_max_sta;
 static int wacp_mode = WACP_MODE_DEFAULT;
 #endif
 
+/** Fw cutom data config */
+static unsigned int fw_data_cfg = 0;
+
 #ifdef WIFI_DIRECT_SUPPORT
 /** Max WIFIDIRECT interfaces */
 static int max_wfd_bss = DEF_WIFIDIRECT_BSS;
@@ -144,7 +153,11 @@ static int shutdown_hs;
 /** SDIO slew rate */
 static int slew_rate = 3;
 #endif
-int tx_work = 0;
+#ifdef IMX_SUPPORT
+static int tx_work = 1;
+#else
+static int tx_work = 0;
+#endif
 
 #if defined(CONFIG_RPS)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
@@ -170,10 +183,11 @@ static int rps = 0;
  */
 static int edmac_ctrl = 0;
 
-static int tx_skb_clone = 0;
 #ifdef IMX_SUPPORT
+static int tx_skb_clone = 1;
 static int pmqos = 1;
 #else
+static int tx_skb_clone = 0;
 static int pmqos = 0;
 #endif
 
@@ -326,7 +340,7 @@ int dual_nb;
 #ifdef DEBUG_LEVEL2
 #define DEFAULT_DEBUG_MASK (0xffffffff)
 #else
-#define DEFAULT_DEBUG_MASK (MMSG | MFATAL | MERROR | MREG_D)
+#define DEFAULT_DEBUG_MASK (MMSG | MFATAL | MERROR | MREG_D | MFW_D)
 #endif /* DEBUG_LEVEL2 */
 t_u32 drvdbg = DEFAULT_DEBUG_MASK;
 
@@ -369,8 +383,8 @@ static card_type_entry card_type_map_tbl[] = {
 #ifdef SDAW693
 	{CARD_TYPE_SDAW693, 0, CARD_SDAW693},
 #endif
-#ifdef SDIW615
-	{CARD_TYPE_SDIW615, 0, CARD_SDIW615},
+#ifdef SDIW610
+	{CARD_TYPE_SDIW610, 0, CARD_SDIW610},
 #endif
 #ifdef PCIE8897
 	{CARD_TYPE_PCIE8897, 0, CARD_PCIE8897},
@@ -412,8 +426,8 @@ static card_type_entry card_type_map_tbl[] = {
 #ifdef USBIW624
 	{CARD_TYPE_USBIW624, 0, CARD_USBIW624},
 #endif
-#ifdef USBIW615
-	{CARD_TYPE_USBIW615, 0, CARD_USBIW615},
+#ifdef USBIW610
+	{CARD_TYPE_USBIW610, 0, CARD_USBIW610},
 #endif
 };
 
@@ -449,6 +463,12 @@ static t_size parse_cfg_get_line(t_u8 *data, t_size size, t_u8 *line_pos)
 	dest = line_pos;
 
 	while (pos < (t_s32)size && *src != '\x0A' && *src != '\0') {
+		if ((dest - line_pos) >= (MAX_LINE_LEN - 1)) {
+			PRINTM(MERROR,
+			       "error: input data size exceeds the dest buff limit\n");
+			LEAVE();
+			return -1;
+		}
 		if (*src != ' ' && *src != '\t') /* parse space */
 			*dest++ = *src++;
 		else
@@ -839,12 +859,32 @@ static mlan_status parse_cfg_read_block(t_u8 *data, t_u32 size,
 			params->amsdu_deaggr = out_data;
 			PRINTM(MMSG, "amsdu_deaggr = %d\n",
 			       params->amsdu_deaggr);
+		} else if (strncmp(line, "tx_budget", strlen("tx_budget")) ==
+			   0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->tx_budget = out_data;
+		} else if (strncmp(line, "mclient_scheduling",
+				   strlen("mclient_scheduling")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->mclient_scheduling = out_data;
 		} else if (strncmp(line, "ext_scan", strlen("ext_scan")) == 0) {
 			if (parse_line_read_int(line, &out_data) !=
 			    MLAN_STATUS_SUCCESS)
 				goto err;
 			params->ext_scan = out_data;
 			PRINTM(MMSG, "ext_scan = %d\n", params->ext_scan);
+		} else if (strncmp(line, "bootup_cal_ctrl",
+				   strlen("bootup_cal_ctrl")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->bootup_cal_ctrl = out_data;
+			PRINTM(MMSG, "bootup_cal_ctrl = %d\n",
+			       params->bootup_cal_ctrl);
 		} else if (strncmp(line, "ps_mode", strlen("ps_mode")) == 0) {
 			if (parse_line_read_int(line, &out_data) !=
 			    MLAN_STATUS_SUCCESS)
@@ -1365,13 +1405,14 @@ static mlan_status parse_cfg_read_block(t_u8 *data, t_u32 size,
 			if (parse_line_read_int(line, &out_data) !=
 			    MLAN_STATUS_SUCCESS)
 				goto err;
-			if (out_data)
-				moal_extflg_set(handle, EXT_DMCS);
-			else
-				moal_extflg_clear(handle, EXT_DMCS);
-			PRINTM(MMSG, "dmcs %s\n",
-			       moal_extflg_isset(handle, EXT_DMCS) ? "on" :
-								     "off");
+			params->dmcs = out_data;
+			PRINTM(MMSG, "dmcs=%d\n", params->dmcs);
+		} else if (strncmp(line, "pref_dbc", strlen("pref_dbc")) == 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->pref_dbc = out_data;
+			PRINTM(MMSG, "pref_dbc=%d\n", params->pref_dbc);
 		}
 
 		else if (strncmp(line, "drcs_chantime_mode",
@@ -1472,7 +1513,14 @@ static mlan_status parse_cfg_read_block(t_u8 *data, t_u32 size,
 			PRINTM(MMSG, "wacp_moe=%d\n", params->wacp_mode);
 		}
 #endif
-		else if (strncmp(line, "mcs32", strlen("mcs32")) == 0) {
+		else if (strncmp(line, "fw_data_cfg", strlen("fw_data_cfg")) ==
+			 0) {
+			if (parse_line_read_int(line, &out_data) !=
+			    MLAN_STATUS_SUCCESS)
+				goto err;
+			params->fw_data_cfg = out_data;
+			PRINTM(MMSG, "fw_data_cfg= %d\n", params->fw_data_cfg);
+		} else if (strncmp(line, "mcs32", strlen("mcs32")) == 0) {
 			if (parse_line_read_int(line, &out_data) !=
 			    MLAN_STATUS_SUCCESS)
 				goto err;
@@ -1551,6 +1599,17 @@ static mlan_status parse_cfg_read_block(t_u8 *data, t_u32 size,
 			       params->reject_addba_req);
 		}
 	}
+
+	if (params->tx_budget <= 0)
+		params->mclient_scheduling = 0;
+
+#ifdef PCIE
+	if (!IS_PCIEAW693(handle->card_type))
+		params->mclient_scheduling = 0;
+#else
+	params->mclient_scheduling = 0;
+#endif
+
 	if (end)
 		return ret;
 err:
@@ -1649,6 +1708,10 @@ static void woal_setup_module_param(moal_handle *handle, moal_mod_para *params)
 		handle->params.mcs32 = params->mcs32;
 	}
 #endif /* UAP_SUPPORT */
+	handle->params.fw_data_cfg = fw_data_cfg;
+	if (params) {
+		handle->params.fw_data_cfg = params->fw_data_cfg;
+	}
 
 	handle->params.hs_auto_arp = hs_auto_arp;
 	if (params) {
@@ -1684,16 +1747,32 @@ static void woal_setup_module_param(moal_handle *handle, moal_mod_para *params)
 	if (params)
 		handle->params.amsdu_deaggr = params->amsdu_deaggr;
 
+	handle->params.tx_budget = params ? params->tx_budget : tx_budget;
+	handle->params.mclient_scheduling =
+		params ? params->mclient_scheduling : mclient_scheduling;
+
+	if (handle->params.tx_budget <= 0)
+		handle->params.mclient_scheduling = 0;
+
+#ifdef PCIE
+	if (!IS_PCIEAW693(handle->card_type))
+		handle->params.mclient_scheduling = 0;
+#else
+	handle->params.mclient_scheduling = 0;
+#endif
+
 	handle->params.ext_scan = ext_scan;
 	if (params)
 		handle->params.ext_scan = params->ext_scan;
 
+	handle->params.bootup_cal_ctrl = bootup_cal_ctrl;
 	handle->params.ps_mode = ps_mode;
 	handle->params.p2a_scan = p2a_scan;
 	handle->params.scan_chan_gap = scan_chan_gap;
 	handle->params.sched_scan = sched_scan;
 	handle->params.max_tx_buf = max_tx_buf;
 	if (params) {
+		handle->params.bootup_cal_ctrl = params->bootup_cal_ctrl;
 		handle->params.ps_mode = params->ps_mode;
 		handle->params.max_tx_buf = params->max_tx_buf;
 		handle->params.p2a_scan = params->p2a_scan;
@@ -1867,8 +1946,12 @@ static void woal_setup_module_param(moal_handle *handle, moal_mod_para *params)
 #endif
 	if (cfg80211_drcs)
 		moal_extflg_set(handle, EXT_CFG80211_DRCS);
-	if (dmcs)
-		moal_extflg_set(handle, EXT_DMCS);
+	handle->params.dmcs = dmcs;
+	if (params)
+		handle->params.dmcs = params->dmcs;
+	handle->params.pref_dbc = pref_dbc;
+	if (params)
+		handle->params.pref_dbc = params->pref_dbc;
 
 	handle->params.drcs_chantime_mode = drcs_chantime_mode;
 	if (params)
@@ -2248,6 +2331,12 @@ void woal_init_from_dev_tree(void)
 				PRINTM(MIOCTL, "dmcs=0x%x\n", data);
 				dmcs = data;
 			}
+		} else if (!strncmp(prop->name, "pref_dbc",
+				    strlen("pref_dbc"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MIOCTL, "pref_dbc=0x%x\n", data);
+				pref_dbc = data;
+			}
 		}
 #endif
 #endif
@@ -2372,6 +2461,13 @@ void woal_init_from_dev_tree(void)
 				multi_dtim = data;
 				PRINTM(MIOCTL, "multi_dtim=%d\n", multi_dtim);
 			}
+		} else if (!strncmp(prop->name, "bootup_cal_ctrl",
+				    strlen("bootup_cal_ctrl"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				bootup_cal_ctrl = data;
+				PRINTM(MIOCTL, "bootup_cal_ctrl=%d\n",
+				       bootup_cal_ctrl);
+			}
 		} else if (!strncmp(prop->name, "inact_tmo",
 				    strlen("inact_tmo"))) {
 			if (!of_property_read_u32(dt_node, prop->name, &data)) {
@@ -2429,7 +2525,13 @@ void woal_init_from_dev_tree(void)
 			}
 		}
 #endif
-		else if (!strncmp(prop->name, "mcs32", strlen("mcs32"))) {
+		else if (!strncmp(prop->name, "fw_data_cfg",
+				  strlen("fw_data_cfg"))) {
+			if (!of_property_read_u32(dt_node, prop->name, &data)) {
+				PRINTM(MERROR, "fw_data_cfg=0x%x\n", data);
+				fw_data_cfg = data;
+			}
+		} else if (!strncmp(prop->name, "mcs32", strlen("mcs32"))) {
 			if (!of_property_read_u32(dt_node, prop->name, &data)) {
 				PRINTM(MERROR, "mcs32=0x%x\n", data);
 				mcs32 = data;
@@ -2648,6 +2750,19 @@ mlan_status woal_init_module_param(moal_handle *handle)
 			}
 		}
 	}
+	/* do some special handle for MFG mode if mfg_mode is specified in
+	 * module param cfg file */
+#ifdef MFG_CMD_SUPPORT
+	if (handle->params.mfg_mode) {
+#if defined(STA_WEXT) || defined(UAP_WEXT)
+		handle->params.cfg80211_wext = STA_WEXT_MASK | UAP_WEXT_MASK;
+#else
+		handle->params.cfg80211_wext = 0;
+#endif
+		handle->params.drv_mode = DRV_MODE_STA;
+	}
+#endif
+
 	if (no_match)
 		ret = woal_cfg_fallback_process(handle);
 out:
@@ -2751,6 +2866,10 @@ module_param(ext_scan, int, 0660);
 MODULE_PARM_DESC(
 	ext_scan,
 	"0: MLAN default; 1: Enable Extended Scan; 2: Enable Enhanced Extended Scan");
+module_param(bootup_cal_ctrl, int, 0660);
+MODULE_PARM_DESC(
+	bootup_cal_ctrl,
+	"0: Disable boot time optimization (default); 1: Enable boot time optimization");
 module_param(ps_mode, int, 0660);
 MODULE_PARM_DESC(
 	ps_mode,
@@ -2771,9 +2890,11 @@ MODULE_PARM_DESC(max_tx_buf, "Maximum Tx buffer size (2048/4096/8192)");
 
 #if defined(SDIO)
 module_param(intmode, int, 0);
-MODULE_PARM_DESC(intmode, "0: INT_MODE_SDIO, 1: INT_MODE_GPIO");
+MODULE_PARM_DESC(intmode, "0: INT_MODE_SDIO (default), 1: INT_MODE_GPIO");
 module_param(gpiopin, int, 0);
-MODULE_PARM_DESC(gpiopin, "255:new GPIO int mode, other vlue: gpio pin number");
+MODULE_PARM_DESC(
+	gpiopin,
+	"GPIO pin number when intmode=1 (default 0, HW mapped intr on GPIO-21)");
 #endif
 
 module_param(pm_keep_power, int, 0);
@@ -2795,22 +2916,25 @@ MODULE_PARM_DESC(
 	"0:has the slowest slew rate, then 01, then 02, and 03 has the highest slew rate");
 #endif
 module_param(tx_work, uint, 0660);
-MODULE_PARM_DESC(tx_work, "1: Enable tx_work; 0: Disable tx_work");
+MODULE_PARM_DESC(
+	tx_work,
+	"1: Enable tx_work_queue (default on iMX); 0: Disable tx_work_queue");
 #if defined(CONFIG_RPS)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
 module_param(rps, uint, 0660);
 MODULE_PARM_DESC(
 	rps,
-	"bit0-bit4(0x1 - 0xf): Enables rps on specific cpu ; 0: Disables rps");
+	"bit0-bit4 (0x1-0xf): Enables rps on specific cpu ; 0: Disables rps (default)");
 #endif
 #endif
 module_param(edmac_ctrl, int, 0660);
 MODULE_PARM_DESC(edmac_ctrl, "0: Disable edmac; 1: Enable edmac");
 module_param(tx_skb_clone, uint, 0660);
-MODULE_PARM_DESC(tx_skb_clone,
-		 "1: Enable tx_skb_clone; 0: Disable tx_skb_clone");
+MODULE_PARM_DESC(
+	tx_skb_clone,
+	"1: Enable tx_skb_clone (default on iMX); 0: Disable tx_skb_clone");
 module_param(pmqos, uint, 0660);
-MODULE_PARM_DESC(pmqos, "1: Enable pmqos; 0: Disable pmqos");
+MODULE_PARM_DESC(pmqos, "1: Enable pmqos (default on iMX); 0: Disable pmqos");
 module_param(mcs32, uint, 0660);
 MODULE_PARM_DESC(mcs32, "1: Enable mcs32; 0: Disable mcs32");
 module_param(hs_auto_arp, uint, 0660);
@@ -2881,13 +3005,23 @@ MODULE_PARM_DESC(wakelock_timeout, "set wakelock_timeout value (ms)");
 module_param(dev_cap_mask, uint, 0);
 MODULE_PARM_DESC(dev_cap_mask, "Device capability mask");
 module_param(net_rx, int, 0);
-MODULE_PARM_DESC(net_rx,
-		 "0: use netif_rx_ni in rx; 1: use netif_receive_skb in rx");
+MODULE_PARM_DESC(
+	net_rx,
+	"0: use netif_rx/netif_rx_ni in rx; 1: use netif_receive_skb in rx (default)");
 module_param(amsdu_deaggr, int, 0);
 MODULE_PARM_DESC(
 	amsdu_deaggr,
 	"0: buf copy in amsud deaggregation; 1: avoid buf copy in amsud deaggregation (default)");
 
+module_param(tx_budget, int, 0);
+MODULE_PARM_DESC(
+	tx_budget,
+	"airtime tx budget for multi-client scheduling in usec, 0 - disable, default - 2600");
+
+module_param(mclient_scheduling, int, 0);
+MODULE_PARM_DESC(mclient_scheduling,
+		 "0: disable multi-client scheduling; 1 - enable(default)");
+
 #ifdef SDIO
 module_param(sdio_rx_aggr, int, 0);
 MODULE_PARM_DESC(sdio_rx_aggr,
@@ -2956,7 +3090,8 @@ MODULE_PARM_DESC(napi, "1: enable napi api; 0: disable napi");
 
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
 module_param(dfs_offload, int, 0);
-MODULE_PARM_DESC(dfs_offload, "1: enable dfs offload; 0: disable dfs offload.");
+MODULE_PARM_DESC(dfs_offload,
+		 "1: enable dfs offload; 0: disable dfs offload (default)");
 #endif
 
 module_param(drcs_chantime_mode, int, 0);
@@ -2968,7 +3103,13 @@ MODULE_PARM_DESC(cfg80211_drcs,
 		 "1: Enable DRCS support; 0: Disable DRCS support");
 
 module_param(dmcs, int, 0);
-MODULE_PARM_DESC(dmcs, "1: Enable dynamic mapping; 0: Disable dynamic mapping");
+MODULE_PARM_DESC(
+	dmcs,
+	"0: Firmware default (default); 1: Enable dynamic mapping; 2: Disable dynamic mapping");
+module_param(pref_dbc, int, 0);
+MODULE_PARM_DESC(
+	pref_dbc,
+	"0: Firmware Default (default); 1: Enable prefer DBC; 2:Disable prefer DBC");
 
 module_param(roamoffload_in_hs, int, 0);
 MODULE_PARM_DESC(
@@ -2983,6 +3124,10 @@ MODULE_PARM_DESC(
 	wacp_mode,
 	"WACP mode for UAP/GO 0: WACP_MODE_DEFAULT; 1: WACP_MODE_1; 2: WACP_MODE_2");
 #endif
+module_param(fw_data_cfg, int, 0);
+MODULE_PARM_DESC(
+	fw_data_cfg,
+	"Custom Fw data Bit0: Fw Remapping; Bit1: USB Bulk End Point; Bit2: DPD Current Optimizations");
 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
 module_param(host_mlme, int, 0);
@@ -2996,17 +3141,17 @@ MODULE_PARM_DESC(
 module_param(disable_regd_by_driver, int, 0);
 MODULE_PARM_DESC(
 	disable_regd_by_driver,
-	"0: reg domain set by driver enable(default); 1: reg domain set by driver disable");
+	"0: reg domain set by driver enable; 1: reg domain set by driver disable (default)");
 module_param(reg_alpha2, charp, 0660);
 MODULE_PARM_DESC(reg_alpha2, "Regulatory alpha2");
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
 module_param(country_ie_ignore, int, 0);
 MODULE_PARM_DESC(
 	country_ie_ignore,
-	"0: Follow countryIE from AP and beacon hint enable; 1: Ignore countryIE from AP and beacon hint disable");
+	"0: Follow countryIE from AP and beacon hint enable; 1: Ignore countryIE from AP and beacon hint disable (default)");
 module_param(beacon_hints, int, 0);
 MODULE_PARM_DESC(beacon_hints,
-		 "0: enable beacon hints(default); 1: disable beacon hints");
+		 "0: enable beacon hints; 1: disable beacon hints (default)");
 #endif
 #endif
 
diff --git a/mlinux/moal_ioctl.c b/mlinux/moal_ioctl.c
index 038619e..94b8b2a 100644
--- a/mlinux/moal_ioctl.c
+++ b/mlinux/moal_ioctl.c
@@ -906,12 +906,12 @@ void woal_request_set_multicast_list(moal_private *priv, struct net_device *dev)
 	bss->sub_command = MLAN_OID_BSS_MULTICAST_LIST;
 	req->req_id = MLAN_IOCTL_BSS;
 	req->action = MLAN_ACT_SET;
-	if (dev->flags & IFF_PROMISC) {
-		bss->param.multicast_list.mode = MLAN_PROMISC_MODE;
-	} else if (dev->flags & IFF_ALLMULTI) {
+	if (dev->flags & IFF_ALLMULTI) {
 		bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
 	} else {
-		bss->param.multicast_list.mode = MLAN_MULTICAST_MODE;
+		if (dev->flags & IFF_PROMISC)
+			bss->param.multicast_list.mode = MLAN_PROMISC_MODE;
+		bss->param.multicast_list.mode |= MLAN_MULTICAST_MODE;
 		mc_count = woal_copy_all_mc_list(priv->phandle,
 						 &bss->param.multicast_list);
 		if (mc_count > MLAN_MAX_MULTICAST_LIST_SIZE)
@@ -1283,6 +1283,11 @@ mlan_status woal_bss_start(moal_private *priv, t_u8 wait_option,
 	kfree(temp_ssid_bssid);
 #endif
 
+	if (MOAL_ACQ_SEMAPHORE_BLOCK(&priv->phandle->async_sem)) {
+		PRINTM(MERROR, "Acquire semaphore error, woal_bss_start\n");
+		LEAVE();
+		return -EBUSY;
+	}
 	/* Allocate an IOCTL request buffer */
 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
 	if (req == NULL) {
@@ -1308,10 +1313,12 @@ mlan_status woal_bss_start(moal_private *priv, t_u8 wait_option,
 				sizeof(mlan_ssid_bssid));
 #ifdef STA_CFG80211
 #ifdef STA_SUPPORT
-	priv->assoc_status = req->status_code;
+	if (status != MLAN_STATUS_PENDING)
+		priv->assoc_status = req->status_code;
 #endif
 #endif
 done:
+	MOAL_REL_SEMAPHORE(&priv->phandle->async_sem);
 	if (status != MLAN_STATUS_PENDING)
 		kfree(req);
 	LEAVE();
@@ -2183,10 +2190,12 @@ mlan_status woal_request_get_fw_info(moal_private *priv, t_u8 wait_option,
 					sizeof(mlan_fw_info),
 					sizeof(mlan_fw_info));
 		DBG_HEXDUMP(MCMD_D, "mac", priv->current_addr, 6);
-	} else
+	} else if (status != MLAN_STATUS_PENDING)
 		PRINTM(MERROR,
 		       "get fw info failed! status=%d, error_code=0x%x\n",
 		       status, req->status_code);
+	else
+		PRINTM(MERROR, "get fw info failed! status=%d", status);
 done:
 	if (status != MLAN_STATUS_PENDING)
 		kfree(req);
@@ -6093,8 +6102,27 @@ mlan_status woal_cancel_scan(moal_private *priv, t_u8 wait_option)
 	unsigned long flags;
 #endif
 	/* If scan is in process, cancel the scan command */
-	if (!handle->scan_pending_on_block || !scan_priv)
+	if (!handle->scan_pending_on_block || !scan_priv) {
+#ifdef STA_CFG80211
+		spin_lock_irqsave(&handle->scan_req_lock, flags);
+		if (IS_STA_CFG80211(handle->params.cfg80211_wext) &&
+		    handle->scan_request) {
+			cancel_delayed_work(&handle->scan_timeout_work);
+			/* some supplicant cannot handle SCAN abort event */
+			if (scan_priv &&
+			    (scan_priv->bss_type == MLAN_BSS_TYPE_STA))
+				woal_cfg80211_scan_done(handle->scan_request,
+							MTRUE);
+			else
+				woal_cfg80211_scan_done(handle->scan_request,
+							MFALSE);
+			handle->scan_request = NULL;
+			handle->fake_scan_complete = MFALSE;
+		}
+		spin_unlock_irqrestore(&handle->scan_req_lock, flags);
+#endif
 		return ret;
+	}
 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
 	if (req == NULL) {
 		ret = MLAN_STATUS_FAILURE;
@@ -6643,7 +6671,7 @@ mlan_status woal_set_rssi_low_threshold(moal_private *priv, char *rssi,
 	priv->mrvl_rssi_low = low_rssi;
 #endif
 	misc->param.subscribe_event.low_rssi = low_rssi;
-	misc->param.subscribe_event.low_rssi_freq = 1;
+	misc->param.subscribe_event.low_rssi_freq = 0;
 	ret = woal_request_ioctl(priv, req, wait_option);
 	if (ret == MLAN_STATUS_FAILURE) {
 		PRINTM(MERROR, "request set rssi_low_threshold fail!\n");
@@ -6707,7 +6735,7 @@ mlan_status woal_set_rssi_threshold(moal_private *priv, t_u32 event_id,
 			SUBSCRIBE_EVT_ACT_BITWISE_SET;
 	misc->param.subscribe_event.evt_bitmap =
 		SUBSCRIBE_EVT_RSSI_LOW | SUBSCRIBE_EVT_RSSI_HIGH;
-	misc->param.subscribe_event.low_rssi_freq = 1;
+	misc->param.subscribe_event.low_rssi_freq = 0;
 	misc->param.subscribe_event.low_rssi = priv->last_rssi_low;
 	misc->param.subscribe_event.high_rssi_freq = 0;
 	misc->param.subscribe_event.high_rssi = priv->last_rssi_high;
@@ -7676,6 +7704,9 @@ mlan_status woal_multi_ap_cfg(moal_private *priv, t_u8 wait_option, t_u8 flag)
 	if (status != MLAN_STATUS_SUCCESS)
 		goto done;
 
+	PRINTM(MCMND, "%s: %s 4addr mode\n", priv->netdev->name,
+	       flag ? "Enable" : "Disable");
+
 done:
 	if (status != MLAN_STATUS_PENDING)
 		kfree(req);
@@ -8292,7 +8323,7 @@ static int parse_tx_pwr_string(moal_handle *handle, const char *s, size_t len,
 	card_type = (handle->card_type) & 0xff;
 	if ((card_type == CARD_TYPE_9098) || (card_type == CARD_TYPE_9097) ||
 	    (card_type == CARD_TYPE_9177) || (card_type == CARD_TYPE_IW624) ||
-	    (card_type == CARD_TYPE_AW693))
+	    (card_type == CARD_TYPE_AW693) || (card_type == CARD_TYPE_IW610))
 		pow_conv = MTRUE;
 
 	flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
@@ -8643,6 +8674,32 @@ static int parse_tx_frame_string(const char *s, size_t len,
 	if (string == NULL)
 		return -ENOMEM;
 
+	/*Initialize the parameters to default values to be used*/
+	d->data_rate = 0x1100;
+	d->frame_pattern = 0xB496DEB6;
+	d->frame_length = 0x400;
+	d->enable = 0;
+	d->short_preamble = -1;
+	d->short_gi = 0;
+	d->adv_coding = -1;
+	d->tx_bf = 0;
+	d->gf_mode = 0;
+	d->stbc = 0;
+	d->adjust_burst_sifs = 0;
+	d->burst_sifs_in_us = 0;
+	d->signal_bw = -1;
+	d->NumPkt = -1;
+	d->MaxPE = -1;
+	d->BeamChange = -1;
+	d->Dcm = -1;
+	d->Doppler = -1;
+	d->MidP = -1;
+	d->QNum = -1;
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		d->bssid[i] = 0xff;
+	}
+
 	moal_memcpy_ext(NULL, string, s + strlen("tx_frame="),
 			len - strlen("tx_frame="), TX_FRAME_STR_LEN - 1);
 
@@ -8747,12 +8804,7 @@ static int parse_tx_frame_string(const char *s, size_t len,
 		}
 	}
 
-	if ((d->enable > 1) || (d->frame_length == 0) ||
-	    (d->adjust_burst_sifs > 1) || (d->burst_sifs_in_us > 255) ||
-	    (d->short_preamble > 1) ||
-	    (d->act_sub_ch == 2 || d->act_sub_ch > 3) || (d->short_gi > 1) ||
-	    (d->adv_coding > 1) || (d->tx_bf > 1) || (d->gf_mode > 1) ||
-	    (d->stbc > 1))
+	if (d->enable > 1)
 		ret = -EINVAL;
 done:
 	kfree(tmp);
@@ -8953,6 +9005,50 @@ done:
 	return ret;
 }
 
+/*
+ *  @brief Parse mfg cmd otp cal data rdwr
+ *
+ *  @param handle   A pointer to moal_handle structure
+ *  @param s        A pointer to user buffer
+ *  @param len      Length of user buffer
+ *  @param d        A pointer to mfg_cmd_generic_cfg struct
+ *  @return         0 on success, -EINVAL otherwise
+ */
+
+static int parse_otp_cal_data_rd_wr_string(const char *s, size_t len,
+					   mfg_cmd_otp_cal_data_rd_wr_t *d)
+{
+	int ret = MLAN_STATUS_SUCCESS;
+	char *string = NULL;
+	char *pos = NULL;
+	int i = 0;
+
+	ENTER();
+	if (!s || !d) {
+		LEAVE();
+		return -EINVAL;
+	}
+
+	string = (char *)&(s[strlen("otp_cal_data_rd_wr=")]);
+	pos = strsep(&string, " \t");
+	d->action = (t_u16)woal_string_to_number(pos);
+	if (d->action == MFALSE)
+		goto done;
+
+	for (i = 0; i < CAL_DATA_LEN; i++) {
+		pos = strsep(&string, " \t");
+		if (pos) {
+			d->cal_data[i] = (t_u16)woal_string_to_number(pos);
+			d->cal_data_len++;
+		}
+	}
+	if (d->action > 1)
+		ret = -EINVAL;
+done:
+	LEAVE();
+	return ret;
+}
+
 /**
  *  @brief This function sends RF test mode command in firmware
  *
@@ -9047,6 +9143,13 @@ mlan_status woal_process_rf_test_mode_cmd(moal_handle *handle, t_u32 cmd,
 			err = MTRUE;
 		}
 		break;
+	case MFG_CMD_OTP_CAL_DATA:
+		misc->sub_command = MLAN_OID_MISC_OTP_CAL_DATA_RD_WR;
+		if (parse_otp_cal_data_rd_wr_string(
+			    buffer, len, &misc->param.mfg_otp_cal_data_rd_wr)) {
+			err = MTRUE;
+		}
+		break;
 	default:
 		err = MTRUE;
 	}
@@ -9205,6 +9308,15 @@ mlan_status woal_process_rf_test_mode_cmd(moal_handle *handle, t_u32 cmd,
 				misc->param.mfg_otp_mac_addr_rd_wr.mac_addr[i];
 		}
 		break;
+	case MFG_CMD_OTP_CAL_DATA:
+		handle->rf_data->mfg_otp_cal_data_rd_wr.action =
+			misc->param.mfg_otp_cal_data_rd_wr.action;
+		for (i = 0; i < misc->param.mfg_otp_cal_data_rd_wr.cal_data_len;
+		     i++) {
+			handle->rf_data->mfg_otp_cal_data_rd_wr.cal_data[i] =
+				misc->param.mfg_otp_cal_data_rd_wr.cal_data[i];
+		}
+		break;
 	}
 done:
 	if (err || ret != MLAN_STATUS_PENDING)
diff --git a/mlinux/moal_main.c b/mlinux/moal_main.c
index 16555e4..07ee1d6 100644
--- a/mlinux/moal_main.c
+++ b/mlinux/moal_main.c
@@ -4,7 +4,7 @@
  * driver.
  *
  *
- * Copyright 2008-2024, 2024 NXP
+ * Copyright 2008-2024 NXP
  *
  * This software file (the File) is distributed by NXP
  * under the terms of the GNU General Public License Version 2, June 1991
@@ -75,6 +75,16 @@ Change log:
 #endif
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+#include <linux/ktime.h>
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+#include <linux/hrtimer.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+#include <linux/rtc.h>
+#include <linux/utsname.h>
+#endif
+
 /********************************************************
 		 Global Variables
  ********************************************************/
@@ -604,8 +614,8 @@ static struct _card_info card_info_SD9177 = {
 };
 #endif
 
-#ifdef SDIW615
-static struct _card_info card_info_SDIW615 = {
+#ifdef SDIW610
+static struct _card_info card_info_SDIW610 = {
 	.embedded_supp = 1,
 	.drcs = 1,
 	.go_noa = 1,
@@ -620,8 +630,8 @@ static struct _card_info card_info_SDIW615 = {
 	.rev_id_reg = 0xc8,
 	.host_strap_reg = 0xf4,
 	.magic_reg = 0xf0,
-	.fw_name = SDIW615_DEFAULT_COMBO_FW_NAME,
-	.fw_name_wlan = SDIW615_DEFAULT_WLAN_FW_NAME,
+	.fw_name = SDIW610_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = SDIW610_DEFAULT_WLAN_FW_NAME,
 #ifdef SDIO
 	.dump_fw_info = DUMP_FW_SDIO_V3,
 	.dump_fw_ctrl_reg = 0xf9,
@@ -637,8 +647,10 @@ static struct _card_info card_info_SDIW615 = {
 	.fw_stuck_code_reg = 0xEB,
 	.fw_reset_reg = 0x0EE,
 	.fw_reset_val = 0x99,
-	.slew_rate_reg = 0x90002328,
-	.slew_rate_bit_offset = 12,
+	.fw_wakeup_reg = 0,
+	.fw_wakeup_val = 2,
+	.slew_rate_reg = 0x45001064,
+	.slew_rate_bit_offset = 16,
 #endif
 	.sniffer_support = 1,
 	.per_pkt_cfg_support = 1,
@@ -773,6 +785,7 @@ static struct _card_info card_info_PCIEAW693 = {
 	.rev_id_reg = 0x8,
 	.host_strap_reg = 0x1c70,
 	.magic_reg = 0x1c74,
+	.boot_mode_reg = 0x1c8c,
 	.fw_name = PCIEAW693_DEFAULT_COMBO_FW_NAME,
 	.fw_name_wlan = PCIEAW693_DEFAULT_WLAN_FW_NAME,
 	.fw_stuck_code_reg = 0x1c80,
@@ -910,8 +923,8 @@ static struct _card_info card_info_USBIW624 = {
 };
 #endif
 
-#ifdef USBIW615
-static struct _card_info card_info_USBIW615 = {
+#ifdef USBIW610
+static struct _card_info card_info_USBIW610 = {
 	.embedded_supp = 1,
 	.drcs = 1,
 	.go_noa = 1,
@@ -923,8 +936,8 @@ static struct _card_info card_info_USBIW615 = {
 	.rx_rate_max = 412,
 	.feature_control = FEATURE_CTRL_DEFAULT,
 	.histogram_table_num = 3,
-	.fw_name = USBIW615_DEFAULT_COMBO_FW_NAME,
-	.fw_name_wlan = USBIW615_DEFAULT_WLAN_FW_NAME,
+	.fw_name = USBIW610_DEFAULT_COMBO_FW_NAME,
+	.fw_name_wlan = USBIW610_DEFAULT_WLAN_FW_NAME,
 	.sniffer_support = 1,
 	.per_pkt_cfg_support = 1,
 };
@@ -1041,6 +1054,7 @@ static mlan_callbacks woal_callbacks = {
 	.moal_assert = moal_assert,
 	.moal_hist_data_add = moal_hist_data_add,
 	.moal_updata_peer_signal = moal_updata_peer_signal,
+	.moal_get_host_time_ns = moal_get_host_time_ns,
 	.moal_do_div = moal_do_div,
 	.moal_tp_accounting = moal_tp_accounting,
 	.moal_tp_accounting_rx_param = moal_tp_accounting_rx_param,
@@ -1201,6 +1215,34 @@ void woal_clean_up(moal_handle *handle)
 		MOAL_REL_SEMAPHORE(&handle->async_sem);
 	}
 #endif
+#ifdef UAP_CFG80211
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
+	if (IS_STA_CFG80211(cfg80211_wext) && handle->is_cac_timer_set &&
+	    (handle->cac_bss_index != 0xff)) {
+		woal_cancel_timer(&handle->cac_timer);
+		handle->is_cac_timer_set = MFALSE;
+		handle->cac_period = MFALSE;
+		priv = handle->priv[handle->cac_bss_index];
+		if (priv) {
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+			cfg80211_cac_event(priv->netdev, &handle->dfs_channel,
+					   NL80211_RADAR_CAC_ABORTED,
+					   GFP_KERNEL);
+#else
+			cfg80211_cac_event(priv->netdev,
+					   NL80211_RADAR_CAC_ABORTED,
+					   GFP_KERNEL);
+#endif
+			if (priv->csa_workqueue)
+				flush_workqueue(priv->csa_workqueue);
+		}
+		memset(&handle->dfs_channel, 0,
+		       sizeof(struct cfg80211_chan_def));
+		handle->cac_bss_index = 0xff;
+	}
+#endif
+#endif
+
 	for (i = 0; i < handle->priv_num; i++) {
 		if (handle->priv[i]) {
 			priv = handle->priv[i];
@@ -1236,7 +1278,6 @@ void woal_clean_up(moal_handle *handle)
 			}
 #endif
 #endif
-
 			// stop bgscan
 #ifdef STA_CFG80211
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
@@ -1287,6 +1328,32 @@ void woal_send_auto_recovery_complete_event(moal_handle *handle)
 	reset_handle = NULL;
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+/**
+ *  @brief This function reads hostname
+ *
+ *  @hostname	Pointer to hostname
+ *  @return	N/A
+ */
+static void woal_get_hostname(char *hostname)
+{
+	snprintf(hostname, MAX_HOSTNAME_LEN, "%s ", utsname()->nodename);
+}
+
+/**
+ *  @brief This function reads real time
+ *
+ *  @tstamp	Pointer to timestamp
+ *  @return	N/A
+ */
+static void woal_get_timestamp(char *tstamp)
+{
+	struct rtc_time time;
+	time = rtc_ktime_to_tm(ktime_get_real());
+	snprintf(tstamp, MAX_TIME_LEN, "%ptRs\n", &time);
+}
+#endif
+
 /**
  *  @brief This function process FW hang
  *
@@ -2142,6 +2209,9 @@ mlan_status woal_update_drv_tbl(moal_handle *handle, int drv_mode_local)
 #endif
 	int max_nan_bss = handle->params.max_nan_bss;
 	int max_dfs_bss = MAX_DFS_BSS;
+#ifdef UAP_SUPPORT
+	int max_uap_bss_limit = MAX_UAP_BSS;
+#endif
 
 	ENTER();
 
@@ -2161,7 +2231,9 @@ mlan_status woal_update_drv_tbl(moal_handle *handle, int drv_mode_local)
 
 #ifdef UAP_SUPPORT
 	if (drv_mode_local & DRV_MODE_UAP) {
-		if ((max_uap_bss < 1) || (max_uap_bss > MAX_UAP_BSS)) {
+		if (handle->pref_mac)
+			max_uap_bss_limit = MAX_UAP_BSS_DUAL_MAC;
+		if ((max_uap_bss < 1) || (max_uap_bss > max_uap_bss_limit)) {
 			PRINTM(MWARN,
 			       "Unsupported max_uap_bss (%d), setting to default\n",
 			       max_uap_bss);
@@ -2356,6 +2428,10 @@ mlan_status woal_init_sw(moal_handle *handle)
 	drvdbg = handle->params.drvdbg;
 #endif
 
+#ifdef MFG_CMD_SUPPORT
+	mfg_mode = handle->params.mfg_mode;
+#endif
+
 	handle->fw_dump_status = MFALSE;
 
 #ifdef STA_SUPPORT
@@ -2549,6 +2625,7 @@ mlan_status woal_init_sw(moal_handle *handle)
 		(t_u32)moal_extflg_isset(handle, EXT_FIX_BCN_BUF);
 	device.auto_ds = (t_u32)handle->params.auto_ds;
 	device.ext_scan = (t_u8)handle->params.ext_scan;
+	device.bootup_cal_ctrl = handle->params.bootup_cal_ctrl;
 	device.ps_mode = (t_u32)handle->params.ps_mode;
 	device.passive_to_active_scan = (t_u8)handle->params.p2a_scan;
 	device.max_tx_buf = (t_u32)handle->params.max_tx_buf;
@@ -2620,6 +2697,7 @@ mlan_status woal_init_sw(moal_handle *handle)
 	device.uap_max_sta = handle->params.uap_max_sta;
 	device.wacp_mode = handle->params.wacp_mode;
 #endif
+	device.fw_data_cfg = handle->params.fw_data_cfg;
 	device.mcs32 = handle->params.mcs32;
 	device.hs_wake_interval = handle->params.hs_wake_interval;
 	device.indication_gpio = handle->params.indication_gpio;
@@ -2631,7 +2709,8 @@ mlan_status woal_init_sw(moal_handle *handle)
 #endif
 	device.second_mac = handle->second_mac;
 	device.antcfg = handle->params.antcfg;
-	device.dmcs = moal_extflg_isset(handle, EXT_DMCS);
+	device.dmcs = handle->params.dmcs;
+	device.pref_dbc = handle->params.pref_dbc;
 	device.reject_addba_req = handle->params.reject_addba_req;
 
 	for (i = 0; i < handle->drv_mode.intf_num; i++) {
@@ -2647,6 +2726,13 @@ mlan_status woal_init_sw(moal_handle *handle)
 		device.bss_attr[i].bss_virtual =
 			handle->drv_mode.bss_attr[i].bss_virtual;
 	}
+
+	device.max_tx_pending = handle->params.mclient_scheduling ?
+					MCLIENT_MAX_TX_PENDING :
+					MAX_TX_PENDING;
+	device.tx_budget = handle->params.tx_budget;
+	device.mclient_scheduling = handle->params.mclient_scheduling;
+
 	moal_memcpy_ext(handle, &device.callbacks, &woal_callbacks,
 			sizeof(mlan_callbacks), sizeof(mlan_callbacks));
 	if (!handle->params.amsdu_deaggr)
@@ -2914,6 +3000,9 @@ static t_u32 woal_set_sdio_slew_rate(moal_handle *handle)
 	t_u32 new_value = 0;
 	t_u32 reg_type = MLAN_REG_MAC;
 	int status;
+	t_u32 i = 0;
+	t_u32 roll_count = 1;
+	t_u8 slew_rate_bit_offset = handle->card_info->slew_rate_bit_offset;
 
 	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
 	if (!priv)
@@ -2923,13 +3012,18 @@ static t_u32 woal_set_sdio_slew_rate(moal_handle *handle)
 	    (handle->params.slew_rate > 3 || handle->params.slew_rate < 0))
 		return MLAN_STATUS_FAILURE;
 #if defined(SD9098) || defined(SD9097) || defined(SDIW624) ||                  \
-	defined(SDAW693) || defined(SD9177) || defined(SDIW615)
+	defined(SDAW693) || defined(SD9177) || defined(SDIW610)
 	if (IS_SD9098(handle->card_type) || IS_SD9097(handle->card_type) ||
-	    IS_SDIW624(handle->card_type) || IS_SDIW615(handle->card_type) ||
+	    IS_SDIW624(handle->card_type) || IS_SDIW610(handle->card_type) ||
 	    IS_SD9177(handle->card_type))
 		reg_type = MLAN_REG_CIU;
 #endif
 
+#if defined(SDIW610)
+	if (IS_SDIW610(handle->card_type))
+		roll_count = 6;
+#endif
+
 	status = woal_getset_regrdwr(priv, MLAN_ACT_GET, reg_type,
 				     handle->card_info->slew_rate_reg, &value);
 	if (status < 0) {
@@ -2937,9 +3031,12 @@ static t_u32 woal_set_sdio_slew_rate(moal_handle *handle)
 		ret = MLAN_STATUS_FAILURE;
 		goto done;
 	}
-	new_value = value & ~(0x3 << handle->card_info->slew_rate_bit_offset);
-	new_value |= (t_u32)handle->params.slew_rate
-		     << handle->card_info->slew_rate_bit_offset;
+	for (i = 0; i < roll_count; i++) {
+		slew_rate_bit_offset += 2 * i;
+		new_value = value & ~(0x3 << slew_rate_bit_offset);
+		new_value |= (t_u32)handle->params.slew_rate
+			     << slew_rate_bit_offset;
+	}
 
 	if (value != new_value) {
 		PRINTM(MMSG, "Set REG 0x%8x: 0x%x slew_rate=%d\n",
@@ -3993,11 +4090,12 @@ static ssize_t woal_set_rps_map(struct netdev_rx_queue *queue, const char *buf,
 static mlan_status woal_add_card_dpc(moal_handle *handle)
 {
 	mlan_status ret = MLAN_STATUS_SUCCESS;
-	int i, j;
+	int i;
 	char str_buf[MLAN_MAX_VER_STR_LEN];
 
 #if defined(CONFIG_RPS)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+	int j;
 	moal_private *priv_rps = NULL;
 	t_u8 rps_buf[3];
 #endif
@@ -4521,7 +4619,7 @@ static mlan_status woal_init_fw_dpc(moal_handle *handle)
 			    !IS_USB9098(handle->card_type) &&
 			    !IS_USB9097(handle->card_type) &&
 			    !IS_USBIW624(handle->card_type) &&
-			    !IS_USBIW615(handle->card_type) &&
+			    !IS_USBIW610(handle->card_type) &&
 			    !IS_USB8978(handle->card_type))
 				ret = woal_reset_usb_dev(handle);
 			goto done;
@@ -5408,6 +5506,8 @@ mlan_status woal_init_uap_dev(struct net_device *dev, moal_private *priv)
 	dev->hard_header_len += MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) +
 				priv->extra_tx_head_len;
 #endif
+	if (priv->phandle->params.mclient_scheduling)
+		dev->tx_queue_len = MCLIENT_MAX_TX_PENDING;
 	/** don't need register to wext */
 	if (priv->bss_type == MLAN_BSS_TYPE_DFS) {
 		LEAVE();
@@ -5429,6 +5529,27 @@ mlan_status woal_init_uap_dev(struct net_device *dev, moal_private *priv)
 }
 #endif /* UAP_SUPPORT */
 
+/**
+ * @brief This function sets thresholds for tx_pending
+ *
+ *  @param handle    A pointer to moal_handle structure
+ *  @param priv      A pointer to moal_private structure
+ *
+ *  @return          N/A
+ */
+static void woal_set_interface_pending_limits(moal_handle *handle,
+					      moal_private *priv)
+{
+	priv->max_tx_pending = MAX_TX_PENDING;
+	priv->low_tx_pending = LOW_TX_PENDING;
+
+	if (handle->params.mclient_scheduling &&
+	    priv->bss_type == MLAN_BSS_TYPE_UAP) {
+		priv->max_tx_pending = MCLIENT_MAX_TX_PENDING;
+		priv->low_tx_pending = MCLIENT_LOW_TX_PENDING;
+	}
+}
+
 /**
  * @brief This function adds a new interface. It will
  *      allocate, initialize and register the device.
@@ -5562,9 +5683,8 @@ moal_private *woal_add_interface(moal_handle *handle, t_u8 bss_index,
 
 #ifdef STA_CFG80211
 	INIT_LIST_HEAD(&priv->dhcp_discover_queue);
-	/* CID - 10017917 */
-	// coverity[side_effect_free: SUPPRESS]
 	spin_lock_init(&priv->dhcp_discover_lock);
+	hash_init(priv->hlist);
 #endif
 #ifdef STA_CFG80211
 #ifdef STA_SUPPORT
@@ -5870,6 +5990,7 @@ void woal_remove_interface(moal_handle *handle, t_u8 bss_index)
 	woal_flush_tcp_sess_queue(priv);
 #ifdef STA_CFG80211
 	woal_flush_dhcp_discover_queue(priv);
+	woal_flush_arp_request_entry(priv);
 #endif
 
 #ifdef STA_CFG80211
@@ -6504,6 +6625,7 @@ int woal_close(struct net_device *dev)
 	woal_flush_tx_stat_queue(priv);
 #ifdef STA_CFG80211
 	woal_flush_dhcp_discover_queue(priv);
+	woal_flush_arp_request_entry(priv);
 #endif
 
 	if ((priv->media_connected == MTRUE)
@@ -7302,11 +7424,166 @@ void woal_remove_tx_info(moal_private *priv, t_u8 tx_seq_num)
 
 #if defined(STA_CFG80211)
 /**
- *  @brief This function flushes timesync info queue
+ *  @brief This function flushes arp request entry from list
  *
- *  @param priv      		A pointer to moal_private structure
+ *  @param priv        A pointer to moal_private structure
  *
- *  @return	         N/A
+ *  @return            N/A
+ */
+t_void woal_flush_arp_request_entry(moal_private *priv)
+{
+	struct arp_entry *arp = NULL;
+	struct hlist_node *tmp = NULL;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&priv->arp_request_lock, flags);
+	hash_for_each_safe (priv->hlist, i, tmp, arp, arp_hlist) {
+		hlist_del(&arp->arp_hlist);
+		kfree(arp);
+	}
+	spin_unlock_irqrestore(&priv->arp_request_lock, flags);
+}
+
+/**
+ *  @brief This function generates constant factor for hash
+ *
+ *  @param factor     Constant factor of hash
+ *
+ *  @return           Returns updated hash factor
+ */
+static t_u32 woal_generate_hash_factor(t_u32 factor)
+{
+	factor *= 0xcc9e2d51;
+	factor = (factor << 15) | (factor >> 17);
+	factor *= 0x1b873593;
+
+	// coverity[integer_overflow:SUPPRESS]
+	return factor;
+}
+
+/**
+ *  @brief This function generates hash based on murmurhash
+ *
+ *  @param data       A pointer to input for hash
+ *  @param len        Length of input
+ *  @param seed       Seed value for hash
+ *
+ *  @return           Returns hash value
+ */
+static t_u32 woal_generate_hash(t_u8 *data, size_t len, t_u32 seed)
+{
+	t_u32 hash = seed;
+	t_u32 factor;
+	size_t i;
+
+	for (i = len >> 2; i; i--) {
+		memcpy(&factor, data, sizeof(t_u32));
+		data += sizeof(t_u32);
+		hash ^= woal_generate_hash_factor(factor);
+		hash = (hash << 13) | (hash >> 19);
+		hash = hash * 5 + 0xe6546b64;
+	}
+
+	factor = 0;
+	for (i = len & 3; i; i--) {
+		factor <<= 8;
+		factor |= data[i - 1];
+	}
+
+	hash ^= woal_generate_hash_factor(factor);
+	hash ^= len;
+	hash ^= hash >> 16;
+	hash *= 0x85ebca6b;
+	hash ^= hash >> 13;
+	hash *= 0xc2b2ae35;
+	hash ^= hash >> 16;
+
+	// coverity[integer_overflow:SUPPRESS]
+	return hash;
+}
+
+/**
+ *  @brief This function generates hash for arp request
+ *
+ *  @param skb        A pointer to sk_buff structure
+ *
+ *  @return           Returns hash of arp request
+ */
+t_u32 woal_generate_arp_request_hash(struct sk_buff *skb)
+{
+	struct ethhdr *eth;
+	struct arphdr *arp;
+	t_u32 hash_key = 0;
+	t_u32 min_len = sizeof(*eth) + sizeof(*arp);
+
+	eth = (struct ethhdr *)(skb->data);
+	if (skb->len < min_len || eth->h_proto != htons(ETH_P_ARP))
+		return 0;
+
+	arp = (struct arphdr *)((u8 *)eth + ETH_HLEN);
+	if (arp->ar_op == htons(ARPOP_REQUEST)) {
+		/*
+		 * since a hash value is required to distinguish ARP
+		 * request.
+		 */
+		hash_key = woal_generate_hash((t_u8 *)arp,
+					      sizeof(struct arp_hdr), 0);
+		return hash_key;
+	}
+	return 0;
+}
+
+/**
+ *  @brief This function adds arp request hash to list
+ *
+ *  @param priv        A pointer to moal_private structure
+ *  @param hash_key    hash key of arp request
+ *
+ *  @return            N/A
+ */
+t_void woal_add_arp_request_node(moal_private *priv, t_u32 hash_key)
+{
+	struct arp_entry *node = NULL;
+	struct hlist_node *temp = NULL;
+	unsigned long flags;
+	bool found = false;
+	int i;
+
+	spin_lock_irqsave(&priv->arp_request_lock, flags);
+	hash_for_each_safe (priv->hlist, i, temp, node, arp_hlist) {
+		if (node && node->hash_key == hash_key) {
+			found = true;
+			break;
+		}
+
+		if (node &&
+		    (jiffies - node->ageout_jiffies) >= ARP_REQ_AGEOUT_TIME) {
+			hlist_del(&node->arp_hlist);
+			kfree(node);
+		}
+	}
+
+	if (!found) {
+		node = kzalloc(sizeof(struct arp_entry), GFP_ATOMIC);
+		if (!node) {
+			PRINTM(MERROR, "Failed to alloc memory for arp node\n");
+			return;
+		}
+
+		node->hash_key = hash_key;
+		node->ageout_jiffies = jiffies;
+		hash_add(priv->hlist, &node->arp_hlist, hash_key);
+	}
+	spin_unlock_irqrestore(&priv->arp_request_lock, flags);
+}
+
+/**
+ *  @brief This function flushes dhcp discover info queue
+ *
+ *  @param priv      	A pointer to moal_private structure
+ *
+ *  @return	        N/A
  */
 void woal_flush_dhcp_discover_queue(moal_private *priv)
 {
@@ -7390,8 +7667,6 @@ t_void woal_add_dhcp_discover_node(moal_private *priv, t_u32 transaction_id,
 		}
 		spin_unlock_irqrestore(&priv->dhcp_discover_lock, flags);
 	}
-	/* CID - 36267456 */
-	// coverity[leaked_storage:SUPPRESS]
 }
 
 /**
@@ -7758,7 +8033,7 @@ static void woal_tcp_ack_timer_func(void *context)
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
 			atomic_inc(&priv->wmm_tx_pending[index]);
 			if (atomic_read(&priv->wmm_tx_pending[index]) >=
-			    MAX_TX_PENDING) {
+			    priv->max_tx_pending) {
 				struct netdev_queue *txq = netdev_get_tx_queue(
 					priv->netdev, index);
 				netif_tx_stop_queue(txq);
@@ -7818,7 +8093,7 @@ static void woal_send_tcp_ack(moal_private *priv, struct sk_buff *skb,
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
 		atomic_inc(&priv->wmm_tx_pending[index]);
 		if (atomic_read(&priv->wmm_tx_pending[index]) >=
-		    MAX_TX_PENDING) {
+		    priv->max_tx_pending) {
 			struct netdev_queue *txq =
 				netdev_get_tx_queue(priv->netdev, index);
 			netif_tx_stop_queue(txq);
@@ -7880,6 +8155,8 @@ static int woal_process_tcp_ack(moal_private *priv, mlan_buffer *pmbuf)
 		LEAVE();
 		return 0;
 	}
+
+	pmbuf->flags |= MLAN_BUF_FLAG_TCP_PKT;
 	tcph = (struct tcphdr *)((t_u8 *)iph + iph->ihl * 4);
 
 	if (*((t_u8 *)tcph + 13) == 0x10) {
@@ -8273,13 +8550,21 @@ static void woal_start_xmit(moal_private *priv, struct sk_buff *skb)
 #endif
 #endif
 #ifdef STA_CFG80211
-	if (priv->multi_ap_flag && priv->bss_type == MLAN_BSS_TYPE_STA) {
+	if (priv->wdev->use_4addr &&
+	    priv->wdev->iftype == NL80211_IFTYPE_STATION) {
 		t_u32 transaction_id;
 		transaction_id = woal_get_dhcp_discover_transation_id(skb);
 		if (transaction_id)
 			woal_add_dhcp_discover_node(priv, transaction_id,
 						    pmbuf);
 	}
+
+	if (priv->wdev->use_4addr &&
+	    priv->wdev->iftype == NL80211_IFTYPE_STATION) {
+		t_u32 hash_key = woal_generate_arp_request_hash(skb);
+		if (hash_key)
+			woal_add_arp_request_node(priv, hash_key);
+	}
 #endif
 
 	if (priv->enable_tcp_ack_enh && priv->media_connected) {
@@ -8321,7 +8606,7 @@ static void woal_start_xmit(moal_private *priv, struct sk_buff *skb)
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
 		atomic_inc(&priv->wmm_tx_pending[index]);
 		if (atomic_read(&priv->wmm_tx_pending[index]) >=
-		    MAX_TX_PENDING) {
+		    priv->max_tx_pending) {
 			struct netdev_queue *txq =
 				netdev_get_tx_queue(priv->netdev, index);
 			netif_tx_stop_queue(txq);
@@ -8383,7 +8668,8 @@ netdev_tx_t woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		priv->stats.tx_dropped++;
 		goto done;
 	}
-	if (moal_extflg_isset(priv->phandle, EXT_TX_WORK) &&
+	if (!priv->wdev->use_4addr &&
+	    moal_extflg_isset(priv->phandle, EXT_TX_WORK) &&
 	    (skb->protocol != htons(NXP_ETH_P_EAPOL))) {
 		spin_lock_bh(&(priv->tx_q.lock));
 		__skb_queue_tail(&(priv->tx_q), skb);
@@ -8832,6 +9118,8 @@ void woal_init_priv(moal_private *priv, t_u8 wait_option)
 	priv->multi_ap_flag = 0;
 #endif
 #endif
+	priv->auth_tx_wait_time = AUTH_TX_DEFAULT_WAIT_TIME;
+	woal_set_interface_pending_limits(priv->phandle, priv);
 	LEAVE();
 }
 
@@ -9216,9 +9504,9 @@ static int woal_get_card_info(moal_handle *phandle)
 		phandle->card_info = &card_info_SDIW624;
 		break;
 #endif
-#ifdef SDIW615
-	case CARD_TYPE_SDIW615:
-		phandle->card_info = &card_info_SDIW615;
+#ifdef SDIW610
+	case CARD_TYPE_SDIW610:
+		phandle->card_info = &card_info_SDIW610;
 		break;
 #endif
 #ifdef SD9177
@@ -9285,9 +9573,9 @@ static int woal_get_card_info(moal_handle *phandle)
 		phandle->card_info = &card_info_USBIW624;
 		break;
 #endif
-#ifdef USBIW615
-	case CARD_TYPE_USBIW615:
-		phandle->card_info = &card_info_USBIW615;
+#ifdef USBIW610
+	case CARD_TYPE_USBIW610:
+		phandle->card_info = &card_info_USBIW610;
 		break;
 #endif
 #ifdef SD8987
@@ -10464,6 +10752,12 @@ t_void woal_store_firmware_dump(moal_handle *phandle, mlan_event *pmevent)
 					       GFP_ATOMIC :
 					       GFP_KERNEL;
 				fwdump_fname = kzalloc(64, flag);
+				if (!fwdump_fname) {
+					PRINTM(MERROR,
+					       "Failed to allocate memory for fwdump fname\n");
+					LEAVE();
+					return;
+				}
 			}
 			snprintf(fwdump_fname, MAX_BUF_LEN, "%s/file_fwdump",
 				 path_name);
@@ -10489,11 +10783,7 @@ t_void woal_store_firmware_dump(moal_handle *phandle, mlan_event *pmevent)
 		LEAVE();
 		return;
 	}
-	if (pmevent->event_len > OFFSET_SEQNUM) {
-		phandle->fw_dump_len += pmevent->event_len - OFFSET_SEQNUM;
-	} else {
-		PRINTM(MERROR, "event_len is invalid\n");
-	}
+	phandle->fw_dump_len += pmevent->event_len - OFFSET_SEQNUM;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
 	vfs_write(pfile_fwdump,
 		  (const char __user *)pmevent->event_buf + OFFSET_SEQNUM,
@@ -10663,6 +10953,10 @@ static int woal_dump_moal_drv_info(moal_handle *phandle, t_u8 *buf)
 	struct usb_card_rec *cardp = NULL;
 #endif
 	char str_buf[MLAN_MAX_VER_STR_LEN];
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	char hostname[MAX_HOSTNAME_LEN];
+	char tstamp[MAX_TIME_LEN];
+#endif
 
 	ENTER();
 	if (!phandle || !buf) {
@@ -10677,6 +10971,12 @@ static int woal_dump_moal_drv_info(moal_handle *phandle, t_u8 *buf)
 	ptr = (char *)buf;
 	ptr += snprintf(ptr, MAX_BUF_LEN,
 			"------------moal_debug_info-------------\n");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	woal_get_hostname(hostname);
+	woal_get_timestamp(tstamp);
+	ptr += snprintf(ptr, MAX_HOSTNAME_LEN, "Host:%s ", hostname);
+	ptr += snprintf(ptr, MAX_TIME_LEN, "Timestamp:%s", tstamp);
+#endif
 	woal_get_version(phandle, str_buf, sizeof(str_buf) - 1);
 	ptr += snprintf(ptr, MAX_BUF_LEN, "Driver version = %s\n", str_buf);
 	ptr += snprintf(ptr, MAX_BUF_LEN, "main_state = %d\n",
@@ -11535,6 +11835,10 @@ void woal_moal_debug_info(moal_private *priv, moal_handle *handle, u8 flag)
 	struct usb_card_rec *cardp = NULL;
 #endif
 	char buf[MLAN_MAX_VER_STR_LEN];
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	char hostname[MAX_HOSTNAME_LEN];
+	char tstamp[MAX_TIME_LEN];
+#endif
 	int i = 0;
 
 	ENTER();
@@ -11569,6 +11873,11 @@ void woal_moal_debug_info(moal_private *priv, moal_handle *handle, u8 flag)
 	}
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+	woal_get_hostname(hostname);
+	woal_get_timestamp(tstamp);
+	PRINTM(MERROR, "Host:%s Timestamp:%s", hostname, tstamp);
+#endif
 	woal_get_version(phandle, buf, sizeof(buf) - 1);
 	PRINTM(MERROR, "Driver version = %s\n", buf);
 	PRINTM(MERROR, "main_state = %d\n", phandle->main_state);
@@ -12016,6 +12325,10 @@ t_void woal_evt_work_queue(struct work_struct *work)
 			woal_host_mlme_process_assoc_resp(
 				(moal_private *)evt->priv, &evt->assoc_info);
 			break;
+		case WOAL_EVENT_ASSOC_TIMEOUT:
+			woal_host_mlme_process_assoc_timeout(
+				(moal_private *)evt->priv, evt->assoc_bss);
+			break;
 #endif
 #endif
 #ifdef UAP_SUPPORT
@@ -12683,6 +12996,10 @@ moal_handle *woal_add_card(void *card, struct device *dev, moal_if_ops *if_ops,
 	drvdbg = handle->params.drvdbg;
 #endif
 
+#ifdef MFG_CMD_SUPPORT
+	mfg_mode = handle->params.mfg_mode;
+#endif
+
 	if (handle->params.mac_addr
 #ifdef MFG_CMD_SUPPORT
 	    && handle->params.mfg_mode != MLAN_INIT_PARA_ENABLED
@@ -13552,6 +13869,11 @@ static void woal_post_reset(moal_handle *handle)
 #ifdef DEBUG_LEVEL1
 	drvdbg = handle->params.drvdbg;
 #endif
+
+#ifdef MFG_CMD_SUPPORT
+	mfg_mode = handle->params.mfg_mode;
+#endif
+
 	handle->fw_dump_status = MFALSE;
 	handle->driver_status = MFALSE;
 	handle->hardware_status = HardwareStatusReady;
@@ -14115,6 +14437,7 @@ static void woal_cleanup_module(void)
 			woal_flush_tx_stat_queue(handle->priv[i]);
 #ifdef STA_CFG80211
 			woal_flush_dhcp_discover_queue(handle->priv[i]);
+			woal_flush_arp_request_entry(handle->priv[i]);
 #endif
 #endif
 		}
diff --git a/mlinux/moal_main.h b/mlinux/moal_main.h
index dd0efd2..50f36bb 100644
--- a/mlinux/moal_main.h
+++ b/mlinux/moal_main.h
@@ -46,6 +46,7 @@ Change log:
 #include <linux/sched.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
+#include <linux/hashtable.h>
 #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 10, 17)
 #include <uapi/linux/sched/types.h>
 #endif
@@ -313,10 +314,29 @@ typedef t_u8 BOOLEAN;
 #define CARD_TYPE_PCIEIW624_UARTUART 7 // As per datasheet/SoC design
 /** card type PCIEIW624_UARTSPI */
 #define CARD_TYPE_PCIEIW624_UARTSPI 5 // As per datasheet/SoC design
+/** card type SDIW615_sd_uart_spi **/
+#ifdef SDIW610
+#define CARD_TYPE_SDIW610_UART                                                 \
+	1 // As per datasheet/SoC design - Nighthawk, sd-uart strap = 0x3
+#endif
+#ifdef USBIW610
+#define CARD_TYPE_USBIW610_USB                                                 \
+	5 // As per datasheet/SoC design - Nighthawk, usb-usb strap = 0x5
+#define CARD_TYPE_USBIW610_UART                                                \
+	7 // As per datasheet/SoC design - Nighthawk, usb-uart strap = 0x7
+#endif
 
 /* Max buffer size */
 #define MAX_BUF_LEN 512
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
+/* Max hostname length */
+#define MAX_HOSTNAME_LEN 128
+
+/* Max rtc time length */
+#define MAX_TIME_LEN 128
+#endif
+
 /** Driver version */
 extern char driver_version[];
 
@@ -364,6 +384,7 @@ typedef enum {
 	RDWR_STATUS_DONE = 2
 } rdwr_status;
 #endif
+
 /** Private structure for MOAL */
 typedef struct _moal_private moal_private, *pmoal_private;
 /** Handle data structure for MOAL  */
@@ -989,6 +1010,12 @@ mlan_status woal_do_dfs_cac(moal_private *priv,
 /** LOW Tx Pending count */
 #define LOW_TX_PENDING 380
 
+/** MAX Tx Pending count when multi-client scheduling is used  */
+#define MCLIENT_MAX_TX_PENDING (128 * MAX_STA_COUNT)
+
+/** LOW Tx Pending count when multi-client scheduling is used */
+#define MCLIENT_LOW_TX_PENDING (MCLIENT_MAX_TX_PENDING * 3 / 4)
+
 /** Offset for subcommand */
 #define SUBCMD_OFFSET 4
 
@@ -999,6 +1026,8 @@ mlan_status woal_do_dfs_cac(moal_private *priv,
 /** GAP value is optional */
 #define GAP_FLAG_OPTIONAL MBIT(15)
 
+#define AUTH_TX_DEFAULT_WAIT_TIME 2400
+
 /** max retry count for wait_event_interupptible_xx while loop */
 #define MAX_RETRY_CNT 100
 /** wait_queue structure */
@@ -1066,7 +1095,8 @@ typedef struct _wait_queue {
 /** Driver mode uAP bit */
 #define DRV_MODE_UAP MBIT(1)
 /** Maximum uAP BSS */
-#define MAX_UAP_BSS 3
+#define MAX_UAP_BSS 2
+#define MAX_UAP_BSS_DUAL_MAC 3
 /** Default uAP BSS */
 #define DEF_UAP_BSS 1
 
@@ -1217,6 +1247,7 @@ enum woal_event_type {
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
 	WOAL_EVENT_DEAUTH,
 	WOAL_EVENT_ASSOC_RESP,
+	WOAL_EVENT_ASSOC_TIMEOUT,
 #endif
 #endif
 	WOAL_EVENT_CHAN_RPT,
@@ -1252,6 +1283,7 @@ struct woal_event {
 	enum woal_event_type type;
 	/** priv pointer */
 	void *priv;
+	struct cfg80211_bss *assoc_bss;
 	union {
 		chan_band_info chan_info;
 		woal_evt_buf evt;
@@ -1415,6 +1447,8 @@ struct rf_test_mode_data {
 	mfg_Cmd_IEEEtypes_CtlBasicTrigHdr_t mfg_tx_trigger_config;
 	/* OTP frame data */
 	mfg_cmd_otp_mac_addr_rd_wr_t mfg_otp_mac_addr_rd_wr;
+	/* OTP CAL data */
+	mfg_cmd_otp_cal_data_rd_wr_t mfg_otp_cal_data_rd_wr;
 };
 
 /** Number of samples in histogram (/proc/mwlan/adapterX/mlan0/histogram).*/
@@ -1560,6 +1594,38 @@ struct dhcp_pkt {
 	t_u8 pOptions[1];
 } __ATTRIB_PACK__;
 
+/** IPv4 arp header */
+struct arp_hdr {
+	/** Hardware type */
+	t_u16 htype;
+	/** Protocol type */
+	t_u16 ptype;
+	/** Hardware address length */
+	t_u8 addr_len;
+	/** Protocol address length */
+	t_u8 proto_len;
+	/** Operation code */
+	t_u16 op_code;
+	/** Source mac address */
+	t_u8 sender_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Sender IP address */
+	t_u8 sender_ip[4];
+	/** Destination mac address */
+	t_u8 target_mac[MLAN_MAC_ADDR_LENGTH];
+	/** Destination IP address */
+	t_u8 target_ip[4];
+} __ATTRIB_PACK__;
+
+/** ARP request entry ageout of 10 secs */
+#define ARP_REQ_AGEOUT_TIME (10 * HZ)
+
+/** ARP request node */
+struct arp_entry {
+	t_u32 hash_key;
+	struct hlist_node arp_hlist;
+	t_u64 ageout_jiffies;
+};
+
 #define EASY_MESH_MULTI_AP_FH_BSS (t_u8)(0x20)
 #define EASY_MESH_MULTI_AP_BH_BSS (t_u8)(0x40)
 #define EASY_MESH_MULTI_AP_BH_AND_FH_BSS (t_u8)(0x60)
@@ -1585,6 +1651,7 @@ struct ipv6addr_entry {
 	/** IPv6 address entry */
 	t_u8 ipv6_addr[16];
 };
+
 /** Private structure for MOAL */
 struct _moal_private {
 	/** Handle structure */
@@ -1934,6 +2001,8 @@ struct _moal_private {
 	t_u8 tdls_check_tx;
 	auto_assoc auto_assoc_priv;
 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
+	t_u32 max_tx_pending;
+	t_u32 low_tx_pending;
 	atomic_t wmm_tx_pending[4];
 #endif
 	struct sk_buff_head tx_q;
@@ -1979,12 +2048,17 @@ struct _moal_private {
 	spinlock_t dhcp_discover_lock;
 	/** DHCP DISCOVER Info queue */
 	struct list_head dhcp_discover_queue;
+	/** hash table for arp request */
+	DECLARE_HASHTABLE(hlist, 8);
+	/** arp request lock */
+	spinlock_t arp_request_lock;
 	/** txwatchdog disable */
 	t_u8 txwatchdog_disable;
 
 	/** secure boot uuid lower and higher 8 bytes */
 	t_u64 uuid_lo;
 	t_u64 uuid_hi;
+	t_u16 auth_tx_wait_time;
 };
 
 #ifdef SDIO
@@ -2526,6 +2600,7 @@ enum ext_mod_params {
 	EXT_PMQOS,
 	EXT_CHAN_TRACK,
 	EXT_DMCS,
+	EXT_PREF_DBC,
 	EXT_MAX_PARAM,
 };
 
@@ -2560,6 +2635,7 @@ typedef struct _moal_mod_para {
 	int uap_max_sta;
 	int wacp_mode;
 #endif /* UAP_SUPPORT */
+	unsigned int fw_data_cfg;
 #ifdef WIFI_DIRECT_SUPPORT
 	int max_wfd_bss;
 	char *wfd_name;
@@ -2572,7 +2648,10 @@ typedef struct _moal_mod_para {
 	int auto_ds;
 	int net_rx;
 	int amsdu_deaggr;
+	int tx_budget;
+	int mclient_scheduling;
 	int ext_scan;
+	int bootup_cal_ctrl;
 	int ps_mode;
 	int p2a_scan;
 	/** scan chan gap */
@@ -2612,6 +2691,10 @@ typedef struct _moal_mod_para {
 	unsigned int dev_cap_mask;
 	int pmic;
 	int antcfg;
+	/** dmcs*/
+	int dmcs;
+	/** pref_dbc*/
+	int pref_dbc;
 	unsigned int uap_oper_ctrl;
 	int hs_wake_interval;
 	int indication_gpio;
@@ -3383,6 +3466,12 @@ extern t_u32 drvdbg;
 			printk(KERN_DEBUG msg);                                \
 	} while (0)
 
+#define PRINTM_MREG(level, msg...)                                             \
+	do {                                                                   \
+		woal_print(level, msg);                                        \
+		if (drvdbg & MREG)                                             \
+			printk(KERN_DEBUG msg);                                \
+	} while (0)
 #define PRINTM_MIOCTL(level, msg...)                                           \
 	do {                                                                   \
 		woal_print(level, msg);                                        \
@@ -4353,6 +4442,9 @@ void woal_flush_dhcp_discover_queue(moal_private *priv);
 t_u32 woal_get_dhcp_discover_transation_id(struct sk_buff *skb);
 t_void woal_add_dhcp_discover_node(moal_private *priv, t_u32 transaction_id,
 				   mlan_buffer *pmbuf);
+t_void woal_add_arp_request_node(moal_private *priv, t_u32 hash_key);
+t_u32 woal_generate_arp_request_hash(struct sk_buff *skb);
+t_void woal_flush_arp_request_entry(moal_private *priv);
 #endif
 
 mlan_status woal_set_get_wowlan_config(moal_private *priv, t_u16 action,
@@ -4449,4 +4541,9 @@ mlan_status woal_edmac_cfg(moal_private *priv, t_u8 *country_code);
 #ifdef DUMP_TO_PROC
 void woal_print_firmware_dump_buf(t_u8 *pfd_buf, t_u64 fwdump_len);
 #endif
+
+#if !defined(STA_CFG80211) && !defined(UAP_CFG80211)
+unsigned int woal_classify8021d(struct sk_buff *skb);
+#endif
+
 #endif /* _MOAL_MAIN_H */
diff --git a/mlinux/moal_pcie.c b/mlinux/moal_pcie.c
index 5cc4fcd..4b86d69 100644
--- a/mlinux/moal_pcie.c
+++ b/mlinux/moal_pcie.c
@@ -638,7 +638,7 @@ static void woal_pcie_remove(struct pci_dev *dev)
 	}
 	cancel_work_sync(&card->reset_work);
 	handle = card->handle;
-	if (!handle || !handle->priv_num) {
+	if (!handle) {
 		PRINTM(MINFO, "PCIE card handle removed\n");
 		woal_pcie_cleanup(card);
 		kfree(card);
@@ -960,7 +960,8 @@ static void woal_pcie_reset_prepare(struct pci_dev *pdev)
 	handle->fw_reseting = MTRUE;
 	// TODO: Can add more chips once the related code has been ported to fw
 	// v18
-	if (IS_PCIE9097(handle->card_type) || IS_PCIE9098(handle->card_type)) {
+	if (IS_PCIE9097(handle->card_type) || IS_PCIE9098(handle->card_type) ||
+	    IS_PCIEAW693(handle->card_type)) {
 		woal_reset_adma(handle);
 	}
 
@@ -1079,7 +1080,8 @@ static void woal_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
 		// TODO: Can add more chips once the related code has been
 		// ported to fw v18
 		if (IS_PCIE9097(handle->card_type) ||
-		    IS_PCIE9098(handle->card_type)) {
+		    IS_PCIE9098(handle->card_type) ||
+		    IS_PCIEAW693(handle->card_type)) {
 			woal_reset_adma(handle);
 		}
 		woal_do_flr(handle, prepare, true);
@@ -1163,6 +1165,7 @@ static mlan_status woal_pcie_write_reg(moal_handle *handle, t_u32 reg,
 	pcie_service_card *card = (pcie_service_card *)handle->card;
 
 	iowrite32(data, card->pci_mmap1 + reg);
+	PRINTM(MREG, "pcie w %x = %x\n", reg, data);
 
 	return MLAN_STATUS_SUCCESS;
 }
@@ -1181,6 +1184,7 @@ static mlan_status woal_pcie_read_reg(moal_handle *handle, t_u32 reg,
 {
 	pcie_service_card *card = (pcie_service_card *)handle->card;
 	*data = ioread32(card->pci_mmap1 + reg);
+	PRINTM(MREG, "pcie r %x = %x\n", reg, *data);
 
 	if (*data == MLAN_STATUS_FAILURE)
 		return MLAN_STATUS_FAILURE;
@@ -2612,7 +2616,7 @@ static mlan_status woal_pcie_get_fw_name(moal_handle *handle)
 	t_u32 strap = 0;
 	t_u32 magic = 0;
 #endif
-#ifdef PCIEIW624
+#if defined(PCIEIW624) || defined(PCIEAW693)
 	t_u32 boot_mode_reg = handle->card_info->boot_mode_reg;
 	t_u32 boot_mode;
 #endif
@@ -2640,6 +2644,21 @@ static mlan_status woal_pcie_get_fw_name(moal_handle *handle)
 				break;
 			}
 		}
+#endif
+#ifdef PCIEAW693
+		if (IS_PCIEAW693(handle->card_type)) {
+			woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
+			revision_id &= 0xff;
+			PRINTM(MCMND, "revision_id=0x%x\n", revision_id);
+			switch (revision_id) {
+			case PCIEAW693_A1:
+				handle->card_rev = CHIP_AW693_REV_A1;
+				break;
+			default:
+				handle->card_rev = CHIP_AW693_REV_A0;
+				break;
+			}
+		}
 #endif
 		goto done;
 	}
@@ -2778,23 +2797,84 @@ static mlan_status woal_pcie_get_fw_name(moal_handle *handle)
 			woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
 			woal_pcie_read_reg(handle, host_strap_reg, &strap);
 			woal_pcie_read_reg(handle, magic_reg, &magic);
+			woal_pcie_read_reg(handle, boot_mode_reg, &boot_mode);
 			revision_id &= 0xff;
 			strap &= 0x7;
 			magic &= 0xff;
+			boot_mode &= 0x03;
 			PRINTM(MCMND,
-			       "magic=0x%x, strap=0x%x, revision_id=0x%x\n",
-			       magic, strap, revision_id);
-			if (magic == CHIP_MAGIC_VALUE) {
-				if (strap == CARD_TYPE_PCIE_UART)
-					strcpy(handle->card_info->fw_name,
-					       PCIEUARTAW693_DEFAULT_COMBO_FW_NAME);
-				else
-					strcpy(handle->card_info->fw_name,
-					       PCIEAW693_DEFAULT_COMBO_FW_NAME);
+			       "magic=0x%x, boot_mode=0x%x, strap=0x%x, revision_id=0x%x\n",
+			       magic, boot_mode, strap, revision_id);
+			if (boot_mode == 0x03)
+				PRINTM(MMSG,
+				       "wlan: PCIE-AW693 in secure-boot mode\n");
+
+			switch (revision_id) {
+			case PCIEAW693_A1:
+				handle->card_rev = CHIP_AW693_REV_A1;
+				if (magic == CHIP_MAGIC_VALUE) {
+					if (strap == CARD_TYPE_PCIE_UART)
+						strcpy(handle->card_info
+							       ->fw_name,
+						       PCIEUARTAW693_COMBO_V1_FW_NAME);
+					else
+						strcpy(handle->card_info
+							       ->fw_name,
+						       PCIEAW693_COMBO_V1_FW_NAME);
+				}
+				strcpy(handle->card_info->fw_name_wlan,
+				       PCIEAW693_WLAN_V1_FW_NAME);
+				if (boot_mode != 0x03) {
+					/* remove extension .se */
+					if (strstr(handle->card_info->fw_name,
+						   ".se"))
+						memset(strstr(handle->card_info
+								      ->fw_name,
+							      ".se"),
+						       '\0', sizeof(".se"));
+					if (strstr(handle->card_info
+							   ->fw_name_wlan,
+						   ".se"))
+						memset(strstr(handle->card_info
+								      ->fw_name_wlan,
+							      ".se"),
+						       '\0', sizeof(".se"));
+				}
+				break;
+			case PCIEAW693_A0:
+				handle->card_rev = CHIP_AW693_REV_A0;
+				if (magic == CHIP_MAGIC_VALUE) {
+					if (strap == CARD_TYPE_PCIE_UART)
+						strcpy(handle->card_info
+							       ->fw_name,
+						       PCIEUARTAW693_DEFAULT_COMBO_FW_NAME);
+					else
+						strcpy(handle->card_info
+							       ->fw_name,
+						       PCIEAW693_DEFAULT_COMBO_FW_NAME);
+				}
+				strcpy(handle->card_info->fw_name_wlan,
+				       PCIEAW693_DEFAULT_WLAN_FW_NAME);
+				break;
+			default:
+				break;
 			}
 		} else {
 			ref_handle = (moal_handle *)handle->pref_mac;
 			if (ref_handle) {
+				woal_pcie_read_reg(handle, rev_id_reg,
+						   &revision_id);
+				revision_id &= 0xff;
+				PRINTM(MCMND, "revision_id=0x%x\n",
+				       revision_id);
+				switch (revision_id) {
+				case PCIEAW693_A1:
+					handle->card_rev = CHIP_AW693_REV_A1;
+					break;
+				default:
+					handle->card_rev = CHIP_AW693_REV_A0;
+					break;
+				}
 				strcpy(handle->card_info->fw_name,
 				       ref_handle->card_info->fw_name);
 				strcpy(handle->card_info->fw_name_wlan,
@@ -2935,7 +3015,8 @@ static void woal_pcie_work(struct work_struct *work)
 	handle->fw_reseting = MTRUE;
 	// TODO: Can add more chips once the related code has been ported to fw
 	// v18
-	if (IS_PCIE9097(handle->card_type) || IS_PCIE9098(handle->card_type)) {
+	if (IS_PCIE9097(handle->card_type) || IS_PCIE9098(handle->card_type) ||
+	    IS_PCIEAW693(handle->card_type)) {
 		woal_reset_adma(handle);
 	}
 	woal_do_flr(handle, true, true);
diff --git a/mlinux/moal_pcie.h b/mlinux/moal_pcie.h
index 8f0197e..cb25bd4 100644
--- a/mlinux/moal_pcie.h
+++ b/mlinux/moal_pcie.h
@@ -94,7 +94,12 @@ Change log:
 #ifdef PCIEAW693
 #define PCIEUARTAW693_DEFAULT_COMBO_FW_NAME "nxp/pcieuartaw693_combo.bin"
 #define PCIEAW693_DEFAULT_COMBO_FW_NAME "nxp/pcieuartaw693_combo.bin"
+#define PCIEUARTAW693_COMBO_V1_FW_NAME "nxp/pcieuartaw693_combo_v1.bin.se"
+#define PCIEAW693_COMBO_V1_FW_NAME "nxp/pcieuartaw693_combo_v1.bin.se"
 #define PCIEAW693_DEFAULT_WLAN_FW_NAME "nxp/pcieaw693_wlan.bin"
+#define PCIEAW693_WLAN_V1_FW_NAME "nxp/pcieaw693_wlan_v1.bin.se"
+#define PCIEAW693_A0 0x00
+#define PCIEAW693_A1 0x01
 #endif /* PCIEAW693*/
 
 #ifdef PCIE9098
diff --git a/mlinux/moal_priv.c b/mlinux/moal_priv.c
index e5f0425..6013e17 100644
--- a/mlinux/moal_priv.c
+++ b/mlinux/moal_priv.c
@@ -124,11 +124,9 @@ static int woal_associate_ssid_bssid(moal_private *priv, struct iwreq *wrq)
 		if (buf[i] == ':') {
 			mac_idx++;
 		} else {
-			if (mac_idx < ETH_ALEN) {
-				// coverity[tainted_data: SUPPRESS]
+			if (mac_idx < ETH_ALEN)
 				ssid_bssid->bssid[mac_idx] =
 					(t_u8)woal_atox(buf + i);
-			}
 
 			while ((i < buflen) && (isxdigit(buf[i + 1]))) {
 				/* Skip entire hex value */
@@ -2753,6 +2751,8 @@ static int woal_drv_dbg(moal_private *priv, struct iwreq *wrq)
 	       (drvdbg & MCMD_D) ? "X" : "");
 	printk(KERN_ALERT "MDAT_D (%08x) %s\n", MDAT_D,
 	       (drvdbg & MDAT_D) ? "X" : "");
+	printk(KERN_ALERT "MREG   (%08x) %s\n", MREG,
+	       (drvdbg & MREG) ? "X" : "");
 	printk(KERN_ALERT "MREG_D (%08x) %s\n", MREG_D,
 	       (drvdbg & MREG_D) ? "X" : "");
 	printk(KERN_ALERT "MIOCTL (%08x) %s\n", MIOCTL,
@@ -2960,6 +2960,94 @@ done:
 	return ret;
 }
 
+/**
+ * @brief Set/Get module configuration
+ *
+ * @param priv     A pointer to moal_private structure
+ * @param wrq      A pointer to iwreq structure
+ *
+ * @return         0 --success, otherwise fail
+ */
+static int woal_fw_wakeup_method(moal_private *priv, struct iwreq *wrq)
+{
+	int ret = 0, data[2];
+	mlan_ds_pm_cfg *pm_cfg = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
+	if (req == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
+
+	if (wrq->u.data.length > 2) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (!wrq->u.data.length) {
+		req->action = MLAN_ACT_GET;
+	} else {
+		req->action = MLAN_ACT_SET;
+		if (copy_from_user(data, wrq->u.data.pointer,
+				   sizeof(int) * wrq->u.data.length)) {
+			PRINTM(MINFO, "Copy from user failed\n");
+			ret = -EFAULT;
+			goto done;
+		}
+		if (data[0] != FW_WAKEUP_METHOD_INTERFACE &&
+		    data[0] != FW_WAKEUP_METHOD_GPIO) {
+			PRINTM(MERROR, "Invalid FW wake up method:%d\n",
+			       data[0]);
+			ret = -EINVAL;
+			goto done;
+		}
+		if (data[0] == FW_WAKEUP_METHOD_GPIO) {
+			if (wrq->u.data.length == 1) {
+				PRINTM(MERROR,
+				       "Please provide gpio pin number for FW_WAKEUP_METHOD gpio\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			pm_cfg->param.fw_wakeup_params.gpio_pin = data[1];
+		}
+
+		pm_cfg->param.fw_wakeup_params.method = data[0];
+	}
+
+	pm_cfg->sub_command = MLAN_OID_PM_CFG_FW_WAKEUP_METHOD;
+	req->req_id = MLAN_IOCTL_PM_CFG;
+
+	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	data[0] = ((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.method;
+	data[1] =
+		((mlan_ds_pm_cfg *)req->pbuf)->param.fw_wakeup_params.gpio_pin;
+
+	if (data[0] == FW_WAKEUP_METHOD_INTERFACE)
+		wrq->u.data.length = 1;
+	else
+		wrq->u.data.length = 2;
+	if (copy_to_user(wrq->u.data.pointer, data,
+			 sizeof(int) * wrq->u.data.length)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
+
 /**
  * @brief Configure sleep parameters
  *
@@ -6372,7 +6460,15 @@ static int woal_set_get_tx_rx_ant(moal_private *priv, struct iwreq *wrq)
 
 		if (priv->phandle->feature_control & FEATURE_CTRL_STREAM_2X2) {
 			radio->param.ant_cfg.tx_antenna = data[0];
-			radio->param.ant_cfg.rx_antenna = data[0];
+			if (data[0] == RF_ANTENNA_AUTO) {
+				radio->param.ant_cfg.rx_antenna = 0;
+				if (data[1] > 0xffff) {
+					ret = -EINVAL;
+					goto done;
+				}
+			} else {
+				radio->param.ant_cfg.rx_antenna = data[0];
+			}
 			if (wrq->u.data.length == 2)
 				radio->param.ant_cfg.rx_antenna = data[1];
 		} else {
@@ -6615,6 +6711,9 @@ int woal_wext_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 		case WOAL_SLEEP_PD:
 			ret = woal_sleep_pd(priv, wrq);
 			break;
+		case WOAL_FW_WAKEUP_METHOD:
+			ret = woal_fw_wakeup_method(priv, wrq);
+			break;
 		case WOAL_AUTH_TYPE:
 			ret = woal_auth_type(priv, wrq);
 			break;
diff --git a/mlinux/moal_priv.h b/mlinux/moal_priv.h
index c35ef67..c4118dd 100644
--- a/mlinux/moal_priv.h
+++ b/mlinux/moal_priv.h
@@ -170,6 +170,8 @@ Change log:
 #define WOAL_SET_GET_WWS_CFG 12
 /** Private command ID to set/get sleep period */
 #define WOAL_SLEEP_PD 13
+/** Private command ID to set/get firmware wakeup method */
+#define WOAL_FW_WAKEUP_METHOD 15
 /** Private command ID to set/get auth type */
 #define WOAL_AUTH_TYPE 18
 /** Private command ID to set/get port control */
diff --git a/mlinux/moal_proc.c b/mlinux/moal_proc.c
index 08f7289..d4cbf67 100644
--- a/mlinux/moal_proc.c
+++ b/mlinux/moal_proc.c
@@ -236,7 +236,7 @@ static int woal_info_proc_read(struct seq_file *sfp, void *data)
 	for (i = 0; i < (int)netdev->num_tx_queues; i++) {
 		seq_printf(sfp, "tx queue %d:  %s\n", i,
 			   ((netif_tx_queue_stopped(
-				    netdev_get_tx_queue(netdev, 0))) ?
+				    netdev_get_tx_queue(netdev, i))) ?
 				    "stopped" :
 				    "started"));
 	}
@@ -558,7 +558,16 @@ static mlan_status woal_priv_set_tx_rx_ant(moal_handle *handle, char *line)
 
 	if (handle->feature_control & FEATURE_CTRL_STREAM_2X2) {
 		radio->param.ant_cfg.tx_antenna = data[0];
-		radio->param.ant_cfg.rx_antenna = data[0];
+		if (data[0] == RF_ANTENNA_AUTO) {
+			radio->param.ant_cfg.rx_antenna = 0;
+			if (data[1] > 0xffff) {
+				kfree(req);
+				LEAVE();
+				return MLAN_STATUS_FAILURE;
+			}
+		} else {
+			radio->param.ant_cfg.rx_antenna = data[0];
+		}
 		if (user_data_len == 2)
 			radio->param.ant_cfg.rx_antenna = data[1];
 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
@@ -601,9 +610,11 @@ static mlan_status woal_priv_set_tx_rx_ant(moal_handle *handle, char *line)
 static ssize_t woal_config_write(struct file *f, const char __user *buf,
 				 size_t count, loff_t *off)
 {
-	char databuf[200];
+	char *databuf = NULL;
 	char *line = NULL;
 	int ret = 0;
+	gfp_t flag;
+
 	t_u32 config_data = 0;
 	struct seq_file *sfp = f->private_data;
 	moal_handle *handle = (moal_handle *)sfp->private;
@@ -622,15 +633,17 @@ static ssize_t woal_config_write(struct file *f, const char __user *buf,
 		return 0;
 	}
 
-	if (count >= sizeof(databuf)) {
-		MODULE_PUT;
+	flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
+	databuf = kzalloc(count, flag);
+	if (databuf == NULL) {
 		LEAVE();
-		return (int)count;
+		return -ENOMEM;
 	}
-	memset(databuf, 0, sizeof(databuf));
-	copy_len = MIN((sizeof(databuf) - 1), count);
-	if (copy_from_user(databuf, buf, copy_len)) {
+
+	copy_len = count;
+	if (copy_from_user(databuf, buf, count)) {
 		MODULE_PUT;
+		kfree(databuf);
 		LEAVE();
 		return 0;
 	}
@@ -692,7 +705,7 @@ static ssize_t woal_config_write(struct file *f, const char __user *buf,
 	if (!strncmp(databuf, "fwdump_file=", strlen("fwdump_file="))) {
 		int len = copy_len - strlen("fwdump_file=");
 		gfp_t flag;
-		if (len) {
+		if (len > 0) {
 			kfree(handle->fwdump_fname);
 			flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC :
 								  GFP_KERNEL;
@@ -806,9 +819,13 @@ static ssize_t woal_config_write(struct file *f, const char __user *buf,
 		cmd = MFG_CMD_CONFIG_TRIGGER_FRAME;
 	if (!strncmp(databuf,
 		     "otp_mac_addr_rd_wr=", strlen("otp_mac_add_rd_wr=")) &&
-	    count > strlen("otp_mac_addr_rd_wr=")) {
+	    count > strlen("otp_mac_addr_rd_wr="))
 		cmd = MFG_CMD_OTP_MAC_ADD;
-	}
+	if (!strncmp(databuf,
+		     "otp_cal_data_rd_wr=", strlen("otp_cal_data_rd_wr=")) &&
+	    count > strlen("otp_cal_data_rd_wr="))
+		cmd = MFG_CMD_OTP_CAL_DATA;
+
 	if (cmd && handle->rf_test_mode &&
 	    (woal_process_rf_test_mode_cmd(
 		     handle, cmd, (const char *)databuf, (size_t)count,
@@ -826,6 +843,7 @@ static ssize_t woal_config_write(struct file *f, const char __user *buf,
 	}
 
 	MODULE_PUT;
+	kfree(databuf);
 	LEAVE();
 	if (ret < 0)
 		return ret;
@@ -1630,7 +1648,7 @@ void woal_create_proc_entry(moal_private *priv)
 		atomic_inc(&(priv->phandle->proc_wlan->count));
 #endif /* < 3.10.0 */
 #endif /* < 2.6.26 */
-		strncpy(priv->proc_entry_name, dev->name, IFNAMSIZ);
+		strncpy(priv->proc_entry_name, dev->name, IFNAMSIZ - 1);
 		if (priv->proc_entry) {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
 			r = proc_create_data("info", 0, priv->proc_entry,
diff --git a/mlinux/moal_sdio.h b/mlinux/moal_sdio.h
index 77a8516..63905a5 100644
--- a/mlinux/moal_sdio.h
+++ b/mlinux/moal_sdio.h
@@ -154,10 +154,15 @@ Change log:
 #endif /* SDIW624 */
 
 #ifdef SDAW693
+#define SDAW693_A0 0x00
+#define SDAW693_A1 0x01
 #define SDAW693_DEFAULT_COMBO_FW_NAME "nxp/sdsdwaw693_combo.bin"
 #define SDUARTAW693_COMBO_FW_NAME "nxp/sduartw693_combo.bin"
 #define SDSDAW693_COMBO_FW_NAME "sdsdaw693_combo.bin"
+#define SDUARTAW693_COMBO_V1_FW_NAME "nxp/sduartw693_combo_v1.bin.se"
+#define SDSDAW693_COMBO_V1_FW_NAME "sdsdaw693_combo_v1.bin.se"
 #define SDAW693_DEFAULT_WLAN_FW_NAME "nxp/sdaw693_wlan.bin"
+#define SDAW693_WLAN_V1_FW_NAME "nxp/sdaw693_wlan_v1.bin.se"
 #endif /* SDAW693 */
 
 #ifdef SD9177
@@ -177,12 +182,12 @@ Change log:
 #define SD9177_DEFAULT_RFTM_WLAN_V1_FW_NAME "nxp/sd_w61x_rftm_v1.bin.se"
 #endif /* SD9177 */
 
-#ifdef SDIW615
-#define SDIW615_DEFAULT_COMBO_FW_NAME "nxp/sdsdiw615_combo.bin"
-#define SDUARTIW615_COMBO_FW_NAME "nxp/sduartiw615_combo.bin"
-#define SDSDIW615_COMBO_FW_NAME "sdsdiw615_combo.bin"
-#define SDIW615_DEFAULT_WLAN_FW_NAME "nxp/sdiw615_wlan.bin"
-#endif /* SDIW615 */
+#ifdef SDIW610
+#define SDIW610_DEFAULT_COMBO_FW_NAME "nxp/sduartspi_iw610.bin.se"
+#define SDUARTIW610_COMBO_FW_NAME "nxp/sduart_iw610.bin.se"
+#define SDUARTSPIIW610_COMBO_FW_NAME "nxp/sduartspi_iw610.bin.se"
+#define SDIW610_DEFAULT_WLAN_FW_NAME "nxp/sd_iw610.bin.se"
+#endif /* SDIW610 */
 
 /********************************************************
 		Global Functions
@@ -220,6 +225,20 @@ typedef struct _sdio_mmc_card {
 	t_u8 work_flags;
 	/** saved host clock value */
 	unsigned int host_clock;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0)
+	/** oob irq */
+	int oob_irq;
+	/** irq enabled */
+	int irq_enabled;
+	/** sdio func intr enabled **/
+	int sdio_func_intr_enabled;
+	/** irq registered */
+	int irq_registered;
+	/* SDIO OOB Interrupt handling workqueue */
+	struct workqueue_struct *sdio_oob_irq_workqueue;
+	/* SDIO OOB Interrupt handler work */
+	struct work_struct sdio_oob_irq_work;
+#endif
 } sdio_mmc_card;
 void woal_sdio_reset_hw(moal_handle *handle);
 #endif /* SDIO_MMC */
diff --git a/mlinux/moal_sdio_mmc.c b/mlinux/moal_sdio_mmc.c
index f8ecdd0..100be7a 100644
--- a/mlinux/moal_sdio_mmc.c
+++ b/mlinux/moal_sdio_mmc.c
@@ -36,10 +36,22 @@ Change log:
 #include <net/addrconf.h>
 #endif
 #endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0)
+#include <linux/gpio.h>
+#include <uapi/linux/sched/types.h>
+#endif
 
 /** define nxp vendor id */
 #define NXP_VENDOR_ID 0x0471
 #define MRVL_VENDOR_ID 0x02df
+/* The macros below are hardware platform dependent.
+   The definition should match the actual platform */
+/** Initialize GPIO port */
+#define GPIO_PORT_INIT()
+/** Set GPIO port to high */
+#define GPIO_PORT_TO_HIGH()
+/** Set GPIO port to low */
+#define GPIO_PORT_TO_LOW()
 
 /********************************************************
 		Local Variables
@@ -102,9 +114,9 @@ static moal_if_ops sdiommc_ops;
 /** Device ID for SDIW624 */
 #define SD_DEVICE_ID_IW624 (0x020D)
 #endif
-#ifdef SDIW615
-/** Device ID for SDIW615 */
-#define SD_DEVICE_ID_IW615 (0x020D)
+#ifdef SDIW610
+/** Device ID for SDIW610 */
+#define SD_DEVICE_ID_IW610 (0x0215)
 #endif
 
 /** WLAN IDs */
@@ -147,8 +159,8 @@ static const struct sdio_device_id wlan_ids[] = {
 #ifdef SDIW624
 	{SDIO_DEVICE(NXP_VENDOR_ID, SD_DEVICE_ID_IW624)},
 #endif
-#ifdef SDIW615
-	{SDIO_DEVICE(NXP_VENDOR_ID, SD_DEVICE_ID_IW615)},
+#ifdef SDIW610
+	{SDIO_DEVICE(NXP_VENDOR_ID, SD_DEVICE_ID_IW610)},
 #endif
 	{},
 };
@@ -210,6 +222,7 @@ static struct sdio_driver REFDATA wlan_sdio = {
 		Local Functions
 ********************************************************/
 static void woal_sdiommc_dump_fw_info(moal_handle *phandle);
+static void woal_trigger_nmi_on_no_dump_event(moal_handle *phandle);
 #if 0
 /**  @brief This function dump the sdio register
  *
@@ -312,6 +325,245 @@ static void woal_sdio_interrupt(struct sdio_func *func)
 	LEAVE();
 }
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0)
+/**
+ * @brief This work handles oob sdio top irq.
+ */
+static void woal_sdio_oob_irq_work(struct work_struct *work)
+{
+	sdio_mmc_card *card =
+		container_of(work, sdio_mmc_card, sdio_oob_irq_work);
+	struct mmc_card *mmc_card = card->func->card;
+	struct sdio_func *func;
+	unsigned char pending;
+	int i;
+	int ret;
+
+	for (i = 0; i < mmc_card->sdio_funcs; i++) {
+		func = NULL;
+		if (mmc_card->sdio_func[i]) {
+			func = mmc_card->sdio_func[i];
+		}
+		if (func) {
+			sdio_claim_host(func);
+			pending = sdio_f0_readb(func, SDIO_CCCR_INTx, &ret);
+			if (!ret && pending && func->irq_handler)
+				func->irq_handler(func);
+			sdio_release_host(func);
+		}
+	}
+
+	if (card->irq_registered && !card->irq_enabled) {
+		card->irq_enabled = MTRUE;
+		enable_irq(card->oob_irq);
+	}
+}
+
+/**
+ *  @brief oob_sdio_irq interrupt handler.
+ *
+ *  @param irq     irq
+ *  @param dev_id   a pointer to structure sdio_mmc_card
+ *  @return         IRQ_HANDLED
+ */
+static irqreturn_t oob_sdio_irq(int irq, void *dev_id)
+{
+	sdio_mmc_card *card = (sdio_mmc_card *)dev_id;
+
+	if (card->sdio_func_intr_enabled) {
+		disable_irq_nosync(card->oob_irq);
+		card->irq_enabled = MFALSE;
+		queue_work(card->sdio_oob_irq_workqueue,
+			   &card->sdio_oob_irq_work);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ *  @brief This function registers oob_sdio_irq
+ *
+ *  @param card    a pointer to sdio_mmc_card
+ *  @return         0-success else failure
+ */
+static int oob_sdio_irq_register(sdio_mmc_card *card)
+{
+	int ret = 0;
+
+	ret = devm_request_irq(card->handle->hotplug_device, card->oob_irq,
+			       oob_sdio_irq, IRQF_TRIGGER_LOW | IRQF_SHARED,
+			       "nxp_oob_sdio_irq", card);
+
+	if (!ret) {
+		card->irq_registered = MTRUE;
+		card->irq_enabled = MTRUE;
+		enable_irq_wake(card->oob_irq);
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief This function unregister oob_sdio_irq
+ *
+ *  @param card    a pointer to sdio_mmc_card
+ *  @return         N/A
+ */
+static void oob_sdio_irq_unregister(sdio_mmc_card *card)
+{
+	if (card->irq_registered) {
+		card->irq_registered = MFALSE;
+		disable_irq_wake(card->oob_irq);
+		if (card->irq_enabled) {
+			disable_irq(card->oob_irq);
+			card->irq_enabled = MFALSE;
+		}
+		devm_free_irq(card->handle->hotplug_device, card->oob_irq,
+			      card);
+	}
+}
+
+/**
+ *  @brief This function enable interrupt in SDIO Func0 SDIO_CCCR_IENx
+ *
+ *  @param func    a pointer to struct sdio_func
+ *  @param handler  sdio_irq_handler
+ *  @return         0-success else failure
+ */
+static int sdio_func_intr_enable(struct sdio_func *func,
+				 sdio_irq_handler_t *handler)
+{
+	int ret;
+	unsigned char reg;
+
+#ifdef MMC_QUIRK_LENIENT_FN0
+	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+#endif
+	reg = sdio_f0_readb(func, SDIO_CCCR_IENx, &ret);
+	if (ret)
+		return ret;
+	reg |= 1 << func->num;
+	reg |= 1;
+	sdio_f0_writeb(func, reg, SDIO_CCCR_IENx, &ret);
+	if (ret)
+		return ret;
+
+	func->irq_handler = handler;
+
+	return ret;
+}
+
+/**
+ *  @brief This function disable interrupt in SDIO Func0 SDIO_CCCR_IENx
+ *
+ *  @param func    a pointer to struct sdio_func
+ *  @return         0-success else failure
+ */
+static int sdio_func_intr_disable(struct sdio_func *func)
+{
+	int ret;
+	unsigned char reg;
+
+#ifdef MMC_QUIRK_LENIENT_FN0
+	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+#endif
+	if (func->irq_handler)
+		func->irq_handler = NULL;
+
+	reg = sdio_f0_readb(func, SDIO_CCCR_IENx, &ret);
+	if (ret)
+		return ret;
+	reg &= ~(1 << func->num);
+	if (!(reg & 0xFE))
+		reg = 0;
+	sdio_f0_writeb(func, reg, SDIO_CCCR_IENx, &ret);
+
+	return ret;
+}
+
+/**
+ *  @brief This function claim the oob sdio irq
+ *
+ *  @param card    a pointer to sdio_mmc_card
+ *  @param handler  sdio_irq_handler
+ *  @return         0-success else failure
+ */
+static int woal_sdio_claim_irq(sdio_mmc_card *card, sdio_irq_handler_t *handler)
+{
+	int ret;
+	struct sdio_func *func = card->func;
+
+	BUG_ON(!func);
+	BUG_ON(!func->card);
+
+	card->sdio_oob_irq_workqueue = alloc_ordered_workqueue(
+		"SDIO_OOB_IRQ_WORKQ",
+		__WQ_LEGACY | WQ_MEM_RECLAIM | WQ_HIGHPRI);
+	MLAN_INIT_WORK(&card->sdio_oob_irq_work, woal_sdio_oob_irq_work);
+	ret = oob_sdio_irq_register(card);
+	if (ret) {
+		destroy_workqueue(card->sdio_oob_irq_workqueue);
+		card->sdio_oob_irq_workqueue = NULL;
+		return ret;
+	}
+	ret = sdio_func_intr_enable(func, handler);
+	if (ret) {
+		oob_sdio_irq_unregister(card);
+		destroy_workqueue(card->sdio_oob_irq_workqueue);
+		card->sdio_oob_irq_workqueue = NULL;
+	}
+	card->sdio_func_intr_enabled = MTRUE;
+	return ret;
+}
+
+/**
+ *  @brief This function release the oob sdio irq
+ *
+ *  @param card    a pointer to sdio_mmc_card
+ *  @return         0-success else failure
+ */
+static int woal_sdio_release_irq(sdio_mmc_card *card)
+{
+	struct sdio_func *func = card->func;
+	BUG_ON(!func);
+	BUG_ON(!func->card);
+
+	oob_sdio_irq_unregister(card);
+	flush_workqueue(card->sdio_oob_irq_workqueue);
+	destroy_workqueue(card->sdio_oob_irq_workqueue);
+	card->sdio_oob_irq_workqueue = NULL;
+
+	if (card->sdio_func_intr_enabled) {
+		sdio_func_intr_disable(func);
+		card->sdio_func_intr_enabled = MFALSE;
+	}
+
+	return 0;
+}
+
+/**
+ *  @brief This function request oob gpio
+ *
+ *  @param card    a pointer to sdio_mmc_card
+ *  @param oob_gpio  oob gpio
+ *  @return         0-success else failure
+ */
+static int woal_request_gpio(sdio_mmc_card *card, t_u8 oob_gpio)
+{
+#if defined(IMX_SUPPORT)
+	struct device_node *node;
+	node = of_find_compatible_node(NULL, NULL, "nxp,wifi-oob-int");
+	if (!node)
+		return -1;
+	card->oob_irq = irq_of_parse_and_map(node, 0);
+	PRINTM(MMSG, "SDIO OOB IRQ: %d", card->oob_irq);
+	return 0;
+#else
+	return -1;
+#endif
+}
+#endif
+
 /**  @brief This function updates the card types
  *
  *  @param handle   A Pointer to the moal_handle structure
@@ -496,11 +748,11 @@ static t_u16 woal_update_card_type(t_void *card)
 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
 	}
 #endif
-#ifdef SDIW615
-	if (cardp_sd->func->device == SD_DEVICE_ID_IW615) {
-		card_type = CARD_TYPE_SDIW615;
-		moal_memcpy_ext(NULL, driver_version, CARD_SDIW615,
-				strlen(CARD_SDIW615), strlen(driver_version));
+#ifdef SDIW610
+	if (cardp_sd->func->device == SD_DEVICE_ID_IW610) {
+		card_type = CARD_TYPE_SDIW610;
+		moal_memcpy_ext(NULL, driver_version, CARD_SDIW610,
+				strlen(CARD_SDIW610), strlen(driver_version));
 		moal_memcpy_ext(
 			NULL,
 			driver_version + strlen(INTF_CARDTYPE) +
@@ -627,7 +879,9 @@ void woal_sdio_remove(struct sdio_func *func)
 
 				/* check if woal_sdio_interrupt() is running */
 				while (card->handle->main_state !=
-				       MOAL_END_MAIN_PROCESS)
+					       MOAL_END_MAIN_PROCESS &&
+				       card->handle->main_state !=
+					       MOAL_STATE_IDLE)
 					woal_sched_timeout(2); /* wait until
 								  woal_sdio_interrupt
 								  ends */
@@ -943,6 +1197,7 @@ static mlan_status woal_sdiommc_write_reg(moal_handle *handle, t_u32 reg,
 	sdio_writeb(((sdio_mmc_card *)handle->card)->func, (t_u8)data, reg,
 		    (int *)&ret);
 	sdio_release_host(((sdio_mmc_card *)handle->card)->func);
+	PRINTM(MREG, "sdio w %x = %x (%x)\n", reg, data, ret);
 	return ret;
 }
 
@@ -965,6 +1220,7 @@ static mlan_status woal_sdiommc_read_reg(moal_handle *handle, t_u32 reg,
 			 (int *)&ret);
 	sdio_release_host(((sdio_mmc_card *)handle->card)->func);
 	*data = val;
+	PRINTM(MREG, "sdio r %x = %x (%x)\n", reg, *data, ret);
 
 	return ret;
 }
@@ -985,6 +1241,7 @@ static mlan_status woal_sdio_writeb(moal_handle *handle, t_u32 reg, t_u8 data)
 	sdio_writeb(((sdio_mmc_card *)handle->card)->func, (t_u8)data, reg,
 		    (int *)&ret);
 	sdio_release_host(((sdio_mmc_card *)handle->card)->func);
+	PRINTM(MREG, "sdio w %x = %x (%x)\n", reg, data, ret);
 	return ret;
 }
 
@@ -1006,6 +1263,7 @@ static mlan_status woal_sdio_readb(moal_handle *handle, t_u32 reg, t_u8 *data)
 			 (int *)&ret);
 	sdio_release_host(((sdio_mmc_card *)handle->card)->func);
 	*data = val;
+	PRINTM(MREG, "sdio r %x = %x (%x)\n", reg, *data, ret);
 
 	return ret;
 }
@@ -1029,6 +1287,7 @@ static mlan_status woal_sdio_f0_readb(moal_handle *handle, t_u32 reg,
 			    (int *)&ret);
 	sdio_release_host(((sdio_mmc_card *)handle->card)->func);
 	*data = val;
+	PRINTM(MREG, "sdio f0 r %x = %x (%x)\n", reg, *data, ret);
 
 	return ret;
 }
@@ -1232,6 +1491,11 @@ mlan_status woal_sdiommc_bus_register(void)
 		return MLAN_STATUS_FAILURE;
 	}
 
+	/* init GPIO PORT for wakeup purpose */
+	GPIO_PORT_INIT();
+	/* set default value */
+	GPIO_PORT_TO_HIGH();
+
 	LEAVE();
 	return ret;
 }
@@ -1267,7 +1531,12 @@ static void woal_sdiommc_unregister_dev(moal_handle *handle)
 #endif
 		/* Release the SDIO IRQ */
 		sdio_claim_host(card->func);
-		sdio_release_irq(card->func);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0)
+		if (moal_extflg_isset(handle, EXT_INTMODE))
+			woal_sdio_release_irq(card);
+		else
+#endif
+			sdio_release_irq(card->func);
 		sdio_disable_func(card->func);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
 		if (handle->driver_status)
@@ -1281,6 +1550,7 @@ static void woal_sdiommc_unregister_dev(moal_handle *handle)
 
 		sdio_set_drvdata(card->func, NULL);
 
+		GPIO_PORT_TO_LOW();
 		PRINTM(MWARN, "Making the sdio dev card as NULL\n");
 		card->handle = NULL;
 	}
@@ -1302,12 +1572,26 @@ static mlan_status woal_sdiommc_register_dev(moal_handle *handle)
 
 	ENTER();
 
+	GPIO_PORT_INIT();
+	GPIO_PORT_TO_HIGH();
+
 	/* save adapter pointer in card */
 	card->handle = handle;
 	func = card->func;
 	sdio_claim_host(func);
+
 	/* Request the SDIO IRQ */
-	ret = sdio_claim_irq(func, woal_sdio_interrupt);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0)
+	if (moal_extflg_isset(handle, EXT_INTMODE)) {
+		ret = woal_request_gpio(card, card->handle->params.gpiopin);
+		if (ret) {
+			PRINTM(MERROR, "Fail to request gpio\n");
+			goto release_host;
+		}
+		ret = woal_sdio_claim_irq(card, woal_sdio_interrupt);
+	} else
+#endif
+		ret = sdio_claim_irq(func, woal_sdio_interrupt);
 	if (ret) {
 		PRINTM(MFATAL, "sdio_claim_irq failed: ret=%d\n", ret);
 		goto release_host;
@@ -1329,7 +1613,12 @@ static mlan_status woal_sdiommc_register_dev(moal_handle *handle)
 	return MLAN_STATUS_SUCCESS;
 
 release_irq:
-	sdio_release_irq(func);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0)
+	if (moal_extflg_isset(handle, EXT_INTMODE))
+		woal_sdio_release_irq(card);
+	else
+#endif
+		sdio_release_irq(func);
 release_host:
 	sdio_release_host(func);
 	handle->card = NULL;
@@ -1496,7 +1785,7 @@ static mlan_status woal_sdiommc_get_fw_name(moal_handle *handle)
 
 #if defined(SD8987) || defined(SD8997) || defined(SD9098) ||                   \
 	defined(SD9097) || defined(SDIW624) || defined(SDAW693) ||             \
-	defined(SD8978) || defined(SD9177) || defined(SDIW615)
+	defined(SD8978) || defined(SD9177) || defined(SDIW610)
 	t_u32 magic_reg = handle->card_info->magic_reg;
 	t_u32 magic = 0;
 	t_u32 host_strap_reg = handle->card_info->host_strap_reg;
@@ -1517,7 +1806,7 @@ static mlan_status woal_sdiommc_get_fw_name(moal_handle *handle)
 
 #if defined(SD8987) || defined(SD8997) || defined(SD9098) ||                   \
 	defined(SD9097) || defined(SDIW624) || defined(SDAW693) ||             \
-	defined(SD8978) || defined(SD9177) || defined(SDIW615)
+	defined(SD8978) || defined(SD9177) || defined(SDIW610)
 	/** Revision ID register */
 	woal_sdiommc_read_reg(handle, magic_reg, &magic);
 	/** Revision ID register */
@@ -1684,7 +1973,12 @@ static mlan_status woal_sdiommc_get_fw_name(moal_handle *handle)
 #endif
 #ifdef SDAW693
 	if (IS_SDAW693(handle->card_type)) {
-		if (magic == CHIP_MAGIC_VALUE) {
+		magic &= 0x03;
+		if (magic == 0x03)
+			PRINTM(MMSG, "wlan: SDAW693 in secure-boot mode\n");
+
+		switch (revision_id) {
+		case SDAW693_A0:
 			if (strap == CARD_TYPE_SD_UART)
 				strncpy(handle->card_info->fw_name,
 					SDUARTAW693_COMBO_FW_NAME,
@@ -1693,6 +1987,36 @@ static mlan_status woal_sdiommc_get_fw_name(moal_handle *handle)
 				strncpy(handle->card_info->fw_name,
 					SDSDAW693_COMBO_FW_NAME,
 					FW_NAMW_MAX_LEN);
+			strncpy(handle->card_info->fw_name_wlan,
+				SDAW693_DEFAULT_WLAN_FW_NAME, FW_NAMW_MAX_LEN);
+			break;
+		case SDAW693_A1:
+			if (strap == CARD_TYPE_SD_UART)
+				strncpy(handle->card_info->fw_name,
+					SDUARTAW693_COMBO_V1_FW_NAME,
+					FW_NAMW_MAX_LEN);
+			else
+				strncpy(handle->card_info->fw_name,
+					SDSDAW693_COMBO_V1_FW_NAME,
+					FW_NAMW_MAX_LEN);
+			strncpy(handle->card_info->fw_name_wlan,
+				SDAW693_WLAN_V1_FW_NAME, FW_NAMW_MAX_LEN);
+			if (magic != 0x03) {
+				/* remove extension .se */
+				if (strstr(handle->card_info->fw_name, ".se"))
+					memset(strstr(handle->card_info->fw_name,
+						      ".se"),
+					       '\0', sizeof(".se"));
+				if (strstr(handle->card_info->fw_name_wlan,
+					   ".se"))
+					memset(strstr(handle->card_info
+							      ->fw_name_wlan,
+						      ".se"),
+					       '\0', sizeof(".se"));
+			}
+			break;
+		default:
+			break;
 		}
 	}
 #endif
@@ -1785,15 +2109,33 @@ static mlan_status woal_sdiommc_get_fw_name(moal_handle *handle)
 	}
 #endif
 
-#ifdef SDIW615
-	if (IS_SDIW615(handle->card_type)) {
-		if (magic == CHIP_MAGIC_VALUE) {
-			if (strap == CARD_TYPE_SD_UART)
-				strcpy(handle->card_info->fw_name,
-				       SDUARTIW615_COMBO_FW_NAME);
+#ifdef SDIW610
+	if (IS_SDIW610(handle->card_type)) {
+		magic &= 0x03;
+		if (magic == 0x03)
+			PRINTM(MMSG, "wlan: SDIW610 in secure-boot mode\n");
+		if (strap == CARD_TYPE_SDIW610_UART) {
+			if (handle->params.dual_nb)
+				strncpy(handle->card_info->fw_name,
+					SDUARTSPIIW610_COMBO_FW_NAME,
+					FW_NAMW_MAX_LEN);
 			else
-				strcpy(handle->card_info->fw_name,
-				       SDSDIW615_COMBO_FW_NAME);
+				strncpy(handle->card_info->fw_name,
+					SDUARTIW610_COMBO_FW_NAME,
+					FW_NAMW_MAX_LEN);
+		}
+		strncpy(handle->card_info->fw_name_wlan,
+			SDIW610_DEFAULT_WLAN_FW_NAME, FW_NAMW_MAX_LEN);
+		if (magic != 0x03) {
+			/* remove extension .se */
+			if (strstr(handle->card_info->fw_name, ".se"))
+				memset(strstr(handle->card_info->fw_name,
+					      ".se"),
+				       '\0', sizeof(".se"));
+			if (strstr(handle->card_info->fw_name_wlan, ".se"))
+				memset(strstr(handle->card_info->fw_name_wlan,
+					      ".se"),
+				       '\0', sizeof(".se"));
 		}
 	}
 #endif
@@ -2411,7 +2753,7 @@ done:
 	return;
 }
 
-void woal_trigger_nmi_on_no_dump_event(moal_handle *phandle)
+static void woal_trigger_nmi_on_no_dump_event(moal_handle *phandle)
 {
 	int ret = 0;
 	t_u8 ctrl_data = 0;
@@ -2915,7 +3257,12 @@ void woal_sdio_reset_hw(moal_handle *handle)
 	struct sdio_func *func = card->func;
 	ENTER();
 	sdio_claim_host(func);
-	sdio_release_irq(card->func);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0)
+	if (moal_extflg_isset(handle, EXT_INTMODE))
+		woal_sdio_release_irq(card);
+	else
+#endif
+		sdio_release_irq(card->func);
 	sdio_disable_func(card->func);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
@@ -2941,7 +3288,12 @@ void woal_sdio_reset_hw(moal_handle *handle)
 		func->enable_timeout = 200;
 #endif
 	sdio_enable_func(func);
-	sdio_claim_irq(func, woal_sdio_interrupt);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 0)
+	if (moal_extflg_isset(handle, EXT_INTMODE))
+		woal_sdio_claim_irq(card, woal_sdio_interrupt);
+	else
+#endif
+		sdio_claim_irq(func, woal_sdio_interrupt);
 	sdio_set_block_size(card->func, MLAN_SDIO_BLOCK_SIZE);
 	sdio_release_host(func);
 	LEAVE();
@@ -2972,7 +3324,7 @@ static int woal_sdiommc_reset_fw(moal_handle *handle)
 		ret = -EFAULT;
 		goto done;
 	}
-
+	udelay(4000);
 	/** wait SOC fully wake up */
 	for (tries = 0; tries < MAX_POLL_TRIES; ++tries) {
 		ret = handle->ops.write_reg(handle, reset_reg, 0xba);
@@ -2993,10 +3345,10 @@ static int woal_sdiommc_reset_fw(moal_handle *handle)
 		goto done;
 	}
 #if defined(SD9098) || defined(SD9097) || defined(SDIW624) ||                  \
-	defined(SDAW693) || defined(SD9177) || defined(SDIW615)
+	defined(SDAW693) || defined(SD9177) || defined(SDIW610)
 	if (IS_SD9098(handle->card_type) || IS_SD9097(handle->card_type) ||
 	    IS_SDIW624(handle->card_type) || IS_SD9177(handle->card_type) ||
-	    IS_SDIW615(handle->card_type) || IS_SDAW693(handle->card_type))
+	    IS_SDIW610(handle->card_type) || IS_SDAW693(handle->card_type))
 		handle->ops.write_reg(handle, 0x00, 0x10);
 #endif
 	/* Poll register around 100 ms */
@@ -3058,6 +3410,12 @@ static mlan_status woal_do_sdiommc_flr(moal_handle *handle, bool prepare,
 	if (!prepare)
 		goto perform_init;
 
+	if (!(handle->pmlan_adapter)) {
+		PRINTM(MINFO, "\n Handle null 2 during prepare=%d\n", prepare);
+		LEAVE();
+		return status;
+	}
+
 	/* Reset all interfaces */
 	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
 	mlan_disable_host_int(handle->pmlan_adapter);
diff --git a/mlinux/moal_shim.c b/mlinux/moal_shim.c
index 9bc0d75..be555ef 100644
--- a/mlinux/moal_shim.c
+++ b/mlinux/moal_shim.c
@@ -225,7 +225,8 @@ mlan_status moal_malloc_consistent(t_void *pmoal, t_u32 size, t_u8 **ppbuf,
 		return MLAN_STATUS_FAILURE;
 	}
 #ifdef PCIEAW693
-	if (IS_PCIEAW693(handle->card_type))
+	if (IS_PCIEAW693(handle->card_type) &&
+	    (handle->card_rev == CHIP_AW693_REV_A0))
 		dma |= 0x100000000;
 #endif
 	*pbuf_pa = (t_u64)dma;
@@ -253,7 +254,8 @@ mlan_status moal_mfree_consistent(t_void *pmoal, t_u32 size, t_u8 *pbuf,
 	if (!pbuf || !card)
 		return MLAN_STATUS_FAILURE;
 #ifdef PCIEAW693
-	if (IS_PCIEAW693(handle->card_type))
+	if (IS_PCIEAW693(handle->card_type) &&
+	    (handle->card_rev == CHIP_AW693_REV_A0))
 		buf_pa &= 0xffffffff;
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
@@ -301,7 +303,8 @@ mlan_status moal_map_memory(t_void *pmoal, t_u8 *pbuf, t_u64 *pbuf_pa,
 		return MLAN_STATUS_FAILURE;
 	}
 #ifdef PCIEAW693
-	if (IS_PCIEAW693(handle->card_type))
+	if (IS_PCIEAW693(handle->card_type) &&
+	    (handle->card_rev == CHIP_AW693_REV_A0))
 		dma |= 0x100000000;
 #endif
 	*pbuf_pa = dma;
@@ -328,7 +331,8 @@ mlan_status moal_unmap_memory(t_void *pmoal, t_u8 *pbuf, t_u64 buf_pa,
 	if (!card)
 		return MLAN_STATUS_FAILURE;
 #ifdef PCIEAW693
-	if (IS_PCIEAW693(handle->card_type))
+	if (IS_PCIEAW693(handle->card_type) &&
+	    (handle->card_rev == CHIP_AW693_REV_A0))
 		buf_pa &= 0xffffffff;
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
@@ -1055,11 +1059,17 @@ mlan_status moal_ioctl_complete(t_void *pmoal, pmlan_ioctl_req pioctl_req,
 	}
 
 	if (status != MLAN_STATUS_SUCCESS && status != MLAN_STATUS_COMPLETE)
-		PRINTM(MERROR,
-		       "IOCTL failed: %p id=0x%x, sub_id=0x%x action=%d, status_code=0x%x\n",
-		       pioctl_req, pioctl_req->req_id,
-		       (*(t_u32 *)pioctl_req->pbuf), (int)pioctl_req->action,
-		       pioctl_req->status_code);
+		if (handle->rf_test_mode == MTRUE)
+			PRINTM(MERROR,
+			       "Operation id=0x%x not allowed in rf-mode\n",
+			       pioctl_req->req_id);
+		else
+			PRINTM(MERROR,
+			       "IOCTL failed: %p id=0x%x, sub_id=0x%x action=%d, status_code=0x%x\n",
+			       pioctl_req, pioctl_req->req_id,
+			       (*(t_u32 *)pioctl_req->pbuf),
+			       (int)pioctl_req->action,
+			       pioctl_req->status_code);
 	else
 		PRINTM(MIOCTL,
 		       "IOCTL completed: %p id=0x%x sub_id=0x%x, action=%d,  status=%d, status_code=0x%x\n",
@@ -1209,7 +1219,7 @@ mlan_status moal_send_packet_complete(t_void *pmoal, pmlan_buffer pmbuf,
 					atomic_dec(&handle->tx_pending);
 					if (atomic_dec_return(
 						    &priv->wmm_tx_pending[index]) ==
-					    LOW_TX_PENDING) {
+					    priv->low_tx_pending) {
 						struct netdev_queue *txq =
 							netdev_get_tx_queue(
 								priv->netdev,
@@ -2114,6 +2124,10 @@ mlan_status moal_recv_amsdu_packet(t_void *pmoal, pmlan_buffer pmbuf)
 		}
 		frame->protocol = eth_type_trans(frame, netdev);
 		frame->ip_summed = CHECKSUM_NONE;
+
+		priv->stats.rx_bytes += frame->len;
+		priv->stats.rx_packets++;
+
 		if (in_interrupt())
 			netif_rx(frame);
 		else {
@@ -2322,9 +2336,10 @@ mlan_status moal_recv_packet(t_void *pmoal, pmlan_buffer pmbuf)
 			}
 #endif
 #endif
-			if (priv->multi_ap_flag &&
-			    priv->bss_type == MLAN_BSS_TYPE_STA) {
+			if (priv->wdev->use_4addr &&
+			    priv->wdev->iftype == NL80211_IFTYPE_STATION) {
 				t_u32 transaction_id;
+				t_u32 hash_key;
 				transaction_id =
 					woal_get_dhcp_discover_transation_id(
 						skb);
@@ -2337,6 +2352,23 @@ mlan_status moal_recv_packet(t_void *pmoal, pmlan_buffer pmbuf)
 					dev_kfree_skb(skb);
 					goto done;
 				}
+
+				hash_key = woal_generate_arp_request_hash(skb);
+				// TODO: Drop too old entry
+				if (hash_key) {
+					struct arp_entry *node;
+					hash_for_each_possible (priv->hlist,
+								node, arp_hlist,
+								hash_key) {
+						if (node->hash_key ==
+						    hash_key) {
+							PRINTM(MDATA,
+							       "ARP entry exists, drop pkt\n");
+							dev_kfree_skb(skb);
+							goto done;
+						}
+					}
+				}
 			}
 			if (!netdev)
 				netdev = priv->netdev;
@@ -3043,12 +3075,6 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent)
 	case MLAN_EVENT_ID_DRV_SCAN_REPORT:
 		PRINTM(MINFO, "Scan report\n");
 
-		if (priv->phandle->scan_pending_on_block == MTRUE) {
-			priv->phandle->scan_pending_on_block = MFALSE;
-			priv->phandle->scan_priv = NULL;
-			MOAL_REL_SEMAPHORE(&priv->phandle->async_sem);
-		}
-
 		if (priv->report_scan_result) {
 			priv->report_scan_result = MFALSE;
 #ifdef STA_CFG80211
@@ -3100,7 +3126,11 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent)
 			woal_broadcast_event(priv, (t_u8 *)&pmevent->event_id,
 					     sizeof(mlan_event_id));
 		}
-
+		if (priv->phandle->scan_pending_on_block == MTRUE) {
+			priv->phandle->scan_pending_on_block = MFALSE;
+			priv->phandle->scan_priv = NULL;
+			MOAL_REL_SEMAPHORE(&priv->phandle->async_sem);
+		}
 		if (!is_zero_timeval(priv->phandle->scan_time_start)) {
 			woal_get_monotonic_time(&priv->phandle->scan_time_end);
 			priv->phandle->scan_time +=
@@ -5085,6 +5115,55 @@ t_void moal_updata_peer_signal(t_void *pmoal, t_u32 bss_index, t_u8 *peer_addr,
 		spin_unlock_irqrestore(&priv->tdls_lock, flags);
 	}
 }
+#if 0
+/**
+ *  @brief This function records host time in nano seconds
+ *
+ *  @return                 64 bit value of host time in nano seconds
+ */
+s64 get_host_time_ns(void)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+	struct timespec64 ts;
+#else
+	struct timespec ts;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+	ktime_get_real_ts64(&ts);
+	return timespec64_to_ns(&ts);
+#else
+	getnstimeofday(&ts);
+	return timespec_to_ns(&ts);
+#endif
+}
+#endif
+
+/**
+ *  @brief Retrieves the current system time
+ *
+ *  @param time     Pointer for the seconds of system time
+ *
+ *  @return         MLAN_STATUS_SUCCESS
+ */
+mlan_status moal_get_host_time_ns(t_u64 *time)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+	struct timespec64 ts;
+#else
+	struct timespec ts;
+#endif
+	t_u64 hclk_val;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+	ktime_get_real_ts64(&ts);
+#else
+	getnstimeofday(&ts);
+#endif
+	hclk_val = (ts.tv_sec * 1000000000L) + ts.tv_nsec;
+	*time = hclk_val;
+	return MLAN_STATUS_SUCCESS;
+}
 
 /**
  *  @brief Performs division of 64-bit num with base
diff --git a/mlinux/moal_shim.h b/mlinux/moal_shim.h
index ca6ed5c..5f65acd 100644
--- a/mlinux/moal_shim.h
+++ b/mlinux/moal_shim.h
@@ -103,6 +103,7 @@ t_void moal_hist_data_add(t_void *pmoal, t_u32 bss_index, t_u16 rx_rate,
 
 t_void moal_updata_peer_signal(t_void *pmoal, t_u32 bss_index, t_u8 *peer_addr,
 			       t_s8 snr, t_s8 nflr);
+mlan_status moal_get_host_time_ns(t_u64 *time);
 t_u64 moal_do_div(t_u64 num, t_u32 base);
 
 mlan_status moal_init_timer(t_void *pmoal, t_void **pptimer,
diff --git a/mlinux/moal_sta_cfg80211.c b/mlinux/moal_sta_cfg80211.c
index 3a487b4..225e5a3 100644
--- a/mlinux/moal_sta_cfg80211.c
+++ b/mlinux/moal_sta_cfg80211.c
@@ -166,7 +166,7 @@ static int woal_cfg80211_set_tx_power(struct wiphy *wiphy,
 #else
 				      enum nl80211_tx_power_setting type,
 #endif
-				      int dbm);
+				      int mbm);
 #endif
 
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
@@ -323,6 +323,9 @@ static int woal_cfg80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
 				   u8 tsid, const u8 *peer);
 #endif /* KERNEL_VERSION(3, 8, 0) */
 
+static mlan_status woal_cfg80211_dump_station_info(moal_private *priv,
+						   struct station_info *sinfo);
+
 /** cfg80211 operations */
 static struct cfg80211_ops woal_cfg80211_ops = {
 	.change_virtual_intf = woal_cfg80211_change_virtual_intf,
@@ -490,7 +493,6 @@ static const struct ieee80211_regdomain mrvl_regdom = {
 		REG_RULE(5470 - 10, 5850 + 10, 80, 6, 20, 0),
 	}};
 
-#define AUTH_TX_DEFAULT_WAIT_TIME 2400
 /********************************************************
 				Local Variables
 ********************************************************/
@@ -1255,6 +1257,7 @@ static mlan_status woal_send_domain_info_cmd_fw(moal_private *priv,
 		ret = MLAN_STATUS_FAILURE;
 		goto done;
 	}
+
 	band = priv->phandle->band;
 	if (!priv->wdev->wiphy->bands[band]) {
 		PRINTM(MERROR, "11D: setting domain info in FW failed band=%d",
@@ -1359,6 +1362,124 @@ done:
 	return ret;
 }
 
+/**
+ * @brief Send channel attributes to the FW
+ *
+ * @param priv      A pointer to moal_private structure
+ * @param is6g      whether its a 6g table
+ * @param wait_option  wait option
+ *
+ * @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
+ */
+static mlan_status woal_dnld_chan_attr(moal_private *priv, t_bool is6g,
+				       t_u8 wait_option)
+{
+	mlan_status ret = MLAN_STATUS_SUCCESS;
+	struct ieee80211_supported_band *sband = NULL;
+	struct wiphy *wiphy = NULL;
+	t_u8 i, c = 0;
+	mlan_ds_misc_cfg *misc = NULL;
+	mlan_ds_chan_attr *ca = NULL;
+	mlan_ioctl_req *req = NULL;
+	mlan_status status = MLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!priv || !priv->wdev || !priv->wdev->wiphy) {
+		PRINTM(MERROR, "No priv or no wdev or wiphy in priv\n");
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	wiphy = priv->wdev->wiphy;
+
+	/* Allocate an IOCTL request buffer */
+	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
+	if (req == NULL) {
+		ret = MLAN_STATUS_FAILURE;
+		goto done;
+	}
+	misc = (mlan_ds_misc_cfg *)req->pbuf;
+	misc->sub_command = MLAN_OID_MISC_GET_CHAN_REGION_CFG;
+	req->req_id = MLAN_IOCTL_MISC_CFG;
+	memset(&misc->param.chan_attr_cfg, 0,
+	       sizeof(misc->param.chan_attr_cfg));
+
+	ca = (mlan_ds_chan_attr *)&misc->param.chan_attr_cfg;
+
+	{
+		req->action = MLAN_ACT_SET;
+		sband = wiphy->bands[NL80211_BAND_2GHZ];
+		if (sband) {
+			for (i = 0; i < sband->n_channels; i++, c++) {
+				ca->chan_attr[c].channel =
+					sband->channels[i].hw_value;
+				if (sband->channels[i].flags &
+				    IEEE80211_CHAN_DISABLED)
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_DISABLED;
+				if (sband->channels[i].flags &
+				    IEEE80211_CHAN_NO_IR)
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_PASSIVE;
+				if (sband->channels[i].flags &
+				    IEEE80211_CHAN_RADAR)
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_DFS;
+				if ((sband->channels[i].flags &
+				     IEEE80211_CHAN_NO_HT40MINUS) &&
+				    (sband->channels[i].flags &
+				     IEEE80211_CHAN_NO_HT40PLUS))
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_NOHT40;
+				if (sband->channels[i].flags &
+				    IEEE80211_CHAN_NO_80MHZ)
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_NOHT80;
+			}
+		}
+		sband = wiphy->bands[NL80211_BAND_5GHZ];
+		if (sband) {
+			for (i = 0; i < sband->n_channels; i++, c++) {
+				ca->chan_attr[c].channel =
+					sband->channels[i].hw_value;
+				if (sband->channels[i].flags &
+				    IEEE80211_CHAN_DISABLED)
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_DISABLED;
+				if (sband->channels[i].flags &
+				    IEEE80211_CHAN_NO_IR)
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_PASSIVE;
+				if (sband->channels[i].flags &
+				    IEEE80211_CHAN_RADAR)
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_DFS;
+				if ((sband->channels[i].flags &
+				     IEEE80211_CHAN_NO_HT40MINUS) &&
+				    (sband->channels[i].flags &
+				     IEEE80211_CHAN_NO_HT40PLUS))
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_NOHT40;
+				if (sband->channels[i].flags &
+				    IEEE80211_CHAN_NO_80MHZ)
+					ca->chan_attr[c].flags |=
+						NXP_CHANNEL_NOHT80;
+			}
+		}
+	}
+	c = (c > MLAN_MAX_CHANNEL_NUM) ? MLAN_MAX_CHANNEL_NUM : c;
+	ca->data_len = c * sizeof(chan_attr_t);
+
+	/* Send chan attr command to FW */
+	if (c)
+		status = woal_request_ioctl(priv, req, wait_option);
+
+done:
+	if (status != MLAN_STATUS_PENDING)
+		kfree(req);
+	LEAVE();
+	return ret;
+}
 /**
  * @brief Request the driver to change the channel and
  * change domain info according to that channel
@@ -1972,6 +2093,12 @@ static void woal_save_assoc_params(moal_private *priv,
 			MLAN_MAC_ADDR_LENGTH);
 	if (req->ie && req->ie_len) {
 		priv->sme_current.ie = kzalloc(req->ie_len, GFP_ATOMIC);
+		if (!priv->sme_current.ie) {
+			PRINTM(MERROR,
+			       "Failed to allocate memory for sme params\n");
+			LEAVE();
+			return;
+		}
 		priv->sme_current.ie_len = req->ie_len;
 		moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.ie,
 				req->ie, req->ie_len, priv->sme_current.ie_len);
@@ -2007,7 +2134,7 @@ static void woal_save_assoc_params(moal_private *priv,
 	if (priv->sinfo)
 		memset(priv->sinfo, 0, sizeof(struct station_info));
 	else
-		priv->sinfo = kzalloc(sizeof(struct station_info), GFP_KERNEL);
+		priv->sinfo = kzalloc(sizeof(struct station_info), GFP_ATOMIC);
 	LEAVE();
 }
 
@@ -2170,8 +2297,10 @@ static mlan_status woal_request_set_host_mlme(moal_private *priv, t_u8 *bssid)
 	bss->sub_command = MLAN_OID_BSS_HOST_MLME;
 	req->req_id = MLAN_IOCTL_BSS;
 	req->action = MLAN_ACT_SET;
-	moal_memcpy_ext(priv->phandle, &bss->param.bssid, bssid,
-			MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	if (bssid) {
+		moal_memcpy_ext(priv->phandle, &bss->param.bssid, bssid,
+				MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
+	}
 	/* Send IOCTL request to MLAN */
 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
 done:
@@ -2396,9 +2525,48 @@ static int woal_cfg80211_authenticate(struct wiphy *wiphy,
 	}
 
 	if (priv->auth_flag == 0) {
+		/*
+		 * The priority of auth req is highest so we need to cancel
+		 * current exist remain on channel for same function.
+		 * EX: If wfd0 supplicant often scans, mlan0 is difficult to
+		 * get the chance to request ROC.
+		 * Risk: If exist one is another auth, it will be replaced
+		 * with new auth ROC request.
+		 * Avoid: if using woal_cfg80211_mgmt_tx_cancel_wait(), we
+		 * cannot sure the result when the API reports cancel event
+		 * to cfg80211 if priv->phandle->cookie != 0.
+		 */
+		if (priv->phandle->remain_on_channel) {
+			moal_private *remain_priv = NULL;
+			remain_priv =
+				priv->phandle
+					->priv[priv->phandle->remain_bss_index];
+			if (!remain_priv) {
+				/* cannot find its priv, weird! keep
+				 * continuing... */
+				PRINTM(MERROR,
+				       "mgmt_tx_cancel_wait: Wrong remain_bss_index=%d\n",
+				       priv->phandle->remain_bss_index);
+			} else {
+				if (woal_cfg80211_remain_on_channel_cfg(
+					    remain_priv, MOAL_IOCTL_WAIT, MTRUE,
+					    (t_u8 *)&status, NULL, 0, 0)) {
+					/* fail to cancel current one! keep
+					 * continuing... */
+					PRINTM(MERROR,
+					       "mgmt_tx_cancel_wait: Fail to cancel remain on channel\n");
+				} else {
+					/* only cancel is successfully then
+					 * change the flag */
+					priv->phandle->remain_on_channel =
+						MFALSE;
+				}
+			}
+		}
+
 		if (woal_cfg80211_remain_on_channel_cfg(
 			    priv, MOAL_IOCTL_WAIT, MFALSE, (t_u8 *)&status,
-			    req->bss->channel, 0, AUTH_TX_DEFAULT_WAIT_TIME)) {
+			    req->bss->channel, 0, priv->auth_tx_wait_time)) {
 			PRINTM(MERROR, "Fail to configure remain on channel\n");
 			ret = -EFAULT;
 			goto done;
@@ -2648,6 +2816,35 @@ void woal_host_mlme_work_queue(struct work_struct *work)
 	}
 }
 
+/**
+ *  @brief This workqueue function handles association timeout event in event
+ * queue case
+ *
+ *  @param priv         pointer to moal_private
+ *  @param assoc_info   pointer to cfg80211_bss
+ *
+ *  @return        N/A
+ */
+
+void woal_host_mlme_process_assoc_timeout(moal_private *priv,
+					  struct cfg80211_bss *bss)
+{
+	/* Send Assoc Failure with Timeout to CFG80211 */
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
+	struct cfg80211_assoc_failure data;
+	memset(&data, 0, sizeof(struct cfg80211_assoc_failure));
+	data.timeout = 1;
+	data.bss[0] = bss;
+	PRINTM(MEVENT, "wlan: HostMlme assoc failure\n");
+	cfg80211_assoc_failure(priv->netdev, &data);
+#else
+	PRINTM(MEVENT, "wlan: HostMlme assoc timeout\n");
+	cfg80211_assoc_timeout(priv->netdev, bss);
+#endif
+	memset(priv->cfg_bssid, 0, ETH_ALEN);
+	woal_clear_conn_params(priv);
+}
+
 /**
  *  @brief This workqueue function handles association response in event queue
  * case
@@ -2803,6 +3000,36 @@ void woal_host_mlme_process_assoc_resp(moal_private *priv,
 	}
 }
 
+/**
+ * @brief   Handle assoc timeout event (When AP do not respond to (Re)Assoc
+ * Request)
+ *
+ * @param priv          A pointer moal_private structure
+ * @param pchan_info    A pointer to cfg80211_assoc_request structre
+ *
+ * @return          N/A
+ */
+
+static void woal_assoc_timeout_event(moal_private *priv,
+				     struct cfg80211_assoc_request *req)
+{
+	struct woal_event *evt;
+	unsigned long flags;
+	moal_handle *handle = priv->phandle;
+	evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
+	if (evt) {
+		evt->priv = priv;
+		evt->type = WOAL_EVENT_ASSOC_TIMEOUT;
+		evt->assoc_bss = req->bss;
+		INIT_LIST_HEAD(&evt->link);
+		spin_lock_irqsave(&handle->evt_lock, flags);
+		list_add_tail(&evt->link, &handle->evt_queue);
+		spin_unlock_irqrestore(&handle->evt_lock, flags);
+		queue_work(handle->evt_workqueue, &handle->evt_work);
+	}
+	// coverity[leaked_storage:SUPPRESS]
+}
+
 /**
  * @brief   Handle assoc response event
  *
@@ -2851,7 +3078,6 @@ static void woal_assoc_resp_event(moal_private *priv,
 		queue_work(handle->evt_workqueue, &handle->evt_work);
 	}
 	kfree(assoc_req);
-	// coverity[leaked_storage:SUPPRESS]
 	return;
 }
 
@@ -2924,6 +3150,11 @@ static int woal_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
 		return -EBUSY;
 	}
 
+	if (!req || !req->bss) {
+		ret = -EINVAL;
+		goto done;
+	}
+
 	/** cancel pending scan */
 	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
 
@@ -2933,6 +3164,7 @@ static int woal_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
 
 	memset(ssid_bssid, 0, sizeof(mlan_ssid_bssid));
 	rcu_read_lock();
+
 	ssid_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
 	moal_memcpy_ext(priv->phandle, ssid_bssid->bssid, req->bss->bssid,
 			ETH_ALEN, sizeof(ssid_bssid->bssid));
@@ -2960,6 +3192,18 @@ static int woal_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
 		goto done;
 	}
 
+	if (req->bss) {
+		if ((!priv->phandle->params.reg_alpha2 ||
+		     strncmp(priv->phandle->params.reg_alpha2, "99",
+			     strlen("99")))
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+		    &&
+		    (!moal_extflg_isset(priv->phandle, EXT_COUNTRY_IE_IGNORE))
+#endif
+		)
+			woal_process_country_ie(priv, req->bss);
+	}
+
 #ifdef STA_WEXT
 	if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
 		switch (req->crypto.wpa_versions) {
@@ -3041,9 +3285,15 @@ static int woal_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
 done:
 
 	if (!ret) {
+		struct station_info sinfo;
 		priv->rssi_low = DEFAULT_RSSI_LOW_THRESHOLD;
 
 		woal_save_assoc_params(priv, req, ssid_bssid);
+		memset(&sinfo, 0, sizeof(sinfo));
+		if (MLAN_STATUS_SUCCESS !=
+		    woal_cfg80211_dump_station_info(priv, &sinfo)) {
+			PRINTM(MERROR, "Failed to get station info\n");
+		}
 
 		memset(&bss_info, 0, sizeof(bss_info));
 		if (MLAN_STATUS_SUCCESS !=
@@ -3093,9 +3343,8 @@ done:
 			ret = 0;
 		} else {
 			ssid_bssid->assoc_rsp.assoc_resp_len = 0;
-			ret = -EFAULT;
-			memset(priv->cfg_bssid, 0, ETH_ALEN);
-			woal_clear_conn_params(priv);
+			ret = 0;
+			woal_assoc_timeout_event(priv, req);
 		}
 		priv->host_mlme = MFALSE;
 		priv->auth_flag = 0;
@@ -3912,8 +4161,10 @@ create_custom_regdomain(moal_private *priv,
 		       chflags);
 		new_rule = false;
 
-		if (chflags & NXP_CHANNEL_DISABLED)
+		if (chflags & NXP_CHANNEL_DISABLED) {
+			prev_chflags = chflags;
 			continue;
+		}
 
 		if (band == IEEE80211_BAND_5GHZ) {
 			if (!(chflags & NXP_CHANNEL_NOHT80))
@@ -3937,16 +4188,8 @@ create_custom_regdomain(moal_private *priv,
 			new_rule = true;
 		}
 		if (!new_rule && pwr != prev_pwr) {
-			if (band == IEEE80211_BAND_2GHZ &&
-			    !(chflags & NXP_CHANNEL_NOHT40)) {
-				/* skip adding new pwr rule for 40 MHz 2G
-				 * overlapping bonded channels, as max tx
-				 * power value may differ
-				 */
-			} else {
-				valid_rules++;
-				new_rule = true;
-			}
+			valid_rules++;
+			new_rule = true;
 		}
 
 		rule = &regd->reg_rules[valid_rules - 1];
@@ -4143,7 +4386,7 @@ static int woal_update_custom_regdomain(moal_private *priv, struct wiphy *wiphy)
 	}
 	regd = create_custom_regdomain(priv, &misc->param.custom_reg_domain);
 	if (regd) {
-		PRINTM(MMSG, "call regulatory_set_wiphy_regd %c%c",
+		PRINTM(MMSG, "call regulatory_set_wiphy_regd %c%c\n",
 		       misc->param.custom_reg_domain.region.country_code[0],
 		       misc->param.custom_reg_domain.region.country_code[1]);
 		wiphy->regulatory_flags &=
@@ -4340,6 +4583,7 @@ woal_cfg80211_reg_notifier(struct wiphy *wiphy,
 		PRINTM(MCMND, "Regulatory domain BY_COUNTRY_IE\n");
 		break;
 	}
+
 	if (priv->wdev && priv->wdev->wiphy &&
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
 	    !(wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) &&
@@ -4355,7 +4599,14 @@ woal_cfg80211_reg_notifier(struct wiphy *wiphy,
 		priv->phandle->band = band;
 	}
 
-	if (handle->params.edmac_ctrl && IS_CARD9098(priv->phandle->card_type))
+	if (priv->wdev && priv->wdev->wiphy &&
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
+	    !(wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
+#endif
+	) {
+		woal_dnld_chan_attr(priv, MFALSE, MOAL_IOCTL_WAIT);
+	}
+	if (handle->params.edmac_ctrl)
 		woal_edmac_cfg(priv, priv->phandle->country_code);
 
 	LEAVE();
@@ -5140,7 +5391,7 @@ static int woal_connect_ft_over_air(moal_private *priv, t_u8 *bssid,
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
 	if (woal_cfg80211_remain_on_channel_cfg(priv, wait_option, MFALSE,
 						&status, chan, 0,
-						AUTH_TX_DEFAULT_WAIT_TIME)) {
+						priv->auth_tx_wait_time)) {
 		PRINTM(MERROR, "Failed remain on channel config\n");
 	}
 #endif
@@ -6125,7 +6376,7 @@ static int woal_cfg80211_get_tx_power(struct wiphy *wiphy,
  *
  * @param wiphy           A pointer to wiphy structure
  * @param type            TX power adjustment type
- * @param dbm             TX power in dbm
+ * @param mbm             TX power in mbm
  *
  * @return                0 -- success, otherwise fail
  */
@@ -6138,12 +6389,13 @@ static int woal_cfg80211_set_tx_power(struct wiphy *wiphy,
 #else
 				      enum nl80211_tx_power_setting type,
 #endif
-				      int dbm)
+				      int mbm)
 {
 	int ret = 0;
 	moal_private *priv = NULL;
 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
 	mlan_power_cfg_t power_cfg;
+	int dbm = MBM_TO_DBM(mbm);
 
 	ENTER();
 	memset(&power_cfg, 0, sizeof(power_cfg));
@@ -6157,6 +6409,11 @@ static int woal_cfg80211_set_tx_power(struct wiphy *wiphy,
 
 	if (type) {
 		power_cfg.is_power_auto = 0;
+		if (mbm < 0 || (mbm % 100)) {
+			PRINTM(MERROR, "Invalid tx power value %d mbm\n", mbm);
+			LEAVE();
+			return -EOPNOTSUPP;
+		}
 		power_cfg.power_level = dbm;
 	} else
 		power_cfg.is_power_auto = 1;
@@ -7029,6 +7286,7 @@ int woal_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
 	int i;
 	int ret = 0;
+	moal_private *priv = NULL;
 	mlan_status status = MLAN_STATUS_SUCCESS;
 	mlan_ds_misc_mef_flt_cfg mef_cfg;
 	mef_entry_t *mef_entry = NULL;
@@ -7039,8 +7297,11 @@ int woal_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
 	t_u8 byte_seq[MAX_NUM_BYTE_SEQ + 1];
 	const t_u8 ipv4_mc_mac[] = {0x33, 0x33};
 	const t_u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
-	moal_private *priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
 	mlan_ds_hs_cfg hscfg;
+	priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
+	if (!priv) {
+		return 0;
+	}
 
 	PRINTM(MCMND, "<--- Enter woal_cfg80211_suspend --->\n");
 	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
@@ -9144,6 +9405,12 @@ void woal_save_conn_params(moal_private *priv,
 	}
 	if (sme->ie && sme->ie_len) {
 		priv->sme_current.ie = kzalloc(sme->ie_len, GFP_KERNEL);
+		if (!priv->sme_current.ie) {
+			PRINTM(MERROR,
+			       "Failed to allocate memory for sme params\n");
+			LEAVE();
+			return;
+		}
 		moal_memcpy_ext(priv->phandle, (void *)priv->sme_current.ie,
 				sme->ie, sme->ie_len, sme->ie_len);
 	}
@@ -9609,6 +9876,7 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev,
 #else
 	if (params->he_capa_len)
 		req_len += sizeof(MrvlExtIEtypesHeader_t) + params->he_capa_len;
+
 #endif
 #endif
 	req = woal_alloc_mlan_ioctl_req(req_len);
@@ -9789,6 +10057,7 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev,
 			sizeof(MrvlExtIEtypesHeader_t) + params->he_capa_len;
 		tlv = (MrvlIEtypes_Data_t *)pos;
 	}
+
 #endif
 	DBG_HEXDUMP(MCMD_D, "sta tlv", &bss->param.sta_info.tlv[0],
 		    bss->param.sta_info.tlv_len);
@@ -10439,6 +10708,11 @@ mlan_status woal_register_cfg80211(moal_private *priv)
 	wiphy->flags |=
 		WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_OFFCHAN_TX;
 	wiphy->flags |= WIPHY_FLAG_AP_UAPSD | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+
+	wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
+				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
+
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
 	if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
 		wiphy->flags |= WIPHY_FLAG_REPORTS_OBSS;
diff --git a/mlinux/moal_sta_cfg80211.h b/mlinux/moal_sta_cfg80211.h
index 193c64e..a07b458 100644
--- a/mlinux/moal_sta_cfg80211.h
+++ b/mlinux/moal_sta_cfg80211.h
@@ -3,7 +3,7 @@
  * @brief This file contains the STA CFG80211 specific defines.
  *
  *
- * Copyright 2011-2021 NXP
+ * Copyright 2011-2024 NXP
  *
  * This software file (the File) is distributed by NXP
  * under the terms of the GNU General Public License Version 2, June 1991
diff --git a/mlinux/moal_uap.c b/mlinux/moal_uap.c
index c422f61..e7fb331 100644
--- a/mlinux/moal_uap.c
+++ b/mlinux/moal_uap.c
@@ -1917,6 +1917,17 @@ static int woal_uap_antenna_cfg(struct net_device *dev, struct ifreq *req)
 		mreq->action = MLAN_ACT_SET;
 		radio->param.ant_cfg.tx_antenna = antenna_config.tx_mode;
 		radio->param.ant_cfg.rx_antenna = antenna_config.rx_mode;
+	}
+
+	status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
+	if (status != MLAN_STATUS_SUCCESS) {
+		PRINTM(MERROR, "Failed to set new antenna config\n");
+		ret = -EFAULT;
+		goto done;
+	}
+
+	/* Notify the CFG80211 layer only on SUCCESS from FW */
+	if ((status == MLAN_STATUS_SUCCESS) && (mreq->action == MLAN_ACT_SET)) {
 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
 		if (IS_CARD9098(priv->phandle->card_type) ||
 		    IS_CARD9097(priv->phandle->card_type) ||
@@ -1930,11 +1941,6 @@ static int woal_uap_antenna_cfg(struct net_device *dev, struct ifreq *req)
 #endif
 	}
 
-	status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
-	if (status != MLAN_STATUS_SUCCESS) {
-		ret = -EFAULT;
-		goto done;
-	}
 	if (mreq->action == MLAN_ACT_GET) {
 		antenna_config.tx_mode = radio->param.ant_cfg.tx_antenna;
 		antenna_config.rx_mode = radio->param.ant_cfg.rx_antenna;
@@ -2156,7 +2162,8 @@ static int woal_uap_get_dfs_chan(t_u8 pri_chan, t_u8 bw,
 			       {116, 120, 124, 128},
 			       {132, 136, 140, 144}};
 	t_u8 find = false;
-	int i, j;
+	int j;
+	int i;
 	t_u8 sec_chan = 0;
 	mlan_ds_11h_chan_dfs_state *pos = ch_dfs_state;
 	t_u8 n_chan = 1;
@@ -2790,7 +2797,8 @@ static int woal_uap_sta_deauth_ioctl(struct net_device *dev, struct ifreq *req)
 			sizeof(mlan_deauth_param),
 			sizeof(bss->param.deauth_param));
 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
-	if (status != MLAN_STATUS_SUCCESS) {
+	if ((status != MLAN_STATUS_SUCCESS) &&
+	    (status != MLAN_STATUS_PENDING)) {
 		ret = -EFAULT;
 		if (copy_to_user(req->ifr_data, &ioctl_req->status_code,
 				 sizeof(t_u32)))
@@ -3175,7 +3183,8 @@ static int woal_uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
 	}
 
 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
-	if (status != MLAN_STATUS_SUCCESS) {
+	if ((status != MLAN_STATUS_SUCCESS) &&
+	    (status != MLAN_STATUS_PENDING)) {
 		ret = -EFAULT;
 		if (copy_to_user(req->ifr_data, &ioctl_req->status_code,
 				 sizeof(t_u32)))
@@ -3931,6 +3940,9 @@ int woal_uap_set_11ax_status(moal_private *priv, t_u8 action, t_u8 band,
 				&hecap_ie->ext_id, he_cfg.he_cap.len,
 				he_cfg.he_cap.len);
 	}
+#define HE_MAC_CAP_TWT_REQ_SUPPORT MBIT(1)
+	/* uap mode should be TWT responder only */
+	he_cfg.he_cap.he_mac_cap[0] &= ~HE_MAC_CAP_TWT_REQ_SUPPORT;
 	if (action == MLAN_ACT_DISABLE) {
 		if (he_cfg.he_cap.len &&
 		    (he_cfg.he_cap.ext_id == HE_CAPABILITY)) {
diff --git a/mlinux/moal_uap.h b/mlinux/moal_uap.h
index f5a1402..0019594 100644
--- a/mlinux/moal_uap.h
+++ b/mlinux/moal_uap.h
@@ -103,6 +103,11 @@ Change log:
 /** BSS RESET */
 #define UAP_BSS_RESET 2
 
+/* HE MAC Capabilities Information field BIT 1 for TWT Req */
+#define HE_MAC_CAP_TWT_REQ_SUPPORT MBIT(1)
+/* HE MAC Capabilities Information field BIT 2 for TWT Resp*/
+#define HE_MAC_CAP_TWT_RESP_SUPPORT MBIT(2)
+
 /** wapi_msg */
 typedef struct _wapi_msg {
 	/** message type */
diff --git a/mlinux/moal_uap_cfg80211.c b/mlinux/moal_uap_cfg80211.c
index 267d54f..bc2940e 100644
--- a/mlinux/moal_uap_cfg80211.c
+++ b/mlinux/moal_uap_cfg80211.c
@@ -614,6 +614,43 @@ static t_u8 woal_check_11ax_capability(moal_private *priv, t_u8 band,
 }
 #endif
 
+#if KERNEL_VERSION(4, 20, 0) <= CFG80211_VERSION_CODE
+/**
+ * @brief check channel width with HE capabilities
+ * @param priv            A pointer to moal private structure
+ * @param chandef         A pointer to cfg80211_chan_def structure
+ * @return                0 -- channel width supported, otherwise not supported
+ */
+static t_u8 woal_check_chan_width_capa(moal_private *priv,
+				       struct cfg80211_chan_def *chandef)
+{
+	mlan_fw_info fw_info;
+	mlan_ds_11ax_he_capa *phe_cap = NULL;
+	ENTER();
+	memset(&fw_info, 0, sizeof(mlan_fw_info));
+	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
+	if (chandef->chan->band == NL80211_BAND_5GHZ) {
+		phe_cap = (mlan_ds_11ax_he_capa *)fw_info.hw_he_cap;
+		if (((chandef->width == NL80211_CHAN_WIDTH_160) &&
+		     (!(phe_cap->he_phy_cap[0] & MBIT(3)))) ||
+		    ((chandef->width == NL80211_CHAN_WIDTH_80P80) &&
+		     (!(phe_cap->he_phy_cap[0] & MBIT(4))))) {
+			PRINTM(MCMND, "FW don't support %s in %s band",
+			       (chandef->width == NL80211_CHAN_WIDTH_160) ?
+				       "160MHz" :
+				       "80+80 MHz",
+			       (chandef->chan->band == NL80211_BAND_5GHZ) ?
+				       "5G" :
+				       "6G");
+			LEAVE();
+			return MFALSE;
+		}
+	}
+	LEAVE();
+	return MTRUE;
+}
+#endif
+
 /**
  * @brief get ht_cap from beacon ie
  *
@@ -994,6 +1031,13 @@ static int woal_cfg80211_beacon_config(moal_private *priv,
 			sizeof(struct cfg80211_chan_def), sizeof(priv->chan));
 #endif
 
+#if KERNEL_VERSION(4, 20, 0) <= CFG80211_VERSION_CODE
+	if (!woal_check_chan_width_capa(priv, &params->chandef)) {
+		ret = -EFAULT;
+		goto done;
+	}
+#endif
+
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
 	woal_convert_chan_to_bandconfig(priv, &bandcfg, &params->chandef);
 #endif
@@ -1467,6 +1511,11 @@ static int woal_cfg80211_beacon_config(moal_private *priv,
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
 		hecap_ie = (IEEEtypes_HECap_t *)woal_parse_ext_ie_tlv(
 			ie, ie_len, HE_CAPABILITY);
+#if CFG80211_VERSION_CODE > KERNEL_VERSION(5, 3, 0)
+		if (params->twt_responder == MFALSE) {
+			hecap_ie->he_mac_cap[0] &= ~HE_MAC_CAP_TWT_RESP_SUPPORT;
+		}
+#endif
 #endif
 		woal_uap_set_11ax_status(priv, MLAN_ACT_ENABLE,
 					 sys_config->bandcfg.chanBand,
@@ -1828,6 +1877,9 @@ static int woal_cfg80211_add_vlan_vir_if(struct wiphy *wiphy,
 	new_priv->bss_index = priv->bss_index;
 	new_priv->parent_priv = priv;
 	new_priv->wdev->iftype = NL80211_IFTYPE_AP_VLAN;
+	new_priv->max_tx_pending = MAX_TX_PENDING;
+	new_priv->low_tx_pending = LOW_TX_PENDING;
+	skb_queue_head_init(&new_priv->tx_q);
 
 	ndev->ieee80211_ptr->use_4addr = params->use_4addr;
 
@@ -1849,6 +1901,17 @@ static int woal_cfg80211_add_vlan_vir_if(struct wiphy *wiphy,
 
 	if (new_dev)
 		*new_dev = ndev;
+
+	if (ndev->ieee80211_ptr->use_4addr && !priv->multi_ap_flag) {
+		/* Supports backhaul and fronthaul BSS and enable four_address
+		 * flag */
+		if (MLAN_STATUS_SUCCESS ==
+		    woal_multi_ap_cfg(priv, MOAL_IOCTL_WAIT,
+				      EASY_MESH_MULTI_AP_BH_AND_FH_BSS)) {
+			priv->multi_ap_flag = EASY_MESH_MULTI_AP_BH_AND_FH_BSS;
+		}
+	}
+
 fail:
 	LEAVE();
 	return ret;
@@ -3051,6 +3114,10 @@ int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
 #ifdef STA_SUPPORT
 	moal_private *pmpriv = NULL;
 #endif
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
+	moal_private *dfs_priv =
+		woal_get_priv_bss_type(priv->phandle, MLAN_BSS_TYPE_DFS);
+#endif
 
 	ENTER();
 
@@ -3076,6 +3143,21 @@ int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
 	if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
 		woal_cancel_cac_block(priv);
 #endif
+
+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
+	if (dfs_priv && dfs_priv->radar_background) {
+		PRINTM(MMSG, "Cancel background radar detection\n");
+		woal_11h_cancel_chan_report_ioctl(dfs_priv, MOAL_IOCTL_WAIT);
+		dfs_priv->chan_rpt_pending = MFALSE;
+		dfs_priv->radar_background = MFALSE;
+		woal_update_channels_dfs_state(
+			dfs_priv, dfs_priv->chan_rpt_req.chanNum,
+			dfs_priv->chan_rpt_req.bandcfg.chanWidth, DFS_USABLE);
+		memset(&dfs_priv->chan_rpt_req, 0,
+		       sizeof(mlan_ds_11h_chan_rep_req));
+		cfg80211_background_cac_abort(priv->phandle->wiphy);
+	}
+#endif
 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
 	memset(&priv->chan, 0, sizeof(struct cfg80211_chan_def));
 	if (priv->phandle->is_cac_timer_set &&
@@ -3136,6 +3218,7 @@ int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
 	memset(priv->uap_wep_key, 0, sizeof(priv->uap_wep_key));
 	priv->channel = 0;
 	priv->bandwidth = 0;
+	priv->multi_ap_flag = 0;
 
 	PRINTM(MMSG, "wlan: %s AP stopped\n", dev->name);
 done:
@@ -3692,6 +3775,9 @@ int woal_cfg80211_set_radar_background(struct wiphy *wiphy,
 		woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
 		priv->chan_rpt_pending = MFALSE;
 		priv->radar_background = MFALSE;
+		woal_update_channels_dfs_state(
+			priv, priv->chan_rpt_req.chanNum,
+			priv->chan_rpt_req.bandcfg.chanWidth, DFS_USABLE);
 		memset(&priv->chan_rpt_req, 0,
 		       sizeof(mlan_ds_11h_chan_rep_req));
 		LEAVE();
diff --git a/mlinux/moal_usb.c b/mlinux/moal_usb.c
index e6302b1..65e7ea4 100644
--- a/mlinux/moal_usb.c
+++ b/mlinux/moal_usb.c
@@ -35,7 +35,7 @@ extern struct semaphore AddRemoveCardSem;
 ********************************************************/
 
 #if defined(USB8997) || defined(USB9098) || defined(USB9097) ||                \
-	defined(USB8978) || defined(USBIW624) || defined(USBIW615)
+	defined(USB8978) || defined(USBIW624) || defined(USBIW610)
 /** Card-type detection frame response */
 typedef struct {
 	/** 32-bit ACK+WINNER field */
@@ -101,10 +101,10 @@ static struct usb_device_id woal_usb_table[] = {
 	{NXP_USB_DEVICE(USBIW624_VID_1, USBIW624_PID_2,
 			"NXP WLAN USB Adapter")},
 #endif
-#ifdef USBIW615
-	{NXP_USB_DEVICE(USBIW615_VID_1, USBIW615_PID_1,
+#ifdef USBIW610
+	{NXP_USB_DEVICE(USBIW610_VID_1, USBIW610_PID_1,
 			"NXP WLAN USB Adapter")},
-	{NXP_USB_DEVICE(USBIW615_VID_1, USBIW615_PID_2,
+	{NXP_USB_DEVICE(USBIW610_VID_1, USBIW610_PID_2,
 			"NXP WLAN USB Adapter")},
 #endif
 	/* Terminating entry */
@@ -138,8 +138,8 @@ static struct usb_device_id woal_usb_table_skip_fwdnld[] = {
 	{NXP_USB_DEVICE(USBIW624_VID_1, USBIW624_PID_2,
 			"NXP WLAN USB Adapter")},
 #endif
-#ifdef USBIW615
-	{NXP_USB_DEVICE(USBIW615_VID_1, USBIW615_PID_2,
+#ifdef USBIW610
+	{NXP_USB_DEVICE(USBIW610_VID_1, USBIW610_PID_2,
 			"NXP WLAN USB Adapter")},
 #endif
 	/* Terminating entry */
@@ -507,7 +507,7 @@ rx_ret:
 ********************************************************/
 
 #if defined(USB8997) || defined(USB9098) || defined(USB9097) ||                \
-	defined(USB8978) || defined(USBIW624) || defined(USBIW615)
+	defined(USB8978) || defined(USBIW624) || defined(USBIW610)
 /**
  *  @brief  Check chip revision
  *
@@ -836,18 +836,18 @@ static t_u16 woal_update_card_type(t_void *card)
 					strlen(KERN_VERSION));
 	}
 #endif
-#ifdef USBIW615
+#ifdef USBIW610
 	if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
-		    (__force __le16)USBIW615_PID_1 ||
+		    (__force __le16)USBIW610_PID_1 ||
 	    woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
-		    (__force __le16)USBIW615_PID_2) {
-		card_type = CARD_TYPE_USBIW615;
-		moal_memcpy_ext(NULL, driver_version, CARD_USBIW615,
-				strlen(CARD_USBIW615), strlen(driver_version));
+		    (__force __le16)USBIW610_PID_2) {
+		card_type = CARD_TYPE_USBIW610;
+		moal_memcpy_ext(NULL, driver_version, CARD_USBIW610,
+				strlen(CARD_USBIW610), strlen(driver_version));
 		moal_memcpy_ext(NULL,
 				driver_version + strlen(INTF_CARDTYPE) +
 					strlen(KERN_VERSION),
-				V17, strlen(V17),
+				V18, strlen(V18),
 				strlen(driver_version) - strlen(INTF_CARDTYPE) -
 					strlen(KERN_VERSION));
 	}
@@ -922,9 +922,9 @@ static int woal_usb_probe(struct usb_interface *intf,
 #ifdef USBIW624
 			case (__force __le16)USBIW624_PID_1:
 #endif /* USBIW624 */
-#ifdef USBIW615
-			case (__force __le16)USBIW615_PID_1:
-#endif /* USBIW615 */
+#ifdef USBIW610
+			case (__force __le16)USBIW610_PID_1:
+#endif /* USBIW610 */
 
 				/* If skip FW is set, we must return error so
 				 * the next driver can download the FW */
@@ -955,9 +955,9 @@ static int woal_usb_probe(struct usb_interface *intf,
 #ifdef USBIW624
 			case (__force __le16)USBIW624_PID_2:
 #endif /* USBIW624 */
-#ifdef USBIW615
-			case (__force __le16)USBIW615_PID_2:
-#endif /* USBIW615 */
+#ifdef USBIW610
+			case (__force __le16)USBIW610_PID_2:
+#endif /* USBIW610 */
 
 				usb_cardp->boot_state = USB_FW_READY;
 				break;
@@ -2097,7 +2097,7 @@ static mlan_status woal_usb_get_fw_name(moal_handle *handle)
 {
 	mlan_status ret = MLAN_STATUS_SUCCESS;
 #if defined(USB8997) || defined(USB9098) || defined(USB9097) ||                \
-	defined(USB8978) || defined(USBIW624) || defined(USBIW615)
+	defined(USB8978) || defined(USBIW624) || defined(USBIW610)
 	t_u32 revision_id = 0;
 	t_u32 strap = 0;
 	t_u32 boot_mode = 0;
@@ -2118,7 +2118,7 @@ static mlan_status woal_usb_get_fw_name(moal_handle *handle)
 #endif
 
 #if defined(USB8997) || defined(USB9098) || defined(USB9097) ||                \
-	defined(USB8978) || defined(USBIW624) || defined(USBIW615)
+	defined(USB8978) || defined(USBIW624) || defined(USBIW610)
 	ret = woal_check_chip_revision(handle, &revision_id, &strap,
 				       &boot_mode);
 	if (ret != MLAN_STATUS_SUCCESS) {
@@ -2236,14 +2236,42 @@ static mlan_status woal_usb_get_fw_name(moal_handle *handle)
 				USBUSBIW624_COMBO_FW_NAME, FW_NAMW_MAX_LEN);
 	}
 #endif
-#ifdef USBIW615
-	if (IS_USBIW615(handle->card_type)) {
-		if (strap == CARD_TYPE_USB_UART)
-			strcpy(handle->card_info->fw_name,
-			       USBUARTIW615_COMBO_FW_NAME);
-		else
-			strcpy(handle->card_info->fw_name,
-			       USBUSBIW615_COMBO_FW_NAME);
+#ifdef USBIW610
+	if (IS_USBIW610(handle->card_type)) {
+		if (boot_mode == 0x03)
+			PRINTM(MMSG, "wlan: USB-IW610 in secure-boot mode\n");
+		if (strap == CARD_TYPE_USBIW610_UART) {
+			if (handle->params.dual_nb)
+				strncpy(handle->card_info->fw_name,
+					USBUARTSPIIW610_COMBO_FW_NAME,
+					FW_NAMW_MAX_LEN);
+			else
+				strncpy(handle->card_info->fw_name,
+					USBUARTIW610_COMBO_FW_NAME,
+					FW_NAMW_MAX_LEN);
+		} else if (strap == CARD_TYPE_USBIW610_USB) {
+			if (handle->params.dual_nb)
+				strncpy(handle->card_info->fw_name,
+					USBUSBSPIIW610_COMBO_FW_NAME,
+					FW_NAMW_MAX_LEN);
+			else
+				strncpy(handle->card_info->fw_name,
+					USBUSBIW610_COMBO_FW_NAME,
+					FW_NAMW_MAX_LEN);
+		}
+		strncpy(handle->card_info->fw_name_wlan,
+			USBIW610_DEFAULT_WLAN_FW_NAME, FW_NAMW_MAX_LEN);
+		if (boot_mode != 0x03) {
+			/* remove extension .se */
+			if (strstr(handle->card_info->fw_name, ".se"))
+				memset(strstr(handle->card_info->fw_name,
+					      ".se"),
+				       '\0', sizeof(".se"));
+			if (strstr(handle->card_info->fw_name_wlan, ".se"))
+				memset(strstr(handle->card_info->fw_name_wlan,
+					      ".se"),
+				       '\0', sizeof(".se"));
+		}
 	}
 #endif
 
diff --git a/mlinux/moal_usb.h b/mlinux/moal_usb.h
index dd4fa95..edd5748 100644
--- a/mlinux/moal_usb.h
+++ b/mlinux/moal_usb.h
@@ -98,14 +98,14 @@ Change Log:
 #define USBIW624_PID_2 0x020F
 #endif /* USBIW624 */
 
-#ifdef USBIW615
+#ifdef USBIW610
 /** USB VID 1 */
-#define USBIW615_VID_1 0x0471
+#define USBIW610_VID_1 0x0471
 /** USB PID 1 */
-#define USBIW615_PID_1 0x021E
+#define USBIW610_PID_1 0x0214
 /** USB PID 2 */
-#define USBIW615_PID_2 0x021F
-#endif /* USBIW615 */
+#define USBIW610_PID_2 0x0215
+#endif /* USBIW610 */
 
 /** Boot state: FW download */
 #define USB_FW_DNLD 1
@@ -120,7 +120,7 @@ Change Log:
 
 #if defined(USB8997) || defined(USB9098) || defined(USB9097) ||                \
 	defined(USB8978) || defined(USB8801) || defined(USBIW624) ||           \
-	defined(USBIW615)
+	defined(USBIW610)
 /* Transmit buffer size for chip revision check */
 #define CHIP_REV_TX_BUF_SIZE 16
 /* Receive buffer size for chip revision check */
@@ -189,12 +189,14 @@ Change Log:
 #define USBIW624_DEFAULT_WLAN_FW_NAME "nxp/usbiw624_wlan.bin"
 #endif /* USBIW624 */
 
-#ifdef USBIW615
-#define USBIW615_DEFAULT_COMBO_FW_NAME "nxp/usbusbiw615_combo.bin"
-#define USBUARTIW615_COMBO_FW_NAME "nxp/usbuartiw615_combo.bin"
-#define USBUSBIW615_COMBO_FW_NAME "nxp/usbusbiw615_combo.bin"
-#define USBIW615_DEFAULT_WLAN_FW_NAME "nxp/usbiw615_wlan.bin"
-#endif /* USBIW615 */
+#ifdef USBIW610
+#define USBIW610_DEFAULT_COMBO_FW_NAME "nxp/usbusbspi_iw610.bin.se"
+#define USBUARTIW610_COMBO_FW_NAME "nxp/usbuart_iw610.bin.se"
+#define USBUARTSPIIW610_COMBO_FW_NAME "nxp/usbuartspi_iw610.bin.se"
+#define USBUSBIW610_COMBO_FW_NAME "nxp/usbusb_iw610.bin.se"
+#define USBUSBSPIIW610_COMBO_FW_NAME "nxp/usbusbspi_iw610.bin.se"
+#define USBIW610_DEFAULT_WLAN_FW_NAME "nxp/usb_iw610.bin.se"
+#endif /* USBIW610 */
 
 /** urb context */
 typedef struct _urb_context {
diff --git a/mlinux/moal_wext.c b/mlinux/moal_wext.c
index 8f686ff..f979af9 100644
--- a/mlinux/moal_wext.c
+++ b/mlinux/moal_wext.c
@@ -77,6 +77,8 @@ static const struct iw_priv_args woal_private_args[] = {
 	{WOAL_TXBUF_CFG, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
 	 "txbufcfg"},
 	{WOAL_SLEEP_PD, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "sleeppd"},
+	{WOAL_FW_WAKEUP_METHOD, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
+	 "fwwakeupmethod"},
 	{WOAL_AUTH_TYPE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
 	 "authtype"},
 	{WOAL_PORT_CTRL, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
@@ -2777,8 +2779,7 @@ static int woal_set_essid(struct net_device *dev, struct iw_request_info *info,
 					       0);
 				ret = MLAN_STATUS_SUCCESS;
 
-				LEAVE();
-				return ret;
+				goto setessid_ret;
 			}
 		}
 #endif