Quellcode durchsuchen

Merge cc769c13c5d6d16702209e51fcb4e0fbcaecad8b on remote branch

Change-Id: I8679a7f713b9a21bf0f34ccba32c52456b64e02e
Linux Build Service Account vor 1 Jahr
Ursprung
Commit
84915e10c6
100 geänderte Dateien mit 4000 neuen und 964 gelöschten Zeilen
  1. 90 2
      Android.mk
  2. 6 0
      Kbuild
  3. 44 0
      Kconfig
  4. 5 1
      components/action_oui/core/src/wlan_action_oui_main.c
  5. 32 0
      components/action_oui/dispatcher/inc/wlan_action_oui_cfg.h
  6. 3 0
      components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h
  7. 6 2
      components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c
  8. 42 4
      components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h
  9. 17 2
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c
  10. 0 11
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c
  11. 180 18
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c
  12. 0 24
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h
  13. 2 2
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c
  14. 5 2
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c
  15. 4 4
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_tables_2x2_dbs_i.h
  16. 6 4
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_tables_2x2_dbs_sbs_i.h
  17. 2 0
      components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h
  18. 81 13
      components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c
  19. 15 0
      components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c
  20. 124 9
      components/dp/core/inc/wlan_dp_main.h
  21. 14 11
      components/dp/core/inc/wlan_dp_objmgr.h
  22. 46 8
      components/dp/core/inc/wlan_dp_priv.h
  23. 26 26
      components/dp/core/inc/wlan_dp_txrx.h
  24. 89 49
      components/dp/core/src/wlan_dp_bus_bandwidth.c
  25. 122 39
      components/dp/core/src/wlan_dp_fisa_rx.c
  26. 22 12
      components/dp/core/src/wlan_dp_fisa_rx.h
  27. 387 89
      components/dp/core/src/wlan_dp_main.c
  28. 36 19
      components/dp/core/src/wlan_dp_nud_tracking.c
  29. 11 7
      components/dp/core/src/wlan_dp_periodic_sta_stats.c
  30. 19 2
      components/dp/core/src/wlan_dp_rx_fst.c
  31. 1 0
      components/dp/core/src/wlan_dp_rx_thread.c
  32. 49 41
      components/dp/core/src/wlan_dp_softap_txrx.c
  33. 83 66
      components/dp/core/src/wlan_dp_txrx.c
  34. 8 2
      components/dp/core/src/wlan_dp_wfds.c
  35. 27 0
      components/dp/dispatcher/inc/wlan_dp_api.h
  36. 13 13
      components/dp/dispatcher/inc/wlan_dp_public_struct.h
  37. 26 10
      components/dp/dispatcher/inc/wlan_dp_ucfg_api.h
  38. 14 0
      components/dp/dispatcher/src/wlan_dp_api.c
  39. 427 184
      components/dp/dispatcher/src/wlan_dp_ucfg_api.c
  40. 4 3
      components/ftm_time_sync/core/src/ftm_time_sync_main.c
  41. 1 1
      components/fw_offload/core/inc/wlan_fw_offload_main.h
  42. 2 2
      components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
  43. 1 1
      components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
  44. 4 0
      components/mlme/core/inc/wlan_mlme_main.h
  45. 6 0
      components/mlme/core/inc/wlan_mlme_twt_api.h
  46. 8 0
      components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h
  47. 16 0
      components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c
  48. 73 0
      components/mlme/dispatcher/inc/wlan_mlme_api.h
  49. 70 0
      components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
  50. 37 0
      components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h
  51. 95 1
      components/mlme/dispatcher/src/wlan_mlme_api.c
  52. 35 0
      components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c
  53. 13 0
      components/pmo/core/inc/wlan_pmo_main.h
  54. 18 0
      components/pmo/core/src/wlan_pmo_main.c
  55. 9 0
      components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h
  56. 6 0
      components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c
  57. 1 13
      components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c
  58. 6 6
      components/son/dispatcher/src/son_api.c
  59. 0 11
      components/target_if/connection_mgr/src/target_if_cm_roam_offload.c
  60. 2 1
      components/target_if/cp_stats/src/target_if_mc_cp_stats.c
  61. 8 0
      components/target_if/nan/src/target_if_nan.c
  62. 35 0
      components/tdls/core/src/wlan_tdls_main.c
  63. 21 2
      components/tdls/core/src/wlan_tdls_main.h
  64. 1 1
      components/tdls/core/src/wlan_tdls_peer.c
  65. 15 0
      components/tdls/dispatcher/inc/wlan_tdls_cfg_api.h
  66. 33 0
      components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h
  67. 14 0
      components/tdls/dispatcher/src/wlan_tdls_cfg.c
  68. 12 0
      components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c
  69. 48 0
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c
  70. 41 12
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c
  71. 5 2
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_disconnect.c
  72. 2 1
      components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c
  73. 61 1
      components/umac/mlme/mlo_mgr/inc/wlan_mlo_link_force.h
  74. 340 36
      components/umac/mlme/mlo_mgr/src/wlan_mlo_link_force.c
  75. 2 1
      components/wmi/src/wmi_unified_roam_tlv.c
  76. 52 2
      configs/config_to_feature.h
  77. 8 1
      configs/default_defconfig
  78. 3 0
      configs/kiwi_v2_defconfig
  79. 2 6
      configs/pineapple_consolidate_kiwi-v2_defconfig
  80. 16 4
      configs/pineapple_gki_kiwi-v2_defconfig
  81. 10 3
      core/hdd/inc/wlan_hdd_assoc.h
  82. 10 0
      core/hdd/inc/wlan_hdd_cfg.h
  83. 120 8
      core/hdd/inc/wlan_hdd_main.h
  84. 54 0
      core/hdd/inc/wlan_hdd_mlo.h
  85. 9 7
      core/hdd/inc/wlan_hdd_tx_rx.h
  86. 0 15
      core/hdd/inc/wlan_hdd_wext.h
  87. 23 24
      core/hdd/src/wlan_hdd_assoc.c
  88. 2 2
      core/hdd/src/wlan_hdd_cfg.c
  89. 337 68
      core/hdd/src/wlan_hdd_cfg80211.c
  90. 10 0
      core/hdd/src/wlan_hdd_cfg80211.h
  91. 4 4
      core/hdd/src/wlan_hdd_cfr.c
  92. 63 2
      core/hdd/src/wlan_hdd_cm_api.h
  93. 79 3
      core/hdd/src/wlan_hdd_cm_connect.c
  94. 23 14
      core/hdd/src/wlan_hdd_cm_disconnect.c
  95. 11 6
      core/hdd/src/wlan_hdd_debugfs_llstat.c
  96. 2 2
      core/hdd/src/wlan_hdd_debugfs_offload.c
  97. 8 8
      core/hdd/src/wlan_hdd_debugfs_roam.c
  98. 17 9
      core/hdd/src/wlan_hdd_hostapd.c
  99. 4 1
      core/hdd/src/wlan_hdd_hostapd.h
  100. 4 4
      core/hdd/src/wlan_hdd_hostapd_wext.c

+ 90 - 2
Android.mk

@@ -13,6 +13,14 @@ $(strip \
 )
 endef
 
+LOCAL_MODULE_DDK_BUILD := true
+LOCAL_MODULE_DDK_ALLOW_UNSAFE_HEADERS := true
+
+ifeq ($(shell test $(PLATFORM_VERSION) -lt 14; echo $$?),0)
+    LOCAL_MODULE_DDK_BUILD := false
+    LOCAL_MODULE_DDK_ALLOW_UNSAFE_HEADERS := false
+endif
+
 LOCAL_PATH := $(call my-dir)
 $(call wlog,LOCAL_PATH=$(LOCAL_PATH))
 
@@ -70,12 +78,92 @@ endif
 ifeq ($(LOCAL_MULTI_KO), true)
 LOCAL_ANDROID_ROOT := $(shell pwd)
 LOCAL_WLAN_BLD_DIR := $(LOCAL_ANDROID_ROOT)/$(WLAN_BLD_DIR)
-$(shell find $(LOCAL_WLAN_BLD_DIR)/qcacld-3.0/ -maxdepth 1 \
-	-name '.*' ! -name '.git' -delete {} +)
+$(shell `find $(LOCAL_WLAN_BLD_DIR)/qcacld-3.0/ -maxdepth 1 -name '.*' ! -name '.git' -delete`)
+ifeq ($(LOCAL_MODULE_DDK_BUILD), true)
+# DLKM_DIR was moved for JELLY_BEAN (PLATFORM_SDK 16)
+ifeq ($(call is-platform-sdk-version-at-least,16),true)
+        DLKM_DIR := $(TOP)/$(BOARD_COMMON_DIR)/dlkm
+else
+        DLKM_DIR := build/dlkm
+endif # platform-sdk-version
+
+include $(CLEAR_VARS)
+LOCAL_MOD_NAME := wlan
+LOCAL_MODULE              := qca_cld3_kiwi_v2.ko
+LOCAL_MODULE_KBUILD_NAME  := qca_cld3_kiwi_v2.ko
+LOCAL_MODULE_DEBUG_ENABLE := true
+ifeq ($(PRODUCT_VENDOR_MOVE_ENABLED),true)
+    ifeq ($(WIFI_DRIVER_INSTALL_TO_KERNEL_OUT),true)
+        LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
+    else
+        LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/$(WLAN_CHIPSET)
+    endif
+else
+    LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET)
+endif
+
+
+LOCAL_DEV_NAME := kiwi_v2
+LOCAL_CHIP_NAME := $(LOCAL_DEV_NAME)
+TARGET_MAC_BIN_PATH := /mnt/vendor/persist/$(LOCAL_CHIP_NAME)
+TARGET_FW_DIR := firmware/wlan/qca_cld/$(LOCAL_CHIP_NAME)
+TARGET_CFG_PATH := /vendor/etc/wifi/$(LOCAL_CHIP_NAME)
+TARGET_MAC_BIN_PATH := /mnt/vendor/persist/$(LOCAL_CHIP_NAME)
+
+ifeq ($(PRODUCT_VENDOR_MOVE_ENABLED),true)
+TARGET_FW_PATH := $(TARGET_OUT_VENDOR)/$(TARGET_FW_DIR)
+else
+TARGET_FW_PATH := $(TARGET_OUT_ETC)/$(TARGET_FW_DIR)
+endif
+
+# Create wlan_mac.bin symbolic link as part of the module
+$(call symlink-file,,$(TARGET_MAC_BIN_PATH)/wlan_mac.bin,$(TARGET_FW_PATH)/wlan_mac.bin)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_FW_PATH)/wlan_mac.bin
+
+# Conditionally create module symbolic link
+ifneq ($(findstring $(WLAN_CHIPSET),$(WIFI_DRIVER_DEFAULT)),)
+ifeq ($(PRODUCT_VENDOR_MOVE_ENABLED),true)
+ifneq ($(WIFI_DRIVER_INSTALL_TO_KERNEL_OUT),true)
+$(call symlink-file,,$(TARGET_COPY_OUT_VENDOR)/lib/modules/$(WLAN_CHIPSET)/$(LOCAL_MODULE),$(TARGET_OUT_VENDOR)/lib/modules/$(LOCAL_MODULE))
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_VENDOR)/lib/modules/$(LOCAL_MODULE)
+endif
+else
+$(call symlink-file,,/system/lib/modules/$(WLAN_CHIPSET)/$(LOCAL_MODULE),$(TARGET_OUT)/lib/modules/$(LOCAL_MODULE))
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT)/lib/modules/$(LOCAL_MODULE)
+endif
+endif
 
+# Conditionally create ini symbolic link
+ifeq ($(TARGET_BOARD_AUTO),true)
+$(call symlink-file,,$(TARGET_CFG_PATH)/WCNSS_qcom_cfg.ini,$(TARGET_FW_PATH)/WCNSS_qcom_cfg.ini)
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_FW_PATH)/WCNSS_qcom_cfg.ini
+$(call wlog,"generate soft link because TARGET_BOARD_AUTO true")
+else
+ifneq ($(GENERIC_ODM_IMAGE),true)
+$(call symlink-file,,$(TARGET_CFG_PATH)/WCNSS_qcom_cfg.ini,$(TARGET_FW_PATH)/WCNSS_qcom_cfg.ini)
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_FW_PATH)/WCNSS_qcom_cfg.ini
+$(call wlog,"generate soft link because GENERIC_ODM_IMAGE not true")
+endif
+endif
+
+# Set dependencies so that CNSS family drivers can be compiled ahead.
+ifneq ($(WLAN_PLATFORM_KBUILD_OPTIONS),)
+LOCAL_REQUIRED_MODULES := wlan-platform-module-symvers
+LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,wlan-platform-module-symvers)/Module.symvers
+endif
+
+$(call wlog,TARGET_USES_KERNEL_PLATFORM=$(TARGET_USES_KERNEL_PLATFORM))
+ifeq ($(TARGET_USES_KERNEL_PLATFORM),true)
+    include $(DLKM_DIR)/Build_external_kernelmodule.mk
+else
+    include $(DLKM_DIR)/AndroidKernelModule.mk
+endif
+
+else
 $(foreach chip, $(TARGET_WLAN_CHIP), \
 	$(shell ln -sf . $(LOCAL_WLAN_BLD_DIR)/qcacld-3.0/.$(chip)))
 include $(foreach chip, $(TARGET_WLAN_CHIP), $(LOCAL_PATH)/.$(chip)/Android.mk)
+endif
 
 else # Multi-ok check
 

+ 6 - 0
Kbuild

@@ -4271,6 +4271,7 @@ ccflags-$(CONFIG_WLAN_TRACE_HIDE_SSID) += -DWLAN_TRACE_HIDE_SSID
 ccflags-$(CONFIG_WLAN_FEATURE_11BE) += -DWLAN_FEATURE_11BE
 ccflags-$(CONFIG_WLAN_FEATURE_11BE_MLO) += -DWLAN_FEATURE_11BE_MLO
 ccflags-$(CONFIG_WLAN_FEATURE_11BE_MLO) += -DWLAN_FEATURE_11BE_MLO_ADV_FEATURE
+ccflags-$(CONFIG_WLAN_HDD_MULTI_VDEV_SINGLE_NDEV) += -DWLAN_HDD_MULTI_VDEV_SINGLE_NDEV
 ccflags-$(CONFIG_WLAN_FEATURE_11BE_MLO) += -DWLAN_SUPPORT_11BE_D3_0
 ccflags-$(CONFIG_FIX_TXDMA_LIMITATION) += -DFIX_TXDMA_LIMITATION
 ccflags-$(CONFIG_FEATURE_AST) += -DFEATURE_AST
@@ -4461,6 +4462,7 @@ ccflags-$(CONFIG_WLAN_TRACEPOINTS) += -DWLAN_TRACEPOINTS
 
 ccflags-$(CONFIG_QCACLD_FEATURE_SON) += -DFEATURE_PERPKT_INFO
 ccflags-$(CONFIG_QCACLD_FEATURE_SON) += -DQCA_ENHANCED_STATS_SUPPORT
+ccflags-$(CONFIG_WLAN_FEATURE_CE_RX_BUFFER_REUSE) += -DWLAN_FEATURE_CE_RX_BUFFER_REUSE
 
 CONFIG_NUM_SOC_PERF_CLUSTER ?= 1
 ccflags-y += -DNUM_SOC_PERF_CLUSTER=$(CONFIG_NUM_SOC_PERF_CLUSTER)
@@ -4757,6 +4759,10 @@ ccflags-$(CONFIG_WINDOW_REG_PLD_LOCK_ENABLE) += -DWINDOW_REG_PLD_LOCK_ENABLE
 ccflags-$(CONFIG_DUMP_REO_QUEUE_INFO_IN_DDR) += -DDUMP_REO_QUEUE_INFO_IN_DDR
 ccflags-$(CONFIG_DP_RX_REFILL_CPU_PERF_AFFINE_MASK) += -DDP_RX_REFILL_CPU_PERF_AFFINE_MASK
 ccflags-$(CONFIG_WLAN_FEATURE_AFFINITY_MGR) += -DWLAN_FEATURE_AFFINITY_MGR
+found = $(shell if grep -qF "walt_get_cpus_taken" $(srctree)/kernel/sched/walt/walt.c; then echo "yes" ;else echo "no" ;fi;)
+ifeq ($(findstring yes, $(found)), yes)
+ccflags-y += -DWALT_GET_CPU_TAKEN_SUPPORT
+endif
 
 ifdef CONFIG_MAX_CLIENTS_ALLOWED
 ccflags-y += -DWLAN_MAX_CLIENTS_ALLOWED=$(CONFIG_MAX_CLIENTS_ALLOWED)

+ 44 - 0
Kconfig

@@ -74,6 +74,10 @@ config BUILD_TIMESTAMP
 	bool "Embed timestamp in wlan version"
 	default n
 
+config BUS_AUTO_SUSPEND
+	bool "enable CONFIG_BUS_AUTO_SUSPEND"
+	default n
+
 config CE_DISABLE_SRNG_TIMER_IRQ
 	bool "Enable CE_DISABLE_SRNG_TIMER_IRQ"
 	default n
@@ -494,6 +498,10 @@ config FEATURE_WLAN_SCAN_PNO
 	bool "Enable FEATURE_WLAN_SCAN_PNO"
 	default n
 
+config WALT_GET_CPU_TAKEN_SUPPORT
+	bool "enable WALT_GET_CPU_TAKEN_SUPPORT"
+	default n
+
 config FEATURE_WLAN_WAPI
 	bool "Enable FEATURE_WLAN_WAPI"
 	default n
@@ -848,6 +856,10 @@ config ROME_IF
 	string "Enable ROME_IF"
 	default pci
 
+config RPS
+	bool "enable CONFIG_QCA_CONFIG_RPS"
+	default n
+
 config RX_DEFRAG_DO_NOT_REINJECT
 	bool "Enable RX_DEFRAG_DO_NOT_REINJECT"
 	default n
@@ -915,6 +927,10 @@ config SMMU_S1_UNMAP
 	bool "Enable SMMU_S1_UNMAP"
 	default n
 
+config SMP
+	bool "enable CONFIG_SMP"
+	default n
+
 config SOFTAP_CHANNEL_RANGE
 	bool "Enable SOFTAP_CHANNEL_RANGE"
 	default n
@@ -1132,6 +1148,10 @@ config WLAN_FEATURE_11BE_MLO
 	bool "Enable WLAN_FEATURE_11BE_MLO"
 	default n
 
+config WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
+	bool "Enable WLAN_HDD_MULTI_VDEV_SINGLE_NDEV"
+	default n
+
 config WLAN_FEATURE_11W
 	bool "Enable the WLAN 802.11w Protected Management Frames feature"
 	default n
@@ -1809,8 +1829,32 @@ config NL80211_EXT_FEATURE_PUNCT_SUPPORT
 	bool "enable CONFIG_NL80211_EXT_FEATURE_PUNCT_SUPPORT"
 	default n
 
+config NL80211_TESTMODE
+	bool "enable CONFIG_NL80211_TESTMODE"
+	default n
+
 config DYNAMIC_DEBUG
 	bool "enable CONFIG_DYNAMIC_DEBUG"
 	default n
 
+config DP_MLO_LINK_STATS_SUPPORT
+	bool "enable CONFIG_DP_MLO_LINK_STATS_SUPPORT"
+	default n
+
+config MULTI_IF_NAME
+	string "set MULTI_IF_NAME"
+	default \"wlan\"
+
+config CFG80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA
+	bool "enable CFG80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA"
+	default n
+
+config WLAN_DP_FEATURE_DEFERRED_REO_QDESC_DESTROY
+	bool "enable WLAN_DP_FEATURE_DEFERRED_REO_QDESC_DESTROY"
+	default n
+
+config FEATURE_WLAN_CH_AVOID_EXT
+	bool "enable FEATURE_WLAN_CH_AVOID_EXT"
+	default n
+
 endif # QCA_CLD_WLAN

+ 5 - 1
components/action_oui/core/src/wlan_action_oui_main.c

@@ -188,7 +188,11 @@ static void action_oui_load_config(struct action_oui_psoc_priv *psoc_priv)
 		      cfg_get(psoc,
 			      CFG_ACTION_OUI_ENABLE_CTS2SELF_WITH_QOS_NULL),
 		      ACTION_OUI_MAX_STR_LEN);
-
+	qdf_str_lcopy(psoc_priv->action_oui_str
+			[ACTION_OUI_SEND_SMPS_FRAME_WITH_OMN],
+		      cfg_get(psoc,
+			      CFG_ACTION_OUI_SEND_SMPS_FRAME_WITH_OMN),
+		      ACTION_OUI_MAX_STR_LEN);
 	qdf_str_lcopy(psoc_priv->action_oui_str
 			[ACTION_OUI_AUTH_ASSOC_6MBPS_2GHZ],
 		      cfg_get(psoc, CFG_ACTION_OUI_AUTH_ASSOC_6MBPS_2GHZ),

+ 32 - 0
components/action_oui/dispatcher/inc/wlan_action_oui_cfg.h

@@ -774,6 +774,37 @@
 	"", \
 	"Used to enable CTS2SELF with QoS null frame for specified APs")
 
+/*
+ * <ini>
+ * gActionOUISendSMPSFrameWithOMN - Used to send SMPS frame along with OMN
+ * for specified APs
+ *
+ * Sample OUIs: (All values in Hex)
+ * OUI 1: 000ce7
+ *   OUI data Len: 04
+ *   OUI Data : 88000000
+ *   OUI data Mask: F0 - 11110000
+ *   Info Mask : 01 - only OUI present in Info mask
+ *
+ * gActionOUISendSMPSFrameWithOMN=000ce7 04 88000000 F0 01
+ *
+ * Refer to gEnableActionOUI for more detail about the format.
+ *
+ * Related: gEnableActionOUI
+ *
+ * Supported Feature: Action OUIs
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+#define CFG_ACTION_OUI_SEND_SMPS_FRAME_WITH_OMN CFG_INI_STRING( \
+	"gActionOUISendSMPSFrameWithOMN", \
+	0, \
+	ACTION_OUI_MAX_STR_LEN, \
+	"", \
+	"Used to send SMPS frame along with OMN for specified APs")
+
 #define CFG_ACTION_OUI \
 	CFG(CFG_ACTION_OUI_CCKM_1X1) \
 	CFG(CFG_ACTION_OUI_CONNECT_1X1) \
@@ -791,6 +822,7 @@
 	CFG(CFG_ACTION_OUI_11BE_ALLOW_LIST) \
 	CFG(CFG_ACTION_OUI_DISABLE_DYNAMIC_QOS_NULL_TX_RATE) \
 	CFG(CFG_ACTION_OUI_ENABLE_CTS2SELF_WITH_QOS_NULL) \
+	CFG(CFG_ACTION_OUI_SEND_SMPS_FRAME_WITH_OMN) \
 	CFG(CFG_ACTION_OUI_AUTH_ASSOC_6MBPS_2GHZ) \
 	CFG(CFG_ENABLE_ACTION_OUI)
 #endif

+ 3 - 0
components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h

@@ -103,6 +103,8 @@
  * null tx rate feature if specific vendor OUI received in beacon
  * @ACTION_OUI_ENABLE_CTS2SELF_WITH_QOS_NULL: Enable CTS2SELF with QoS null
  * frame for specified IoT APs.
+ * @ACTION_OUI_SEND_SMPS_FRAME_WITH_OMN: Send SMPS frame along with OMN
+ * frame for specified IoT APs.
  * @ACTION_OUI_HOST_ONLY: host only action id start - placeholder.
  * New Firmware related "ACTION" needs to be added before this placeholder.
  * @ACTION_OUI_HOST_RECONN: reconnect to the same BSSID when wait for
@@ -127,6 +129,7 @@ enum action_oui_id {
 	ACTION_OUI_11BE_OUI_ALLOW = 11,
 	ACTION_OUI_DISABLE_DYNAMIC_QOS_NULL_TX_RATE = 12,
 	ACTION_OUI_ENABLE_CTS2SELF_WITH_QOS_NULL = 13,
+	ACTION_OUI_SEND_SMPS_FRAME_WITH_OMN = 14,
 	/* host&fw interface add above here */
 
 	ACTION_OUI_HOST_ONLY,

+ 6 - 2
components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c

@@ -786,6 +786,7 @@ if_mgr_get_conc_ext_flags(struct wlan_objmgr_vdev *vdev,
 }
 
 static void if_mgr_update_candidate(struct wlan_objmgr_psoc *psoc,
+				    struct wlan_objmgr_vdev *vdev,
 				    struct validate_bss_data *candidate_info)
 {
 	struct scan_cache_entry *scan_entry = candidate_info->scan_entry;
@@ -796,8 +797,10 @@ static void if_mgr_update_candidate(struct wlan_objmgr_psoc *psoc,
 
 	if (mlme_get_bss_11be_allowed(psoc, &candidate_info->peer_addr,
 				      util_scan_entry_ie_data(scan_entry),
-				      util_scan_entry_ie_len(scan_entry)))
+				      util_scan_entry_ie_len(scan_entry)) &&
+	    (!wlan_vdev_mlme_get_user_dis_eht_flag(vdev)))
 		return;
+
 	scan_entry->ie_list.multi_link_bv = NULL;
 	scan_entry->ie_list.ehtcap = NULL;
 	scan_entry->ie_list.ehtop = NULL;
@@ -813,6 +816,7 @@ if_mgr_get_conc_ext_flags(struct wlan_objmgr_vdev *vdev,
 }
 
 static void if_mgr_update_candidate(struct wlan_objmgr_psoc *psoc,
+				    struct wlan_objmgr_vdev *vdev,
 				    struct validate_bss_data *candidate_info)
 {
 }
@@ -841,7 +845,7 @@ QDF_STATUS if_mgr_validate_candidate(struct wlan_objmgr_vdev *vdev,
 	if (!psoc)
 		return QDF_STATUS_E_FAILURE;
 
-	if_mgr_update_candidate(psoc, candidate_info);
+	if_mgr_update_candidate(psoc, vdev, candidate_info);
 	/*
 	 * Do not allow STA to connect on 6Ghz or indoor channel for non dbs
 	 * hardware if SAP and skip_6g_and_indoor_freq_scan ini are present

+ 42 - 4
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -1255,12 +1255,19 @@ void policy_mgr_move_vdev_from_connection_to_disabled_tbl(
  * disabled during connection.
  * @psoc: psoc
  * @vdev: vdev
+ * @peer_assoc: check peer assoc command
+ *
+ * Check the vdev need to be moved to disabled policy mgr table.
+ * If peer_assoc = false, the API will check the forced inactive link bitmap
+ * as well. Vdev will be disabled if vdev's link id is forced inactive(includes
+ * dynamic inactive)
  *
  * Return: true if STA link is need to be disabled else false.
  */
 bool
 policy_mgr_ml_link_vdev_need_to_be_disabled(struct wlan_objmgr_psoc *psoc,
-					    struct wlan_objmgr_vdev *vdev);
+					    struct wlan_objmgr_vdev *vdev,
+					    bool peer_assoc);
 
 /**
  * policy_mgr_is_set_link_in_progress() - Check set link in progress or not
@@ -1328,7 +1335,8 @@ policy_mgr_move_vdev_from_disabled_to_connection_tbl(
 
 static inline bool
 policy_mgr_ml_link_vdev_need_to_be_disabled(struct wlan_objmgr_psoc *psoc,
-					    struct wlan_objmgr_vdev *vdev)
+					    struct wlan_objmgr_vdev *vdev,
+					    bool peer_assoc)
 {
 	return false;
 }
@@ -3989,6 +3997,23 @@ QDF_STATUS policy_mgr_get_updated_scan_and_fw_mode_config(
 bool policy_mgr_is_safe_channel(struct wlan_objmgr_psoc *psoc,
 				uint32_t ch_freq);
 
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+/**
+ * policy_mgr_restrict_sap_on_unsafe_chan() - Check if need check unsafe
+ * channel if SAP start on fixed channel.
+ * @psoc: PSOC object information
+ *
+ * Return: true for success, else false
+ */
+bool policy_mgr_restrict_sap_on_unsafe_chan(struct wlan_objmgr_psoc *psoc);
+#else
+static inline bool
+policy_mgr_restrict_sap_on_unsafe_chan(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
+#endif
+
 /**
  * policy_mgr_is_sap_freq_allowed - Check if the channel is allowed for sap
  * @psoc: PSOC object information
@@ -4911,6 +4936,7 @@ void policy_mgr_handle_link_removal_on_vdev(struct wlan_objmgr_vdev *vdev);
  *                                               concurrency combination
  * @psoc: PSOC object information
  * @is_new_vdev_mlo: Is new vdev a mlo device or not
+ * @new_vdev_id: new vdev id which need concurrency check
  *
  * When a new connection is about to come up check if current
  * concurrency combination including the new connection is
@@ -4919,7 +4945,8 @@ void policy_mgr_handle_link_removal_on_vdev(struct wlan_objmgr_vdev *vdev);
  * Return: True if concurrency is supported, otherwise false.
  */
 bool policy_mgr_is_mlo_sap_concurrency_allowed(struct wlan_objmgr_psoc *psoc,
-					       bool is_new_vdev_mlo);
+					       bool is_new_vdev_mlo,
+					       uint8_t new_vdev_id);
 
 /**
  * policy_mgr_get_conc_ext_flags() - get extended flags for concurrency check
@@ -5118,7 +5145,8 @@ QDF_STATUS policy_mgr_update_active_mlo_num_links(struct wlan_objmgr_psoc *psoc,
 
 static inline bool policy_mgr_is_mlo_sap_concurrency_allowed(
 			struct wlan_objmgr_psoc *psoc,
-			bool is_new_vdev_mlo)
+			bool is_new_vdev_mlo,
+			uint8_t new_vdev_id)
 {
 	return true;
 }
@@ -5440,4 +5468,14 @@ bool policy_mgr_is_beaconing_mode(enum policy_mgr_con_mode mode);
 
 bool policy_mgr_get_nan_sap_scc_on_lte_coex_chnl(struct wlan_objmgr_psoc *psoc);
 
+/**
+ * policy_mgr_reset_sap_mandatory_channels() - Reset the SAP mandatory channels
+ * @psoc: psoc object
+ *
+ * Resets the SAP mandatory channel list and the length of the list
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+policy_mgr_reset_sap_mandatory_channels(struct wlan_objmgr_psoc *psoc);
 #endif /* __WLAN_POLICY_MGR_API_H */

+ 17 - 2
components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c

@@ -1580,6 +1580,22 @@ bool policy_mgr_is_safe_channel(struct wlan_objmgr_psoc *psoc,
 
 	return is_safe;
 }
+
+bool policy_mgr_restrict_sap_on_unsafe_chan(struct wlan_objmgr_psoc *psoc)
+{
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	unsigned long restriction_mask;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid context");
+		return false;
+	}
+
+	restriction_mask =
+		(unsigned long)policy_mgr_get_freq_restriction_mask(pm_ctx);
+	return qdf_test_bit(QDF_SAP_MODE, &restriction_mask);
+}
 #else
 bool policy_mgr_is_safe_channel(struct wlan_objmgr_psoc *psoc,
 				uint32_t ch_freq)
@@ -1730,8 +1746,7 @@ bool policy_mgr_is_sap_restart_required_after_sta_disconnect(
 		}
 
 		if ((is_acs_mode ||
-		     !target_psoc_get_sap_coex_fixed_chan_cap(
-					wlan_psoc_get_tgt_if_handle(psoc))) &&
+		     policy_mgr_restrict_sap_on_unsafe_chan(psoc)) &&
 		    sta_sap_scc_on_lte_coex_chan &&
 		    !policy_mgr_is_safe_channel(psoc, op_ch_freq_list[i]) &&
 		    pm_ctx->last_disconn_sta_freq == op_ch_freq_list[i]) {

+ 0 - 11
components/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c

@@ -4741,17 +4741,6 @@ policy_mgr_get_current_pref_hw_mode_dual_dbs(
 	return next_action;
 }
 
-QDF_STATUS policy_mgr_reset_sap_mandatory_channels(
-		struct policy_mgr_psoc_priv_obj *pm_ctx)
-{
-	pm_ctx->sap_mandatory_channels_len = 0;
-	qdf_mem_zero(pm_ctx->sap_mandatory_channels,
-		     QDF_ARRAY_SIZE(pm_ctx->sap_mandatory_channels) *
-		     sizeof(*pm_ctx->sap_mandatory_channels));
-
-	return QDF_STATUS_SUCCESS;
-}
-
 void policy_mgr_add_sap_mandatory_chan(struct wlan_objmgr_psoc *psoc,
 				       uint32_t ch_freq)
 {

+ 180 - 18
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -2178,8 +2178,9 @@ policy_mgr_ml_sta_active_freq(struct wlan_objmgr_psoc *psoc,
 	if (num_ml_sta > MAX_NUMBER_OF_CONC_CONNECTIONS ||
 	    num_disabled_ml_sta > MAX_NUMBER_OF_CONC_CONNECTIONS ||
 	    num_ml_sta <= num_disabled_ml_sta) {
-		policy_mgr_debug("unexpected ml sta num %d %d",
-				 num_ml_sta, num_disabled_ml_sta);
+		if (num_ml_sta || num_disabled_ml_sta)
+			policy_mgr_rl_debug("unexpected ml sta num %d %d",
+					    num_ml_sta, num_disabled_ml_sta);
 		return;
 	}
 	num_active_ml_sta = num_ml_sta;
@@ -4063,9 +4064,37 @@ void policy_mgr_move_vdev_from_connection_to_disabled_tbl(
 	policy_mgr_dump_current_concurrency(psoc);
 }
 
+static bool
+policy_mgr_vdev_disabled_by_link_force(struct wlan_objmgr_psoc *psoc,
+				       struct wlan_objmgr_vdev *vdev,
+				       bool peer_assoc)
+{
+	uint16_t dynamic_inactive = 0, forced_inactive = 0;
+	uint16_t link_id;
+
+	if (ml_is_nlink_service_supported(psoc) &&
+	    !peer_assoc) {
+		ml_nlink_get_dynamic_inactive_links(psoc, vdev,
+						    &dynamic_inactive,
+						    &forced_inactive);
+		link_id = wlan_vdev_get_link_id(vdev);
+		if ((forced_inactive | dynamic_inactive) &
+		    (1 << link_id)) {
+			policy_mgr_debug("vdev %d linkid %d is forced inactived 0x%0x dyn 0x%x",
+					 wlan_vdev_get_id(vdev),
+					 link_id, forced_inactive,
+					 dynamic_inactive);
+			return true;
+		}
+	}
+
+	return false;
+}
+
 bool
 policy_mgr_ml_link_vdev_need_to_be_disabled(struct wlan_objmgr_psoc *psoc,
-					    struct wlan_objmgr_vdev *vdev)
+					    struct wlan_objmgr_vdev *vdev,
+					    bool peer_assoc)
 {
 	union conc_ext_flag conc_ext_flags;
 
@@ -4077,6 +4106,11 @@ policy_mgr_ml_link_vdev_need_to_be_disabled(struct wlan_objmgr_psoc *psoc,
 	    !wlan_vdev_mlme_is_mlo_link_vdev(vdev))
 		return false;
 
+	/* Check vdev is disabled by link force command */
+	if (policy_mgr_vdev_disabled_by_link_force(psoc, vdev,
+						   peer_assoc))
+		return true;
+
 	conc_ext_flags.value = policy_mgr_get_conc_ext_flags(vdev, false);
 	/*
 	 * For non-assoc link vdev set link as disabled if concurrency is
@@ -4287,6 +4321,73 @@ policy_mgr_trigger_roam_on_link_removal(struct wlan_objmgr_vdev *vdev)
 		policy_mgr_err("roam invoke failed");
 }
 
+static void
+policy_mgr_update_dynamic_inactive_bitmap(
+			struct wlan_objmgr_psoc *psoc,
+			struct wlan_objmgr_vdev *vdev,
+			struct mlo_link_set_active_req *req,
+			struct mlo_link_set_active_resp *resp)
+{
+	uint32_t candidate_inactive_links;
+	uint32_t dyn_inactive_links = 0;
+	uint8_t dyn_num = 0, num = 0, i;
+	uint8_t link_ids[MAX_MLO_LINK_ID * 2];
+
+	if (req->param.force_mode != MLO_LINK_FORCE_MODE_INACTIVE_NUM ||
+	    !req->param.control_flags.dynamic_force_link_num)
+		return;
+
+	/* force inactive num "clear" case, return 0 - no
+	 * dynamic inactive links.
+	 */
+	if (!req->param.force_cmd.link_num) {
+		dyn_inactive_links = 0;
+		dyn_num = 0;
+		goto update;
+	}
+	/* 1. If force inactive overlap with force num bitmap,
+	 * select the inactive link from overlapped links firstly.
+	 * 2. If selected inactive link num <
+	 * req->param.force_cmd.link_num, then select the inactive
+	 * links from current inactive links reported from FW.
+	 */
+	candidate_inactive_links =
+		req->param.force_cmd.ieee_link_id_bitmap &
+		resp->inactive_linkid_bitmap;
+
+	num = ml_nlink_convert_link_bitmap_to_ids(candidate_inactive_links,
+						  QDF_ARRAY_SIZE(link_ids),
+						  link_ids);
+	if (num < req->param.force_cmd.link_num &&
+	    num < QDF_ARRAY_SIZE(link_ids)) {
+		candidate_inactive_links =
+			req->param.force_cmd.ieee_link_id_bitmap &
+			resp->curr_inactive_linkid_bitmap &
+			~candidate_inactive_links;
+		num += ml_nlink_convert_link_bitmap_to_ids(
+				candidate_inactive_links,
+				QDF_ARRAY_SIZE(link_ids) - num,
+				&link_ids[num]);
+	}
+	for (i = 0; i < num; i++) {
+		if (dyn_num >= req->param.force_cmd.link_num)
+			break;
+		dyn_inactive_links |= 1 << link_ids[i];
+		dyn_num++;
+	}
+
+update:
+	policy_mgr_debug("inactive link num %d bitmap 0x%x force inactive 0x%x dyn links 0x%x num %d",
+			 req->param.force_cmd.link_num,
+			 req->param.force_cmd.ieee_link_id_bitmap,
+			 resp->inactive_linkid_bitmap,
+			 dyn_inactive_links, dyn_num);
+	if (dyn_num < req->param.force_cmd.link_num)
+		policy_mgr_debug("unexpected selected dynamic inactive link num %d",
+				 dyn_num);
+	ml_nlink_set_dynamic_inactive_links(psoc, vdev, dyn_inactive_links);
+}
+
 static void
 policy_mgr_handle_vdev_active_inactive_resp(
 					struct wlan_objmgr_psoc *psoc,
@@ -4298,6 +4399,8 @@ policy_mgr_handle_vdev_active_inactive_resp(
 	uint8_t vdev_id_num = 0;
 	uint8_t vdev_ids[WLAN_MLO_MAX_VDEVS] = {0};
 	uint32_t assoc_bitmap = 0;
+	uint16_t dynamic_inactive_bitmap = 0;
+	uint16_t forced_inactive_bitmap = 0;
 
 	/* convert link id to vdev id and update vdev status based
 	 * on both inactive and active bitmap.
@@ -4307,11 +4410,16 @@ policy_mgr_handle_vdev_active_inactive_resp(
 	 * they will be moved to policy mgr disable connection table.
 	 * for other links, they will be in active tables.
 	 */
+	ml_nlink_get_dynamic_inactive_links(psoc, vdev,
+					    &dynamic_inactive_bitmap,
+					    &forced_inactive_bitmap);
+	resp->inactive_linkid_bitmap |= dynamic_inactive_bitmap;
 	ml_nlink_convert_linkid_bitmap_to_vdev_bitmap(
 		psoc, vdev, resp->inactive_linkid_bitmap,
 		&assoc_bitmap,
 		&resp->inactive_sz, resp->inactive,
 		&vdev_id_num, vdev_ids);
+
 	ml_nlink_convert_linkid_bitmap_to_vdev_bitmap(
 		psoc, vdev,
 		(~resp->inactive_linkid_bitmap) & assoc_bitmap,
@@ -4468,6 +4576,8 @@ policy_mgr_handle_force_inactive_num_resp(
 		ml_nlink_set_curr_force_inactive_num_state(
 			psoc, vdev, req->param.force_cmd.link_num,
 			req->param.force_cmd.ieee_link_id_bitmap);
+		policy_mgr_update_dynamic_inactive_bitmap(psoc, vdev, req,
+							  resp);
 
 		/* update vdev active inactive status */
 		policy_mgr_handle_vdev_active_inactive_resp(psoc, vdev, req,
@@ -6219,7 +6329,8 @@ next:
 
 bool
 policy_mgr_is_mlo_sap_concurrency_allowed(struct wlan_objmgr_psoc *psoc,
-					  bool is_new_vdev_mlo)
+					  bool is_new_vdev_mlo,
+					  uint8_t new_vdev_id)
 {
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
 	uint32_t conn_index;
@@ -6241,6 +6352,8 @@ policy_mgr_is_mlo_sap_concurrency_allowed(struct wlan_objmgr_psoc *psoc,
 			continue;
 
 		vdev_id = pm_conc_connection_list[conn_index].vdev_id;
+		if (vdev_id == new_vdev_id)
+			continue;
 		vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
 							    WLAN_POLICY_MGR_ID);
 		if (!vdev) {
@@ -7919,7 +8032,7 @@ void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 				 QDF_MAC_ADDR_REF(link_mac_addr));
 		for (link = 0; link < num_links; link++) {
 			policy_mgr_debug("active addr: " QDF_MAC_ADDR_FMT,
-					 QDF_MAC_ADDR_REF(&active_link_addr[link]));
+			   QDF_MAC_ADDR_REF(&active_link_addr[link].bytes[0]));
 			if (!qdf_mem_cmp(link_mac_addr,
 					 &active_link_addr[link].bytes[0],
 					 QDF_MAC_ADDR_SIZE)) {
@@ -11275,14 +11388,17 @@ bool policy_mgr_is_ap_ap_mcc_allow(struct wlan_objmgr_psoc *psoc,
 	enum QDF_OPMODE mode;
 	enum policy_mgr_con_mode con_mode;
 	union conc_ext_flag conc_ext_flags;
-	uint32_t cc_count, i;
+	uint32_t cc_count, i, j, ap_index;
 	uint32_t op_freq[MAX_NUMBER_OF_CONC_CONNECTIONS * 2];
 	uint8_t vdev_id[MAX_NUMBER_OF_CONC_CONNECTIONS * 2];
+	QDF_STATUS status;
+	struct policy_mgr_pcl_list pcl;
 
 	if (!psoc || !vdev || !pdev) {
 		policy_mgr_debug("psoc or vdev or pdev is NULL");
 		return false;
 	}
+
 	cc_count = policy_mgr_get_mode_specific_conn_info(psoc,
 							  &op_freq[0],
 							  &vdev_id[0],
@@ -11294,27 +11410,54 @@ bool policy_mgr_is_ap_ap_mcc_allow(struct wlan_objmgr_psoc *psoc,
 					&op_freq[cc_count],
 					&vdev_id[cc_count],
 					PM_P2P_GO_MODE);
-	for (i = 0 ; i < cc_count; i++) {
-		if (ch_freq == op_freq[i])
+	if (!cc_count)
+		return true;
+
+	mode = wlan_vdev_mlme_get_opmode(vdev);
+	con_mode = policy_mgr_qdf_opmode_to_pm_con_mode(
+				psoc, mode, wlan_vdev_get_id(vdev));
+	qdf_mem_zero(&pcl, sizeof(pcl));
+	status = policy_mgr_get_pcl(psoc, con_mode, pcl.pcl_list, &pcl.pcl_len,
+				    pcl.weight_list,
+				    QDF_ARRAY_SIZE(pcl.weight_list),
+				    wlan_vdev_get_id(vdev));
+	if (!pcl.pcl_len)
+		return true;
+	ap_index = cc_count;
+	for (i = 0 ; i < pcl.pcl_len; i++) {
+		for (j = 0; j < cc_count; j++) {
+			if (op_freq[j] == pcl.pcl_list[i])
+				break;
+		}
+		if (j >= cc_count)
+			continue;
+		if (ch_freq == op_freq[j]) {
+			ap_index = j;
 			break;
-		if (!policy_mgr_is_hw_dbs_capable(psoc))
+		}
+		if (!policy_mgr_is_hw_dbs_capable(psoc)) {
+			ap_index = j;
 			break;
-		if (wlan_reg_is_same_band_freqs(ch_freq, op_freq[i]) &&
-		    !policy_mgr_are_sbs_chan(psoc, ch_freq, op_freq[i]))
+		}
+		if (wlan_reg_is_same_band_freqs(ch_freq, op_freq[j]) &&
+		    !policy_mgr_are_sbs_chan(psoc, ch_freq, op_freq[j])) {
+			ap_index = j;
 			break;
+		}
+		if (wlan_reg_is_same_band_freqs(ch_freq, op_freq[j]) &&
+		    policy_mgr_get_connection_count(psoc) > 2) {
+			ap_index = j;
+			break;
+		}
 	}
 	/* If same band MCC SAP/GO not present, return true,
 	 * no AP to AP channel override
 	 */
-	if (i >= cc_count)
+	if (ap_index >= cc_count)
 		return true;
 
-	*con_freq = op_freq[i];
-	*con_vdev_id = vdev_id[i];
-
-	mode = wlan_vdev_mlme_get_opmode(vdev);
-	con_mode = policy_mgr_qdf_opmode_to_pm_con_mode(psoc, mode,
-							wlan_vdev_get_id(vdev));
+	*con_freq = op_freq[ap_index];
+	*con_vdev_id = vdev_id[ap_index];
 	/*
 	 * For 3Vif concurrency we only support SCC in same MAC
 	 * in below combination:
@@ -11711,3 +11854,22 @@ bool policy_mgr_get_nan_sap_scc_on_lte_coex_chnl(struct wlan_objmgr_psoc *psoc)
 	return pm_ctx->cfg.nan_sap_scc_on_lte_coex_chnl;
 }
 
+QDF_STATUS
+policy_mgr_reset_sap_mandatory_channels(struct wlan_objmgr_psoc *psoc)
+{
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	pm_ctx->sap_mandatory_channels_len = 0;
+	qdf_mem_zero(pm_ctx->sap_mandatory_channels,
+		     QDF_ARRAY_SIZE(pm_ctx->sap_mandatory_channels) *
+		     sizeof(*pm_ctx->sap_mandatory_channels));
+
+	return QDF_STATUS_SUCCESS;
+}
+

+ 0 - 24
components/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h

@@ -937,30 +937,6 @@ enum policy_mgr_conc_next_action
 		policy_mgr_get_current_pref_hw_mode_dual_dbs(
 		struct wlan_objmgr_psoc *psoc);
 
-/**
- * policy_mgr_reset_sap_mandatory_channels() - Reset the SAP mandatory channels
- * @pm_ctx: policy mgr context
- *
- * Resets the SAP mandatory channel list and the length of the list
- *
- * Return: QDF_STATUS
- */
-QDF_STATUS policy_mgr_reset_sap_mandatory_channels(
-		struct policy_mgr_psoc_priv_obj *pm_ctx);
-
-/**
- * policy_mgr_dump_freq_range_per_mac() - Function to print frequency range
- * for both MAC 0 and MAC1 for given Hw mode
- *
- * @freq_range: Policy Mgr context
- * @hw_mode: HW mode
- *
- * This Function will print frequency range for both MAC 0 and MAC1 for given
- * Hw mode
- *
- * Return: void
- *
- */
 void
 policy_mgr_dump_freq_range_per_mac(struct policy_mgr_freq_range *freq_range,
 				   enum policy_mgr_mode hw_mode);

+ 2 - 2
components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c

@@ -530,7 +530,7 @@ QDF_STATUS policy_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
 	policy_mgr_set_dynamic_mcc_adaptive_sch(psoc, enable_mcc_adaptive_sch);
 	pm_ctx->hw_mode_change_in_progress = POLICY_MGR_HW_MODE_NOT_IN_PROGRESS;
 	/* reset sap mandatory channels */
-	status = policy_mgr_reset_sap_mandatory_channels(pm_ctx);
+	status = policy_mgr_reset_sap_mandatory_channels(psoc);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		policy_mgr_err("failed to reset mandatory channels");
 		return status;
@@ -683,7 +683,7 @@ QDF_STATUS policy_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc)
 
 	/* reset sap mandatory channels */
 	if (QDF_IS_STATUS_ERROR(
-		policy_mgr_reset_sap_mandatory_channels(pm_ctx))) {
+		policy_mgr_reset_sap_mandatory_channels(psoc))) {
 		policy_mgr_err("failed to reset sap mandatory channels");
 		status = QDF_STATUS_E_FAILURE;
 		QDF_ASSERT(0);

+ 5 - 2
components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c

@@ -1083,6 +1083,7 @@ policy_mgr_modify_sap_pcl_for_6G_channels(struct wlan_objmgr_psoc *psoc,
 	qdf_freq_t sta_gc_6ghz_freq = 0;
 	uint32_t ap_pwr_type_6g = 0;
 	bool indoor_ch_support = false;
+	bool keep_6ghz_sta_cli_conn;
 
 	pm_ctx = policy_mgr_get_context(psoc);
 	if (!pm_ctx) {
@@ -1130,10 +1131,12 @@ policy_mgr_modify_sap_pcl_for_6G_channels(struct wlan_objmgr_psoc *psoc,
 	policy_mgr_debug("STA power type : %d", ap_pwr_type_6g);
 
 	ucfg_mlme_get_indoor_channel_support(psoc, &indoor_ch_support);
-
+	keep_6ghz_sta_cli_conn = wlan_reg_get_keep_6ghz_sta_cli_connection(
+								pm_ctx->pdev);
 	for (i = 0; i < *pcl_len_org; i++) {
 		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(pcl_list_org[i])) {
-			if (!WLAN_REG_IS_6GHZ_PSC_CHAN_FREQ(pcl_list_org[i]))
+			if (!WLAN_REG_IS_6GHZ_PSC_CHAN_FREQ(pcl_list_org[i]) ||
+			    keep_6ghz_sta_cli_conn)
 				continue;
 			if (ap_pwr_type_6g == REG_VERY_LOW_POWER_AP)
 				goto add_freq;

+ 4 - 4
components/cmn_services/policy_mgr/src/wlan_policy_mgr_tables_2x2_dbs_i.h

@@ -2322,13 +2322,13 @@ fourth_connection_pcl_dbs_sbs_table
 	[PM_24_SCC_MCC_PLUS_5_DBS] = {
 	[PM_STA_MODE] = { PM_SCC_ON_5_CH_5G, PM_SCC_ON_5_CH_5G,
 			 PM_SCC_ON_5_CH_5G},
-	[PM_SAP_MODE] = { PM_SCC_ON_5_5G_SCC_ON_24G, PM_SCC_ON_5_5G_SCC_ON_24G,
-			 PM_SCC_ON_5_5G_SCC_ON_24G} },
+	[PM_SAP_MODE] = { PM_SCC_ON_5_SCC_ON_24, PM_SCC_ON_5_SCC_ON_24,
+			 PM_SCC_ON_5_SCC_ON_24} },
 	[PM_5_SCC_MCC_PLUS_24_DBS] = {
 	[PM_STA_MODE] = { PM_SBS_CH_2G, PM_SBS_CH_2G,
 			  PM_SBS_CH_2G },
-	[PM_SAP_MODE] = { PM_SBS_CH_24G_SCC_CH, PM_SBS_CH_24G_SCC_CH,
-			  PM_SBS_CH_24G_SCC_CH } },
+	[PM_SAP_MODE] = { PM_SCC_ON_24_SCC_ON_5, PM_SCC_ON_24_SCC_ON_5,
+			  PM_SCC_ON_24_SCC_ON_5 } },
 	[PM_MCC_SCC_5G_HIGH_PLUS_5_LOW_SBS] = {
 	[PM_STA_MODE] = {PM_SCC_ON_5G_LOW_5G_LOW_PLUS_SHARED_2G,
 			 PM_SCC_ON_5G_LOW_5G_LOW_PLUS_SHARED_2G,

+ 6 - 4
components/cmn_services/policy_mgr/src/wlan_policy_mgr_tables_2x2_dbs_sbs_i.h

@@ -779,7 +779,7 @@ pm_third_connection_pcl_dbs_sbs_2x2_table = {
 	[PM_STA_MODE] = {
 		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
 	[PM_SAP_MODE] = {
-		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
+		PM_SCC_ON_5_SCC_ON_24, PM_SCC_ON_5_SCC_ON_24, PM_SCC_ON_5_SCC_ON_24},
 	[PM_P2P_CLIENT_MODE] = {
 		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
 	[PM_P2P_GO_MODE] = {PM_24G, PM_24G, PM_24G},
@@ -793,7 +793,7 @@ pm_third_connection_pcl_dbs_sbs_2x2_table = {
 	[PM_STA_MODE] = {
 		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
 	[PM_SAP_MODE] = {
-		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
+		PM_SCC_ON_5_SCC_ON_24, PM_SCC_ON_5_SCC_ON_24, PM_SCC_ON_5_SCC_ON_24},
 	[PM_P2P_CLIENT_MODE] = {
 		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
 	[PM_P2P_GO_MODE] = {PM_24G, PM_24G, PM_24G},
@@ -1560,7 +1560,8 @@ pm_third_connection_pcl_dbs_sbs_2x2_table = {
 	[PM_STA_P2P_CLI_MCC_24_5_1x1] = {
 	[PM_STA_MODE] = {
 		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
-	[PM_SAP_MODE] = {PM_5G, PM_5G, PM_5G},
+	[PM_SAP_MODE] =
+	{PM_SCC_ON_5_SCC_ON_24, PM_SCC_ON_5_SCC_ON_24, PM_SCC_ON_5_SCC_ON_24},
 	[PM_P2P_CLIENT_MODE] = {
 		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
 	[PM_P2P_GO_MODE] = {
@@ -1574,7 +1575,8 @@ pm_third_connection_pcl_dbs_sbs_2x2_table = {
 	[PM_STA_P2P_CLI_MCC_24_5_2x2] = {
 	[PM_STA_MODE] = {
 		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
-	[PM_SAP_MODE] = {PM_5G, PM_5G, PM_5G},
+	[PM_SAP_MODE] =
+	{PM_SCC_ON_5_SCC_ON_24, PM_SCC_ON_5_SCC_ON_24, PM_SCC_ON_5_SCC_ON_24},
 	[PM_P2P_CLIENT_MODE] = {
 		PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
 	[PM_P2P_GO_MODE] = {

+ 2 - 0
components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h

@@ -445,10 +445,12 @@ struct pmf_bcn_protect_stats {
  * struct vdev_summary_extd_stats - vdev summary extended stats
  * @vdev_id: vdev_id of the event
  * @is_mlo_vdev_active: is the mlo vdev currently active
+ * @vdev_tx_power: vdev tx power
  */
 struct vdev_summary_extd_stats {
 	uint8_t vdev_id;
 	bool is_mlo_vdev_active;
+	uint32_t vdev_tx_power;
 };
 
 /**

+ 81 - 13
components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c

@@ -125,7 +125,6 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc,
 	struct wlan_objmgr_vdev *vdev = NULL;
 	struct pdev_mc_cp_stats *pdev_mc_stats;
 	struct pdev_cp_stats *pdev_cp_stats_priv;
-	bool pending = false;
 
 	if (!ev->pdev_stats)
 		return;
@@ -180,17 +179,6 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc,
 			ev->pdev_stats[pdev_id].max_pwr;
 
 	wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
-	if (is_station_stats)
-		goto end;
-
-	if (mac_id == ev->mac_seq_num) {
-		ucfg_mc_cp_stats_reset_pending_req(psoc,
-						   TYPE_CONNECTION_TX_POWER,
-						   &last_req,
-						   &pending);
-		if (last_req.u.get_tx_power_cb && pending)
-			last_req.u.get_tx_power_cb(max_pwr, last_req.cookie);
-	}
 
 end:
 	if (vdev)
@@ -1216,6 +1204,86 @@ end:
 	return QDF_STATUS_E_NULL_VALUE;
 }
 
+static QDF_STATUS
+tgt_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, int *dbm)
+{
+	struct wlan_objmgr_pdev *pdev;
+	struct pdev_mc_cp_stats *pdev_mc_stats;
+	struct pdev_cp_stats *pdev_cp_stats_priv;
+	struct vdev_mc_cp_stats *vdev_mc_stats;
+	struct vdev_cp_stats *vdev_cp_stat;
+	uint32_t vdev_power = 0;
+
+	vdev_cp_stat = wlan_cp_stats_get_vdev_stats_obj(vdev);
+	if (vdev_cp_stat) {
+		wlan_cp_stats_vdev_obj_lock(vdev_cp_stat);
+		vdev_mc_stats = vdev_cp_stat->vdev_stats;
+		vdev_power = vdev_mc_stats->vdev_extd_stats.vdev_tx_power;
+		wlan_cp_stats_vdev_obj_unlock(vdev_cp_stat);
+		if (vdev_power) {
+			*dbm = vdev_power;
+			return QDF_STATUS_SUCCESS;
+		}
+	}
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);
+	if (!pdev_cp_stats_priv) {
+		cp_stats_err("pdev cp stats object is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv);
+	pdev_mc_stats = pdev_cp_stats_priv->pdev_stats;
+	*dbm = pdev_mc_stats->max_pwr;
+	wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static void
+tgt_mc_cp_stats_extract_vdev_and_extd_stats(struct wlan_objmgr_psoc *psoc,
+					    struct stats_event *ev)
+{
+	QDF_STATUS status;
+	struct request_info last_req = {0};
+	bool pending = false;
+	int32_t max_pwr = 0;
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	status = ucfg_mc_cp_stats_get_pending_req(psoc,
+						  TYPE_CONNECTION_TX_POWER,
+						  &last_req);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
+		return;
+	}
+
+	if (ev->pdev_stats)
+		tgt_mc_cp_stats_extract_tx_power(psoc, ev, false);
+	else if (ev->vdev_extd_stats)
+		tgt_mc_cp_stats_extract_vdev_extd_stats(psoc, ev);
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req.vdev_id,
+						    WLAN_CP_STATS_ID);
+	if (!vdev) {
+		cp_stats_err("vdev is null");
+		return;
+	}
+	tgt_mc_cp_stats_get_tx_power(vdev, &max_pwr);
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
+
+	if (tgt_mc_cp_stats_is_last_event(ev, TYPE_CONNECTION_TX_POWER)) {
+		ucfg_mc_cp_stats_reset_pending_req(psoc,
+						   TYPE_CONNECTION_TX_POWER,
+						   &last_req,
+						   &pending);
+		if (last_req.u.get_tx_power_cb && pending)
+			last_req.u.get_tx_power_cb(max_pwr, last_req.cookie);
+	}
+}
+
 static void
 tgt_mc_cp_stats_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
 				       struct request_info *last_req)
@@ -1374,7 +1442,7 @@ QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
 					       struct stats_event *ev)
 {
 	if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_CONNECTION_TX_POWER))
-		tgt_mc_cp_stats_extract_tx_power(psoc, ev, false);
+		tgt_mc_cp_stats_extract_vdev_and_extd_stats(psoc, ev);
 
 	if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_PEER_STATS))
 		tgt_mc_cp_stats_extract_peer_stats(psoc, ev, false);

+ 15 - 0
components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c

@@ -810,6 +810,21 @@ QDF_STATUS ucfg_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev,
 	struct wlan_objmgr_pdev *pdev;
 	struct pdev_mc_cp_stats *pdev_mc_stats;
 	struct pdev_cp_stats *pdev_cp_stats_priv;
+	struct vdev_mc_cp_stats *vdev_mc_stats;
+	struct vdev_cp_stats *vdev_cp_stat;
+	uint32_t vdev_power = 0;
+
+	vdev_cp_stat = wlan_cp_stats_get_vdev_stats_obj(vdev);
+	if (vdev_cp_stat) {
+		wlan_cp_stats_vdev_obj_lock(vdev_cp_stat);
+		vdev_mc_stats = vdev_cp_stat->vdev_stats;
+		vdev_power = vdev_mc_stats->vdev_extd_stats.vdev_tx_power;
+		wlan_cp_stats_vdev_obj_unlock(vdev_cp_stat);
+		if (vdev_power) {
+			*dbm = vdev_power;
+			return QDF_STATUS_SUCCESS;
+		}
+	}
 
 	pdev = wlan_vdev_get_pdev(vdev);
 	pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);

+ 124 - 9
components/dp/core/inc/wlan_dp_main.h

@@ -144,6 +144,83 @@ dp_get_intf_by_macaddr(struct wlan_dp_psoc_context *dp_ctx,
 struct wlan_dp_intf*
 dp_get_intf_by_netdev(struct wlan_dp_psoc_context *dp_ctx, qdf_netdev_t dev);
 
+/**
+ * dp_get_front_link_no_lock() - Get the first link from the dp links list
+ * This API does not use any lock in it's implementation. It is the caller's
+ * directive to ensure concurrency safety.
+ * @dp_intf: DP interface handle
+ * @out_link: double pointer to pass the next link
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+dp_get_front_link_no_lock(struct wlan_dp_intf *dp_intf,
+			  struct wlan_dp_link **out_link);
+
+/**
+ * dp_get_next_link_no_lock() - Get the next link from the link list
+ * This API does not use any lock in it's implementation. It is the caller's
+ * directive to ensure concurrency safety.
+ * @dp_intf: DP interface handle
+ * @cur_link: pointer to the currentlink
+ * @out_link: double pointer to pass the nextlink
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+dp_get_next_link_no_lock(struct wlan_dp_intf *dp_intf,
+			 struct wlan_dp_link *cur_link,
+			 struct wlan_dp_link **out_link);
+
+/**
+ * __dp_take_ref_and_fetch_front_link_safe - Helper macro to lock, fetch
+ * front and next link, take ref and unlock.
+ * @dp_intf: DP interface handle
+ * @dp_link: an dp_link pointer to use as a cursor
+ * @dp_link_next: dp_link pointer to nextlink
+ */
+#define __dp_take_ref_and_fetch_front_link_safe(dp_intf, dp_link, \
+						dp_link_next) \
+	qdf_spin_lock_bh(&(dp_intf)->dp_link_list_lock), \
+	dp_get_front_link_no_lock(dp_intf, &(dp_link)), \
+	dp_get_next_link_no_lock(dp_intf, dp_link, &(dp_link_next)), \
+	qdf_spin_unlock_bh(&(dp_intf)->dp_link_list_lock)
+
+/**
+ * __dp_take_ref_and_fetch_next_link_safe - Helper macro to lock, fetch next
+ * interface, take ref and unlock.
+ * @dp_intf: DP interface handle
+ * @dp_link: dp_link pointer to use as a cursor
+ * @dp_link_next: dp_link pointer to next link
+ */
+#define __dp_take_ref_and_fetch_next_link_safe(dp_intf, dp_link, \
+					       dp_link_next) \
+	qdf_spin_lock_bh(&(dp_intf)->dp_link_list_lock), \
+	dp_link = dp_link_next, \
+	dp_get_next_link_no_lock(dp_intf, dp_link, &(dp_link_next)), \
+	qdf_spin_unlock_bh(&(dp_intf)->dp_link_list_lock)
+
+/**
+ * __dp_is_link_valid - Helper macro to return true/false for valid interface.
+ * @_dp_link: an dp_link pointer to use as a cursor
+ */
+#define __dp_is_link_valid(_dp_link) !!(_dp_link)
+
+/**
+ * dp_for_each_link_held_safe - Interface iterator called
+ *                                      in a delete safe manner
+ * @dp_intf: DP interface handle
+ * @dp_link: an dp_link pointer to use as a cursor
+ * @dp_link_next: dp_link pointer to the next interface
+ *
+ */
+#define dp_for_each_link_held_safe(dp_intf, dp_link, dp_link_next) \
+	for (__dp_take_ref_and_fetch_front_link_safe(dp_intf, dp_link, \
+						     dp_link_next); \
+	     __dp_is_link_valid(dp_link); \
+	     __dp_take_ref_and_fetch_next_link_safe(dp_intf, dp_link, \
+						    dp_link_next))
+
 /* MAX iteration count to wait for dp packet process to complete */
 #define DP_TASK_MAX_WAIT_CNT  100
 /* Milli seconds to wait when packet is getting processed */
@@ -251,6 +328,19 @@ QDF_STATUS wlan_dp_txrx_pdev_attach(ol_txrx_soc_handle soc);
 QDF_STATUS wlan_dp_txrx_pdev_detach(ol_txrx_soc_handle soc, uint8_t pdev_id,
 				    int force);
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * dp_link_switch_notification() - DP notifier for MLO link switch
+ * @vdev: Objmgr vdev handle
+ * @lswitch_req: Link switch request params
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+dp_link_switch_notification(struct wlan_objmgr_vdev *vdev,
+			    struct wlan_mlo_link_switch_req *lswitch_req);
+#endif
+
 /**
  * dp_peer_obj_create_notification(): dp peer create handler
  * @peer: peer which is going to created by objmgr
@@ -397,10 +487,18 @@ static inline void
 dp_add_latency_critical_client(struct wlan_objmgr_vdev *vdev,
 			       enum qca_wlan_802_11_mode phymode)
 {
-	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_link *dp_link = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_intf *dp_intf;
+
+	if (!dp_link) {
+		dp_err("No dp_link for objmgr vdev %pK", vdev);
+		return;
+	}
 
+	dp_intf = dp_link->dp_intf;
 	if (!dp_intf) {
-		dp_err("Unable to get DP interface");
+		dp_err("Invalid dp_intf for dp_link %pK (" QDF_MAC_ADDR_FMT ")",
+		       dp_link, QDF_MAC_ADDR_REF(dp_link->mac_addr.bytes));
 		return;
 	}
 
@@ -410,9 +508,9 @@ dp_add_latency_critical_client(struct wlan_objmgr_vdev *vdev,
 		qdf_atomic_inc(&dp_intf->dp_ctx->num_latency_critical_clients);
 
 		dp_debug("Adding latency critical connection for vdev %d",
-			 dp_intf->intf_id);
+			 dp_link->link_id);
 		cdp_vdev_inform_ll_conn(cds_get_context(QDF_MODULE_ID_SOC),
-					dp_intf->intf_id,
+					dp_link->link_id,
 					CDP_VDEV_LL_CONN_ADD);
 		break;
 	default:
@@ -435,10 +533,18 @@ static inline void
 dp_del_latency_critical_client(struct wlan_objmgr_vdev *vdev,
 			       enum qca_wlan_802_11_mode phymode)
 {
-	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_link *dp_link = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_intf *dp_intf;
+
+	if (!dp_link) {
+		dp_err("No dp_link for objmgr vdev %pK", vdev);
+		return;
+	}
 
+	dp_intf = dp_link->dp_intf;
 	if (!dp_intf) {
-		dp_err("Unable to get DP interface");
+		dp_err("Invalid dp_intf for dp_link %pK (" QDF_MAC_ADDR_FMT ")",
+		       dp_link, QDF_MAC_ADDR_REF(dp_link->mac_addr.bytes));
 		return;
 	}
 
@@ -448,9 +554,9 @@ dp_del_latency_critical_client(struct wlan_objmgr_vdev *vdev,
 		qdf_atomic_dec(&dp_intf->dp_ctx->num_latency_critical_clients);
 
 		dp_info("Removing latency critical connection for vdev %d",
-			dp_intf->intf_id);
+			dp_link->link_id);
 		cdp_vdev_inform_ll_conn(cds_get_context(QDF_MODULE_ID_SOC),
-					dp_intf->intf_id,
+					dp_link->link_id,
 					CDP_VDEV_LL_CONN_DEL);
 		break;
 	default:
@@ -468,6 +574,16 @@ dp_del_latency_critical_client(struct wlan_objmgr_vdev *vdev,
  */
 int is_dp_intf_valid(struct wlan_dp_intf *dp_intf);
 
+/**
+ * is_dp_link_valid() - check if DP link is valid
+ * @dp_link: DP link handle
+ *
+ * API to check whether DP link is valid
+ *
+ * Return: true if dp_link is valid, else false.
+ */
+bool is_dp_link_valid(struct wlan_dp_link *dp_link);
+
 /**
  * dp_send_rps_ind() - send rps indication to daemon
  * @dp_intf: DP interface
@@ -768,7 +884,6 @@ void dp_direct_link_deinit(struct wlan_dp_psoc_context *dp_ctx, bool is_ssr);
 QDF_STATUS dp_config_direct_link(struct wlan_dp_intf *dp_intf,
 				 bool config_direct_link,
 				 bool enable_low_latency);
-
 #else
 static inline
 QDF_STATUS dp_direct_link_init(struct wlan_dp_psoc_context *dp_ctx)

+ 14 - 11
components/dp/core/inc/wlan_dp_objmgr.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -29,6 +29,9 @@
 #include "wlan_objmgr_psoc_obj.h"
 #include "wlan_utility.h"
 
+struct wlan_dp_intf;
+struct wlan_dp_link;
+
 /* Get/Put Ref */
 
 #define dp_comp_peer_get_ref(peer) wlan_objmgr_peer_try_get_ref(peer, WLAN_DP_ID)
@@ -69,10 +72,10 @@ dp_get_peer_priv_obj(struct wlan_objmgr_peer *peer)
  *
  * Return: DP vdev private object
  */
-static inline struct wlan_dp_intf *
+static inline struct wlan_dp_link *
 dp_get_vdev_priv_obj(struct wlan_objmgr_vdev *vdev)
 {
-	struct wlan_dp_intf *obj;
+	struct wlan_dp_link *obj;
 
 	if (!vdev) {
 		dp_err("vdev is null");
@@ -102,26 +105,26 @@ dp_psoc_get_priv(struct wlan_objmgr_psoc *psoc)
 }
 
 /**
- * dp_objmgr_get_vdev_by_user() - Get reference of vdev from dp_intf
+ * dp_objmgr_get_vdev_by_user() - Get reference of vdev from dp_link
  *  with user id
- * @dp_intf: dp dp_intf
+ * @dp_link: DP link handle
  * @dbgid: reference count dbg id
  *
  * Return: pointer to vdev object for success, NULL for failure
  */
 #ifdef WLAN_OBJMGR_REF_ID_TRACE
-#define dp_objmgr_get_vdev_by_user(dp_intf, dbgid) \
-	__dp_objmgr_get_vdev_by_user(dp_intf, dbgid, __func__, __LINE__)
+#define dp_objmgr_get_vdev_by_user(dp_link, dbgid) \
+	__dp_objmgr_get_vdev_by_user(dp_link, dbgid, __func__, __LINE__)
 struct wlan_objmgr_vdev *
-__dp_objmgr_get_vdev_by_user(struct wlan_dp_intf *dp_intf,
+__dp_objmgr_get_vdev_by_user(struct wlan_dp_link *dp_link,
 			     wlan_objmgr_ref_dbgid id,
 			     const char *func,
 			     int line);
 #else
-#define dp_objmgr_get_vdev_by_user(dp_intf, dbgid) \
-	__dp_objmgr_get_vdev_by_user(dp_intf, dbgid, __func__)
+#define dp_objmgr_get_vdev_by_user(dp_link, dbgid) \
+	__dp_objmgr_get_vdev_by_user(dp_link, dbgid, __func__)
 struct wlan_objmgr_vdev *
-__dp_objmgr_get_vdev_by_user(struct wlan_dp_intf *dp_intf,
+__dp_objmgr_get_vdev_by_user(struct wlan_dp_link *dp_link,
 			     wlan_objmgr_ref_dbgid id,
 			     const char *func);
 #endif

+ 46 - 8
components/dp/core/inc/wlan_dp_priv.h

@@ -415,6 +415,7 @@ struct fisa_pkt_hist {
  * @rx_flow_tuple_info: RX tuple information
  * @napi_id: NAPI ID (REO ID) on which the flow is being received
  * @vdev: VDEV handle corresponding to the FLOW
+ * @dp_intf: DP interface handle corresponding to the flow
  * @bytes_aggregated: Number of bytes currently aggregated
  * @flush_count: Number of Flow flushes done
  * @aggr_count: Aggregation count
@@ -432,6 +433,7 @@ struct fisa_pkt_hist {
  * @flow_init_ts: FLOW init timestamp
  * @last_accessed_ts: Timestamp when the flow was last accessed
  * @pkt_hist: FISA aggreagtion packets history
+ * @same_mld_vdev_mismatch: Packets flushed after vdev_mismatch on same MLD
  */
 struct dp_fisa_rx_sw_ft {
 	void *hw_fse;
@@ -456,6 +458,7 @@ struct dp_fisa_rx_sw_ft {
 	struct cdp_rx_flow_tuple_info rx_flow_tuple_info;
 	uint8_t napi_id;
 	struct dp_vdev *vdev;
+	struct wlan_dp_intf *dp_intf;
 	uint64_t bytes_aggregated;
 	uint32_t flush_count;
 	uint32_t aggr_count;
@@ -478,6 +481,7 @@ struct dp_fisa_rx_sw_ft {
 #ifdef WLAN_SUPPORT_RX_FISA_HIST
 	struct fisa_pkt_hist pkt_hist;
 #endif
+	uint64_t same_mld_vdev_mismatch;
 };
 
 #define DP_RX_GET_SW_FT_ENTRY_SIZE sizeof(struct dp_fisa_rx_sw_ft)
@@ -574,8 +578,6 @@ struct dp_rx_fst {
  * @device_mode: Device Mode
  * @intf_id: Interface ID
  * @node: list node for membership in the interface list
- * @vdev: object manager vdev context
- * @vdev_lock: vdev spin lock
  * @dev: netdev reference
  * @txrx_ops: Interface tx-rx ops
  * @dp_stats: Device TX/RX statistics
@@ -605,14 +607,21 @@ struct dp_rx_fst {
  * @sap_tx_block_mask: SAP TX block mask
  * @gro_disallowed: GRO disallowed flag
  * @gro_flushed: GRO flushed flag
+ * @fisa_disallowed: Flag to indicate fisa aggregation not to be done for a
+ *		     particular rx_context
+ * @fisa_force_flushed: Flag to indicate FISA flow has been flushed for a
+ *			particular rx_context
  * @runtime_disable_rx_thread: Runtime Rx thread flag
  * @rx_stack: function pointer Rx packet handover
  * @tx_fn: function pointer to send Tx packet
- * @conn_info: STA connection information
  * @bss_state: AP BSS state
  * @qdf_sta_eap_frm_done_event: EAP frame event management
  * @traffic_end_ind: store traffic end indication info
  * @direct_link_config: direct link configuration parameters
+ * @num_links: Number of links for this DP interface
+ * @def_link: Pointer to default link (usually used for TX operation)
+ * @dp_link_list_lock: Lock to protect dp_link_list operatiosn
+ * @dp_link_list: List of dp_links for this DP interface
  */
 struct wlan_dp_intf {
 	struct wlan_dp_psoc_context *dp_ctx;
@@ -623,12 +632,8 @@ struct wlan_dp_intf {
 
 	enum QDF_OPMODE device_mode;
 
-	uint8_t intf_id;
-
 	qdf_list_node_t node;
 
-	struct wlan_objmgr_vdev *vdev;
-	qdf_spinlock_t vdev_lock;
 	qdf_netdev_t dev;
 	struct ol_txrx_ops txrx_ops;
 	struct dp_stats dp_stats;
@@ -665,8 +670,15 @@ struct wlan_dp_intf {
 	qdf_atomic_t gro_disallowed;
 	uint8_t gro_flushed[DP_MAX_RX_THREADS];
 
+#ifdef WLAN_SUPPORT_RX_FISA
+	/*
+	 * Params used for controlling the fisa aggregation dynamically
+	 */
+	uint8_t fisa_disallowed[MAX_REO_DEST_RINGS];
+	uint8_t fisa_force_flushed[MAX_REO_DEST_RINGS];
+#endif
+
 	bool runtime_disable_rx_thread;
-	struct wlan_dp_conn_info conn_info;
 
 	enum bss_intf_state bss_state;
 	qdf_event_t qdf_sta_eap_frm_done_event;
@@ -674,6 +686,30 @@ struct wlan_dp_intf {
 #ifdef FEATURE_DIRECT_LINK
 	struct direct_link_info direct_link_config;
 #endif
+	uint8_t num_links;
+	struct wlan_dp_link *def_link;
+	qdf_spinlock_t dp_link_list_lock;
+	qdf_list_t dp_link_list;
+};
+
+/**
+ * struct wlan_dp_link - DP link (corresponds to objmgr vdev)
+ * @node: list node for membership in the DP links list
+ * @link_id: ID for this DP link (Same as vdev_id)
+ * @mac_addr: mac address of this link
+ * @dp_intf: Parent DP interface for this DP link
+ * @vdev: object manager vdev context
+ * @vdev_lock: vdev spin lock
+ * @conn_info: STA connection information
+ */
+struct wlan_dp_link {
+	qdf_list_node_t node;
+	uint8_t link_id;
+	struct qdf_mac_addr mac_addr;
+	struct wlan_dp_intf *dp_intf;
+	struct wlan_objmgr_vdev *vdev;
+	qdf_spinlock_t vdev_lock;
+	struct wlan_dp_conn_info conn_info;
 };
 
 /**
@@ -764,6 +800,7 @@ struct dp_direct_link_context {
  * @fst_in_cmem: Flag indicating if FST is in CMEM or not
  * @fisa_enable: Flag to indicate if FISA is enabled or not
  * @fisa_lru_del_enable: Flag to indicate if LRU flow delete is enabled
+ * @fisa_dynamic_aggr_size_support: Indicate dynamic aggr size programming support
  * @skip_fisa_param: FISA skip params structure
  * @skip_fisa_param.skip_fisa: Flag to skip FISA aggr inside @skip_fisa_param
  * @skip_fisa_param.fisa_force_flush: Force flush inside @skip_fisa_param
@@ -852,6 +889,7 @@ struct wlan_dp_psoc_context {
 	bool fst_in_cmem;
 	uint8_t fisa_enable;
 	uint8_t fisa_lru_del_enable;
+	bool fisa_dynamic_aggr_size_support;
 	/*
 	 * Params used for controlling the fisa aggregation dynamically
 	 */

+ 26 - 26
components/dp/core/inc/wlan_dp_txrx.h

@@ -90,18 +90,18 @@ void dp_softap_check_wait_for_tx_eap_pkt(struct wlan_dp_intf *dp_intf,
 #ifdef SAP_DHCP_FW_IND
 /**
  * dp_post_dhcp_ind() - Send DHCP START/STOP indication to FW
- * @dp_intf: pointer to dp interface
+ * @dp_link: DP link handle
  * @mac_addr: mac address
  * @dhcp_start: true if DHCP start, otherwise DHCP stop
  *
  * Return: error number
  */
-int dp_post_dhcp_ind(struct wlan_dp_intf *dp_intf,
+int dp_post_dhcp_ind(struct wlan_dp_link *dp_link,
 		     uint8_t *mac_addr, bool dhcp_start);
 
 /**
  * dp_softap_inspect_dhcp_packet() - Inspect DHCP packet
- * @dp_intf: pointer to dp interface
+ * @dp_link: DP link handle
  * @nbuf: pointer to OS packet (sk_buff)
  * @dir: direction
  *
@@ -126,19 +126,19 @@ int dp_post_dhcp_ind(struct wlan_dp_intf *dp_intf,
  *
  * Return: error number
  */
-int dp_softap_inspect_dhcp_packet(struct wlan_dp_intf *dp_intf,
+int dp_softap_inspect_dhcp_packet(struct wlan_dp_link *dp_link,
 				  qdf_nbuf_t nbuf,
 				  enum qdf_proto_dir dir);
 #else
 static inline
-int dp_post_dhcp_ind(struct wlan_dp_intf *dp_intf,
+int dp_post_dhcp_ind(struct wlan_dp_link *dp_link,
 		     uint8_t *mac_addr, bool dhcp_start)
 {
 	return 0;
 }
 
 static inline
-int dp_softap_inspect_dhcp_packet(struct wlan_dp_intf *dp_intf,
+int dp_softap_inspect_dhcp_packet(struct wlan_dp_link *dp_link,
 				  qdf_nbuf_t nbuf,
 				  enum qdf_proto_dir dir)
 {
@@ -148,8 +148,8 @@ int dp_softap_inspect_dhcp_packet(struct wlan_dp_intf *dp_intf,
 
 /**
  * dp_rx_flush_packet_cbk() - flush rx packet handler
- * @dp_intf_ctx: pointer to DP interface context
- * @vdev_id: vdev_id of the packets to be flushed
+ * @dp_link_context: pointer to DP link context
+ * @link_id: vdev_id of the packets to be flushed
  *
  * Flush rx packet callback registered with data path. DP will call this to
  * notify when packets for a particular vdev is to be flushed out.
@@ -157,16 +157,16 @@ int dp_softap_inspect_dhcp_packet(struct wlan_dp_intf *dp_intf,
  * Return: QDF_STATUS_E_FAILURE if any errors encountered,
  *	   QDF_STATUS_SUCCESS otherwise
  */
-QDF_STATUS dp_rx_flush_packet_cbk(void *dp_intf_ctx, uint8_t vdev_id);
+QDF_STATUS dp_rx_flush_packet_cbk(void *dp_link_context, uint8_t link_id);
 
 /**
  * dp_softap_start_xmit() - Transmit a frame for SAP interface
  * @nbuf: pointer to Network buffer
- * @dp_intf: DP interface
+ * @dp_link: DP link handle
  *
  * Return: QDF_STATUS_SUCCESS on successful transmission
  */
-QDF_STATUS dp_softap_start_xmit(qdf_nbuf_t nbuf, struct wlan_dp_intf *dp_intf);
+QDF_STATUS dp_softap_start_xmit(qdf_nbuf_t nbuf, struct wlan_dp_link *dp_link);
 
 /**
  * dp_softap_tx_timeout() - TX timeout handler
@@ -198,12 +198,12 @@ dp_softap_rx_packet_cbk(void *intf_ctx, qdf_nbuf_t rx_buf);
 /**
  * dp_start_xmit() - Transmit a frame for STA interface
  * @nbuf: pointer to Network buffer
- * @dp_intf: DP interface
+ * @dp_link: DP link handle
  *
  * Return: QDF_STATUS_SUCCESS on successful transmission
  */
 QDF_STATUS
-dp_start_xmit(struct wlan_dp_intf *dp_intf, qdf_nbuf_t nbuf);
+dp_start_xmit(struct wlan_dp_link *dp_link, qdf_nbuf_t nbuf);
 
 /**
  * dp_tx_timeout() - DP Tx timeout API
@@ -217,7 +217,7 @@ void dp_tx_timeout(struct wlan_dp_intf *dp_intf);
 
 /**
  * dp_rx_packet_cbk() - Receive packet handler
- * @dp_intf_context: pointer to DP interface context
+ * @dp_link_context: pointer to DP link context
  * @rx_buf: pointer to rx qdf_nbuf
  *
  * Receive callback registered with data path.  DP will call this to notify
@@ -227,7 +227,7 @@ void dp_tx_timeout(struct wlan_dp_intf *dp_intf);
  * Return: QDF_STATUS_E_FAILURE if any errors encountered,
  *	   QDF_STATUS_SUCCESS otherwise
  */
-QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context, qdf_nbuf_t rx_buf);
+QDF_STATUS dp_rx_packet_cbk(void *dp_link_context, qdf_nbuf_t rx_buf);
 
 #if defined(WLAN_SUPPORT_RX_FISA)
 /**
@@ -284,7 +284,7 @@ QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
 
 /**
  * dp_rx_thread_gro_flush_ind_cbk() - receive handler to flush GRO packets
- * @intf_ctx: pointer to DP interface context
+ * @link_ctx: pointer to DP interface context
  * @rx_ctx_id: RX CTX Id for which flush should happen
  *
  * Receive callback registered with DP layer which flushes GRO packets
@@ -293,11 +293,11 @@ QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
  * Return: QDF_STATUS_E_FAILURE if any errors encountered,
  *	   QDF_STATUS_SUCCESS otherwise
  */
-QDF_STATUS dp_rx_thread_gro_flush_ind_cbk(void *intf_ctx, int rx_ctx_id);
+QDF_STATUS dp_rx_thread_gro_flush_ind_cbk(void *link_ctx, int rx_ctx_id);
 
 /**
  * dp_rx_pkt_thread_enqueue_cbk() - receive pkt handler to enqueue into thread
- * @intf_ctx: pointer to DP interface context
+ * @link_ctx: pointer to DP link context
  * @nbuf_list: pointer to qdf_nbuf list
  *
  * Receive callback registered with DP layer which enqueues packets into dp rx
@@ -306,7 +306,7 @@ QDF_STATUS dp_rx_thread_gro_flush_ind_cbk(void *intf_ctx, int rx_ctx_id);
  * Return: QDF_STATUS_E_FAILURE if any errors encountered,
  *	   QDF_STATUS_SUCCESS otherwise
  */
-QDF_STATUS dp_rx_pkt_thread_enqueue_cbk(void *intf_ctx,
+QDF_STATUS dp_rx_pkt_thread_enqueue_cbk(void *link_ctx,
 					qdf_nbuf_t nbuf_list);
 
 /**
@@ -386,7 +386,7 @@ qdf_nbuf_t dp_nbuf_orphan(struct wlan_dp_intf *dp_intf,
 
 	tx_flow_low_watermark =
 	   dp_ops->dp_get_tx_flow_low_watermark(dp_ops->callback_ctx,
-						dp_intf->intf_id);
+						dp_intf->dev);
 	if (tx_flow_low_watermark > 0) {
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 19, 0))
 		/*
@@ -426,12 +426,12 @@ qdf_nbuf_t dp_nbuf_orphan(struct wlan_dp_intf *dp_intf,
 
 /**
  * dp_get_tx_resource() - check tx resources and take action
- * @dp_intf: DP interface
+ * @dp_link: DP link handle
  * @mac_addr: mac address
  *
  * Return: none
  */
-void dp_get_tx_resource(struct wlan_dp_intf *dp_intf,
+void dp_get_tx_resource(struct wlan_dp_link *dp_link,
 			struct qdf_mac_addr *mac_addr);
 
 #else
@@ -481,13 +481,13 @@ qdf_nbuf_t dp_nbuf_orphan(struct wlan_dp_intf *dp_intf,
 
 /**
  * dp_get_tx_resource() - check tx resources and take action
- * @dp_intf: DP interface
+ * @dp_link: DP link handle
  * @mac_addr: mac address
  *
  * Return: none
  */
 static inline
-void dp_get_tx_resource(struct wlan_dp_intf *dp_intf,
+void dp_get_tx_resource(struct wlan_dp_link *dp_link,
 			struct qdf_mac_addr *mac_addr)
 {
 }
@@ -495,7 +495,7 @@ void dp_get_tx_resource(struct wlan_dp_intf *dp_intf,
 
 /**
  * dp_start_xmit() - Transmit a frame
- * @dp_intf: pointer to DP interface
+ * @dp_link: DP link handle
  * @nbuf: n/w buffer
  *
  * Function called to Transmit a n/w buffer in STA mode.
@@ -503,7 +503,7 @@ void dp_get_tx_resource(struct wlan_dp_intf *dp_intf,
  * Return: Status of the transmission
  */
 QDF_STATUS
-dp_start_xmit(struct wlan_dp_intf *dp_intf, qdf_nbuf_t nbuf);
+dp_start_xmit(struct wlan_dp_link *dp_link, qdf_nbuf_t nbuf);
 
 #ifdef FEATURE_MONITOR_MODE_SUPPORT
 /**

+ 89 - 49
components/dp/core/src/wlan_dp_bus_bandwidth.c

@@ -196,21 +196,18 @@ bbm_get_bus_bw_level_vote(struct wlan_dp_intf *dp_intf,
 	case QDF_STA_MODE:
 	case QDF_P2P_CLIENT_MODE:
 		if (!cb_obj->wlan_dp_sta_get_dot11mode(ctx,
-						       dp_intf->intf_id,
+						       dp_intf->dev,
 						       &dot11_mode))
 			break;
 
-		if (dot11_mode >= QCA_WLAN_802_11_MODE_INVALID) {
-			dp_err("invalid STA/P2P-CLI dot11 modei %d",
-			       dot11_mode);
+		if (dot11_mode >= QCA_WLAN_802_11_MODE_INVALID)
 			break;
-		}
 
 		return (*lkp_table)[dot11_mode][tput_level];
 	case QDF_SAP_MODE:
 	case QDF_P2P_GO_MODE:
 		if (!cb_obj->wlan_dp_get_ap_client_count(ctx,
-							 dp_intf->intf_id,
+							 dp_intf->dev,
 							 client_count))
 			break;
 
@@ -224,7 +221,7 @@ bbm_get_bus_bw_level_vote(struct wlan_dp_intf *dp_intf,
 		return vote_lvl;
 	case QDF_NDI_MODE:
 		if (!cb_obj->wlan_dp_sta_ndi_connected(ctx,
-						       dp_intf->intf_id))
+						       dp_intf->dev))
 			break;
 
 		/*
@@ -242,12 +239,6 @@ bbm_get_bus_bw_level_vote(struct wlan_dp_intf *dp_intf,
 	return vote_lvl;
 }
 
-static inline bool bbm_validate_intf_id(uint8_t intf_id)
-{
-	return !!(intf_id == WLAN_UMAC_VDEV_ID_MAX ||
-				intf_id >= WLAN_MAX_VDEVS);
-}
-
 /**
  * bbm_apply_tput_policy() - Apply tput BBM policy by considering
  *  throughput level and connection modes across adapters
@@ -285,10 +276,9 @@ bbm_apply_tput_policy(struct wlan_dp_psoc_context *dp_ctx,
 	}
 
 	dp_for_each_intf_held_safe(dp_ctx, dp_intf, dp_intf_next) {
-		if (!dp_intf)
-			continue;
-		if (bbm_validate_intf_id(dp_intf->intf_id))
+		if (dp_intf->num_links == 0)
 			continue;
+
 		tmp_vote = bbm_get_bus_bw_level_vote(dp_intf, tput_level);
 		if (tmp_vote > next_vote)
 			next_vote = tmp_vote;
@@ -1091,10 +1081,11 @@ static void wlan_dp_display_txrx_stats(struct wlan_dp_psoc_context *dp_ctx)
 		total_tx_orphaned = 0;
 		stats = &dp_intf->dp_stats.tx_rx_stats;
 
-		if (dp_intf->intf_id == WLAN_INVALID_VDEV_ID)
+		if (!dp_intf->num_links)
 			continue;
 
-		dp_info("dp_intf: %u", dp_intf->intf_id);
+		dp_info("dp_intf: " QDF_MAC_ADDR_FMT,
+			QDF_MAC_ADDR_REF(dp_intf->mac_addr.bytes));
 		for (i = 0; i < NUM_CPUS; i++) {
 			total_rx_pkt += stats->per_cpu[i].rx_packets;
 			total_rx_dropped += stats->per_cpu[i].rx_dropped;
@@ -1119,7 +1110,8 @@ static void wlan_dp_display_txrx_stats(struct wlan_dp_psoc_context *dp_ctx)
 			total_tx_pkt, total_tx_dropped,
 			total_tx_orphaned);
 
-		dp_ctx->dp_ops.wlan_dp_display_tx_multiq_stats(ctx, dp_intf->intf_id);
+		dp_ctx->dp_ops.wlan_dp_display_tx_multiq_stats(ctx,
+							       dp_intf->dev);
 
 		for (i = 0; i < NUM_CPUS; i++) {
 			if (stats->per_cpu[i].rx_packets == 0)
@@ -1778,6 +1770,7 @@ dp_link_monitoring(struct wlan_dp_psoc_context *dp_ctx,
 	uint32_t link_speed;
 	struct wlan_objmgr_psoc *psoc;
 	struct link_monitoring link_mon;
+	struct wlan_dp_link *def_link = dp_intf->def_link;
 
 	/*
 	 *  If throughput is high, link speed should be good,  don't check it
@@ -1804,7 +1797,7 @@ dp_link_monitoring(struct wlan_dp_psoc_context *dp_ctx,
 		if (no_rx_times >= NO_RX_PKT_LINK_SPEED_AGEOUT_COUNT) {
 			no_rx_times = 0;
 			dp_ctx->dp_ops.link_monitoring_cb(psoc,
-							  dp_intf->intf_id,
+							  def_link->link_id,
 							  false);
 			dp_intf->link_monitoring.is_rx_linkspeed_good = false;
 
@@ -1815,13 +1808,19 @@ dp_link_monitoring(struct wlan_dp_psoc_context *dp_ctx,
 	peer_stats = qdf_mem_malloc(sizeof(*peer_stats));
 	if (!peer_stats)
 		return;
-	bss_peer = wlan_vdev_get_bsspeer(dp_intf->vdev);
+
+	/* TODO - Temp WAR, check what to do here */
+	/* Peer stats for any link peer is going to return the
+	 * stats from MLD peer, so its okay to query deflink
+	 */
+	bss_peer = wlan_vdev_get_bsspeer(def_link->vdev);
 	if (!bss_peer) {
 		dp_debug("Invalid bss peer");
 		qdf_mem_free(peer_stats);
 		return;
 	}
-	status = cdp_host_get_peer_stats(soc, dp_intf->intf_id,
+
+	status = cdp_host_get_peer_stats(soc, def_link->link_id,
 					 bss_peer->macaddr,
 					 peer_stats);
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -1840,17 +1839,17 @@ dp_link_monitoring(struct wlan_dp_psoc_context *dp_ctx,
 	 * driver will send rx link speed poor state to firmware.
 	 */
 	if (!link_mon.rx_linkspeed_threshold) {
-		dp_ctx->dp_ops.link_monitoring_cb(psoc, dp_intf->intf_id,
+		dp_ctx->dp_ops.link_monitoring_cb(psoc, def_link->link_id,
 						  false);
 		dp_intf->link_monitoring.is_rx_linkspeed_good = false;
 	} else if (link_speed > link_mon.rx_linkspeed_threshold &&
 	     !link_mon.is_rx_linkspeed_good) {
-		dp_ctx->dp_ops.link_monitoring_cb(psoc, dp_intf->intf_id,
+		dp_ctx->dp_ops.link_monitoring_cb(psoc, def_link->link_id,
 						  true);
 		dp_intf->link_monitoring.is_rx_linkspeed_good = true;
 	} else if (link_speed < link_mon.rx_linkspeed_threshold &&
 		   link_mon.is_rx_linkspeed_good) {
-		dp_ctx->dp_ops.link_monitoring_cb(psoc, dp_intf->intf_id,
+		dp_ctx->dp_ops.link_monitoring_cb(psoc, def_link->link_id,
 						  false);
 		dp_intf->link_monitoring.is_rx_linkspeed_good = false;
 	}
@@ -1871,8 +1870,11 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx)
 	struct wlan_objmgr_vdev *vdev;
 	struct wlan_dp_intf *dp_intf = NULL, *con_sap_dp_intf = NULL;
 	struct wlan_dp_intf *dp_intf_next = NULL;
+	struct wlan_dp_link *dp_link = NULL;
+	struct wlan_dp_link *dp_link_next;
 	uint64_t tx_packets = 0, rx_packets = 0, tx_bytes = 0;
 	uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
+	uint64_t fwd_tx_packets_temp = 0, fwd_rx_packets_temp = 0;
 	uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
 	uint64_t total_tx = 0, total_rx = 0;
 	A_STATUS ret;
@@ -1898,7 +1900,8 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx)
 	dp_ctx->bw_vote_time = curr_time_us;
 
 	dp_for_each_intf_held_safe(dp_ctx, dp_intf, dp_intf_next) {
-		vdev = dp_objmgr_get_vdev_by_user(dp_intf, WLAN_DP_ID);
+		vdev = dp_objmgr_get_vdev_by_user(dp_intf->def_link,
+						  WLAN_DP_ID);
 		if (!vdev)
 			continue;
 
@@ -1912,7 +1915,7 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx)
 		if ((dp_intf->device_mode == QDF_SAP_MODE ||
 		     dp_intf->device_mode == QDF_P2P_GO_MODE) &&
 		     !dp_ctx->dp_ops.dp_is_ap_active(ctx,
-						     dp_intf->intf_id)) {
+						     dp_intf->dev)) {
 			dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
 			continue;
 		}
@@ -1933,27 +1936,42 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx)
 		if (dp_intf->device_mode == QDF_STA_MODE &&
 		    wlan_cm_is_vdev_active(vdev)) {
 			dp_ctx->dp_ops.dp_send_mscs_action_frame(ctx,
-							dp_intf->intf_id);
+							dp_intf->dev);
 			if (dp_intf->link_monitoring.enabled)
 				dp_link_monitoring(dp_ctx, dp_intf);
 		}
+
+		ret = A_ERROR;
+		fwd_tx_packets = 0;
+		fwd_rx_packets = 0;
 		if (dp_intf->device_mode == QDF_SAP_MODE ||
 		    dp_intf->device_mode == QDF_P2P_GO_MODE ||
 		    dp_intf->device_mode == QDF_NDI_MODE) {
-			ret = cdp_get_intra_bss_fwd_pkts_count(
-				cds_get_context(QDF_MODULE_ID_SOC),
-				dp_intf->intf_id,
-				&fwd_tx_packets, &fwd_rx_packets);
-			if (ret == A_OK) {
-				fwd_tx_packets_diff += DP_BW_GET_DIFF(
-					fwd_tx_packets,
-					dp_intf->prev_fwd_tx_packets);
-				fwd_rx_packets_diff += DP_BW_GET_DIFF(
-					fwd_tx_packets,
-					dp_intf->prev_fwd_rx_packets);
+			dp_for_each_link_held_safe(dp_intf, dp_link,
+						   dp_link_next) {
+				ret = cdp_get_intra_bss_fwd_pkts_count(
+					cds_get_context(QDF_MODULE_ID_SOC),
+					dp_link->link_id,
+					&fwd_tx_packets_temp,
+					&fwd_rx_packets_temp);
+				if (ret == A_OK) {
+					fwd_tx_packets += fwd_tx_packets_temp;
+					fwd_rx_packets += fwd_rx_packets_temp;
+				} else {
+					break;
+				}
 			}
 		}
 
+		if (ret == A_OK) {
+			fwd_tx_packets_diff += DP_BW_GET_DIFF(
+				fwd_tx_packets,
+				dp_intf->prev_fwd_tx_packets);
+			fwd_rx_packets_diff += DP_BW_GET_DIFF(
+				fwd_rx_packets,
+				dp_intf->prev_fwd_rx_packets);
+		}
+
 		if (dp_intf->device_mode == QDF_SAP_MODE) {
 			con_sap_dp_intf = dp_intf;
 			sap_tx_bytes =
@@ -1964,11 +1982,13 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx)
 			sta_tx_bytes =
 				qdf_net_stats_get_tx_bytes(&dp_intf->stats);
 
-		dp_set_driver_del_ack_enable(dp_intf->intf_id, dp_ctx,
-					     rx_packets);
+		dp_for_each_link_held_safe(dp_intf, dp_link, dp_link_next) {
+			dp_set_driver_del_ack_enable(dp_link->link_id, dp_ctx,
+						     rx_packets);
 
-		dp_set_vdev_bundle_require_flag(dp_intf->intf_id, dp_ctx,
-						tx_bytes);
+			dp_set_vdev_bundle_require_flag(dp_link->link_id,
+							dp_ctx, tx_bytes);
+		}
 
 		total_rx += qdf_net_stats_get_rx_pkts(&dp_intf->stats);
 		total_tx += qdf_net_stats_get_tx_pkts(&dp_intf->stats);
@@ -2213,12 +2233,19 @@ void dp_bus_bw_compute_timer_try_stop(struct wlan_objmgr_psoc *psoc)
 void dp_bus_bw_compute_prev_txrx_stats(struct wlan_objmgr_vdev *vdev)
 {
 	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
-
-	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_link *dp_link = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_intf *dp_intf;
 	struct wlan_dp_psoc_context *dp_ctx = dp_psoc_get_priv(psoc);
 
+	if (!dp_link) {
+		dp_err("No dp_link for objmgr vdev %pK", vdev);
+		return;
+	}
+
+	dp_intf = dp_link->dp_intf;
 	if (!dp_intf) {
-		dp_err("Unable to get DP interface");
+		dp_err("Invalid dp_intf for dp_link %pK (" QDF_MAC_ADDR_FMT ")",
+		       dp_link, QDF_MAC_ADDR_REF(dp_link->mac_addr.bytes));
 		return;
 	}
 
@@ -2230,8 +2257,12 @@ void dp_bus_bw_compute_prev_txrx_stats(struct wlan_objmgr_vdev *vdev)
 	dp_intf->prev_rx_packets = qdf_net_stats_get_rx_pkts(&dp_intf->stats);
 	dp_intf->prev_tx_bytes = qdf_net_stats_get_tx_bytes(&dp_intf->stats);
 
+	/*
+	 * TODO - Should the prev_fwd_tx_packets and
+	 * such stats be per link ??
+	 */
 	cdp_get_intra_bss_fwd_pkts_count(cds_get_context(QDF_MODULE_ID_SOC),
-					 dp_intf->intf_id,
+					 dp_link->link_id,
 					 &dp_intf->prev_fwd_tx_packets,
 					 &dp_intf->prev_fwd_rx_packets);
 	qdf_spin_unlock_bh(&dp_ctx->bus_bw_lock);
@@ -2240,13 +2271,22 @@ void dp_bus_bw_compute_prev_txrx_stats(struct wlan_objmgr_vdev *vdev)
 void dp_bus_bw_compute_reset_prev_txrx_stats(struct wlan_objmgr_vdev *vdev)
 {
 	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
-	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_link *dp_link = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_intf *dp_intf;
 	struct wlan_dp_psoc_context *dp_ctx = dp_psoc_get_priv(psoc);
 
+	if (!dp_link) {
+		dp_err("No dp_link for objmgr vdev %pK", vdev);
+		return;
+	}
+
+	dp_intf = dp_link->dp_intf;
 	if (!dp_intf) {
-		dp_err("Unable to get DP interface");
+		dp_err("Invalid dp_intf for dp_link %pK (" QDF_MAC_ADDR_FMT ")",
+		       dp_link, QDF_MAC_ADDR_REF(dp_link->mac_addr.bytes));
 		return;
 	}
+
 	if (QDF_GLOBAL_FTM_MODE == cds_get_conparam())
 		return;
 

+ 122 - 39
components/dp/core/src/wlan_dp_fisa_rx.c

@@ -431,6 +431,16 @@ dp_rx_fisa_setup_cmem_fse(struct dp_rx_fst *fisa_hdl, uint32_t hashed_flow_idx,
 					  &flow);
 }
 
+static inline
+struct wlan_dp_intf *dp_fisa_rx_get_dp_intf_for_vdev(struct dp_vdev *vdev)
+{
+	struct wlan_dp_link *dp_link =
+				(struct wlan_dp_link *)vdev->osif_vdev;
+
+	/* dp_link cannot be invalid if vdev is present */
+	return dp_link->dp_intf;
+}
+
 /**
  * dp_rx_fisa_update_sw_ft_entry() - Helper function to update few SW FT entry
  * @sw_ft_entry: Pointer to softerware flow table entry
@@ -450,6 +460,7 @@ static void dp_rx_fisa_update_sw_ft_entry(struct dp_fisa_rx_sw_ft *sw_ft_entry,
 	sw_ft_entry->flow_hash = flow_hash;
 	sw_ft_entry->flow_id = flow_id;
 	sw_ft_entry->vdev = vdev;
+	sw_ft_entry->dp_intf = dp_fisa_rx_get_dp_intf_for_vdev(vdev);
 	sw_ft_entry->dp_ctx = dp_ctx;
 }
 
@@ -578,6 +589,8 @@ dp_rx_fisa_add_ft_entry(struct dp_vdev *vdev,
 		if (is_same_flow(&sw_ft_entry->rx_flow_tuple_info,
 				 &rx_flow_tuple_info)) {
 			sw_ft_entry->vdev = vdev;
+			sw_ft_entry->dp_intf =
+					dp_fisa_rx_get_dp_intf_for_vdev(vdev);
 			dp_fisa_debug("It is same flow fse entry idx %d",
 				      hashed_flow_idx);
 			/* Incoming flow tuple matches with existing
@@ -788,7 +801,6 @@ static void dp_fisa_rx_fst_update(struct dp_rx_fst *fisa_hdl,
 	struct cdp_rx_flow_tuple_info *rx_flow_tuple_info;
 	uint32_t skid_count = 0, max_skid_length;
 	struct dp_fisa_rx_sw_ft *sw_ft_entry;
-	/* TODO - Make this better */
 	struct wlan_dp_psoc_context *dp_ctx = dp_get_context();
 	struct wlan_dp_psoc_cfg *dp_cfg = &dp_ctx->dp_cfg;
 	bool is_fst_updated = false;
@@ -1087,6 +1099,7 @@ dp_fisa_rx_get_sw_ft_entry(struct dp_rx_fst *fisa_hdl, qdf_nbuf_t nbuf,
 
 	if (!fisa_hdl->flow_deletion_supported) {
 		sw_ft_entry->vdev = vdev;
+		sw_ft_entry->dp_intf = dp_fisa_rx_get_dp_intf_for_vdev(vdev);
 		return sw_ft_entry;
 	}
 
@@ -1100,6 +1113,7 @@ dp_fisa_rx_get_sw_ft_entry(struct dp_rx_fst *fisa_hdl, qdf_nbuf_t nbuf,
 		return NULL;
 
 	sw_ft_entry->vdev = vdev;
+	sw_ft_entry->dp_intf = dp_fisa_rx_get_dp_intf_for_vdev(vdev);
 	return sw_ft_entry;
 }
 
@@ -1426,6 +1440,84 @@ static qdf_nbuf_t dp_fisa_rx_linear_skb(struct dp_vdev *vdev,
 	return NULL;
 }
 
+#ifdef WLAN_FEATURE_11BE
+static inline struct dp_vdev *
+dp_fisa_rx_get_flow_flush_vdev_ref(ol_txrx_soc_handle cdp_soc,
+				   struct dp_fisa_rx_sw_ft *fisa_flow)
+{
+	struct dp_vdev *fisa_flow_head_skb_vdev;
+	uint8_t vdev_id;
+
+	vdev_id = QDF_NBUF_CB_RX_VDEV_ID(fisa_flow->head_skb);
+
+get_new_vdev_ref:
+	fisa_flow_head_skb_vdev = dp_vdev_get_ref_by_id(
+						cdp_soc_t_to_dp_soc(cdp_soc),
+						vdev_id, DP_MOD_ID_RX);
+	if (qdf_unlikely(!fisa_flow_head_skb_vdev)) {
+		qdf_nbuf_free(fisa_flow->head_skb);
+		goto out;
+	}
+
+	if (qdf_unlikely(fisa_flow_head_skb_vdev != fisa_flow->vdev)) {
+		/*
+		 * vdev_id may mismatch in case of MLO link switch.
+		 * Check if the vdevs belong to same MLD,
+		 * if yes, then submit the flow else drop the packets.
+		 */
+		if (qdf_unlikely(qdf_mem_cmp(
+				fisa_flow->vdev->mld_mac_addr.raw,
+				fisa_flow_head_skb_vdev->mld_mac_addr.raw,
+				QDF_MAC_ADDR_SIZE) != 0)) {
+			qdf_nbuf_free(fisa_flow->head_skb);
+			goto out;
+		} else {
+			fisa_flow->same_mld_vdev_mismatch++;
+			/* Continue with aggregation */
+
+			/* Release ref to old vdev */
+			dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
+					     fisa_flow_head_skb_vdev,
+					     DP_MOD_ID_RX);
+			/*
+			 * Update vdev_id and let it loop to find this
+			 * vdev by ref.
+			 */
+			vdev_id = fisa_flow->vdev->vdev_id;
+			goto get_new_vdev_ref;
+		}
+	}
+
+out:
+	return fisa_flow_head_skb_vdev;
+}
+#else
+static inline struct dp_vdev *
+dp_fisa_rx_get_flow_flush_vdev_ref(ol_txrx_soc_handle cdp_soc,
+				   struct dp_fisa_rx_sw_ft *fisa_flow)
+{
+	struct dp_vdev *fisa_flow_head_skb_vdev;
+
+	fisa_flow_head_skb_vdev = dp_vdev_get_ref_by_id(
+				cdp_soc_t_to_dp_soc(cdp_soc),
+				QDF_NBUF_CB_RX_VDEV_ID(fisa_flow->head_skb),
+				DP_MOD_ID_RX);
+	if (qdf_unlikely(!fisa_flow_head_skb_vdev ||
+			 (fisa_flow_head_skb_vdev != fisa_flow->vdev))) {
+		qdf_nbuf_free(fisa_flow->head_skb);
+		goto out;
+	}
+
+	return fisa_flow_head_skb_vdev;
+
+out:
+	dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
+			     fisa_flow_head_skb_vdev,
+			     DP_MOD_ID_RX);
+	return NULL;
+}
+#endif
+
 /**
  * dp_rx_fisa_flush_udp_flow() - Flush all aggregated nbuf of the udp flow
  * @vdev: handle to dp_vdev
@@ -1520,15 +1612,10 @@ dp_rx_fisa_flush_udp_flow(struct dp_vdev *vdev,
 
 	hex_dump_skb_data(fisa_flow->head_skb, false);
 
-	fisa_flow_vdev = dp_vdev_get_ref_by_id(
-				cdp_soc_t_to_dp_soc(cdp_soc),
-				QDF_NBUF_CB_RX_VDEV_ID(fisa_flow->head_skb),
-				DP_MOD_ID_RX);
-	if (qdf_unlikely(!fisa_flow_vdev ||
-			 (fisa_flow_vdev != fisa_flow->vdev))) {
-		qdf_nbuf_free(fisa_flow->head_skb);
-		goto out;
-	}
+	fisa_flow_vdev = dp_fisa_rx_get_flow_flush_vdev_ref(cdp_soc, fisa_flow);
+	if (!fisa_flow_vdev)
+		goto vdev_ref_get_fail;
+
 	dp_fisa_debug("fisa_flow->curr_aggr %d", fisa_flow->cur_aggr);
 	linear_skb = dp_fisa_rx_linear_skb(vdev, fisa_flow->head_skb, 24000);
 	if (linear_skb) {
@@ -1560,6 +1647,8 @@ out:
 		dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
 				     fisa_flow_vdev,
 				     DP_MOD_ID_RX);
+
+vdev_ref_get_fail:
 	fisa_flow->head_skb = NULL;
 	fisa_flow->last_skb = NULL;
 
@@ -1889,17 +1978,15 @@ static bool dp_is_nbuf_bypass_fisa(qdf_nbuf_t nbuf)
 }
 
 /**
- * dp_rx_fisa_flush_by_vdev_ctx_id() - Flush fisa aggregates per vdev and rx
- *  context id
- * @soc: core txrx main context
- * @vdev: Handle DP vdev
+ * dp_rx_fisa_flush_by_intf_ctx_id() - Flush fisa aggregates per dp_interface
+ *				       and rx context id
+ * @dp_intf: DP interface handle
  * @rx_ctx_id: Rx context id
  *
  * Return: Success on flushing the flows for the vdev and rx ctx id
  */
 static
-QDF_STATUS dp_rx_fisa_flush_by_vdev_ctx_id(struct dp_soc *soc,
-					   struct dp_vdev *vdev,
+QDF_STATUS dp_rx_fisa_flush_by_intf_ctx_id(struct wlan_dp_intf *dp_intf,
 					   uint8_t rx_ctx_id)
 {
 	struct wlan_dp_psoc_context *dp_ctx = dp_get_context();
@@ -1912,10 +1999,10 @@ QDF_STATUS dp_rx_fisa_flush_by_vdev_ctx_id(struct dp_soc *soc,
 	dp_rx_fisa_acquire_ft_lock(fisa_hdl, rx_ctx_id);
 	for (i = 0; i < ft_size; i++) {
 		if (sw_ft_entry[i].is_populated &&
-		    vdev == sw_ft_entry[i].vdev &&
+		    dp_intf == sw_ft_entry[i].dp_intf &&
 		    sw_ft_entry[i].napi_id == rx_ctx_id) {
-			dp_fisa_debug("flushing %d %pk vdev %pK napi id:%d", i,
-				      &sw_ft_entry[i], vdev, rx_ctx_id);
+			dp_fisa_debug("flushing %d %pk dp_intf %pK napi id:%d",
+				      i, &sw_ft_entry[i], dp_intf, rx_ctx_id);
 			dp_rx_fisa_flush_flow_wrap(&sw_ft_entry[i]);
 		}
 	}
@@ -1936,15 +2023,18 @@ static bool dp_fisa_disallowed_for_vdev(struct dp_soc *soc,
 					struct dp_vdev *vdev,
 					uint8_t rx_ctx_id)
 {
-	if (!vdev->fisa_disallowed[rx_ctx_id]) {
-		if (vdev->fisa_force_flushed[rx_ctx_id])
-			vdev->fisa_force_flushed[rx_ctx_id] = 0;
+	struct wlan_dp_intf *dp_intf;
+
+	dp_intf = dp_fisa_rx_get_dp_intf_for_vdev(vdev);
+	if (!dp_intf->fisa_disallowed[rx_ctx_id]) {
+		if (dp_intf->fisa_force_flushed[rx_ctx_id])
+			dp_intf->fisa_force_flushed[rx_ctx_id] = 0;
 		return false;
 	}
 
-	if (!vdev->fisa_force_flushed[rx_ctx_id]) {
-		dp_rx_fisa_flush_by_vdev_ctx_id(soc, vdev, rx_ctx_id);
-		vdev->fisa_force_flushed[rx_ctx_id] = 1;
+	if (!dp_intf->fisa_force_flushed[rx_ctx_id]) {
+		dp_rx_fisa_flush_by_intf_ctx_id(dp_intf, rx_ctx_id);
+		dp_intf->fisa_force_flushed[rx_ctx_id] = 1;
 	}
 
 	return true;
@@ -2133,20 +2223,6 @@ QDF_STATUS dp_rx_fisa_flush_by_vdev_id(struct dp_soc *soc, uint8_t vdev_id)
 	return QDF_STATUS_SUCCESS;
 }
 
-void dp_set_fisa_disallowed_for_vdev(struct cdp_soc_t *cdp_soc, uint8_t vdev_id,
-				     uint8_t rx_ctx_id, uint8_t val)
-{
-	struct dp_soc *soc = (struct dp_soc *)cdp_soc;
-	struct dp_vdev *vdev;
-
-	vdev = dp_vdev_get_ref_by_id(soc, vdev_id, DP_MOD_ID_RX);
-	if (qdf_unlikely(!vdev))
-		return;
-
-	vdev->fisa_disallowed[rx_ctx_id] = val;
-	dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_RX);
-}
-
 void dp_suspend_fse_cache_flush(struct wlan_dp_psoc_context *dp_ctx)
 {
 	struct dp_rx_fst *dp_fst;
@@ -2173,3 +2249,10 @@ void dp_resume_fse_cache_flush(struct wlan_dp_psoc_context *dp_ctx)
 
 	dp_info("fse cache flush resumed");
 }
+
+void dp_set_fisa_dynamic_aggr_size_support(bool dynamic_aggr_size_support)
+{
+	struct wlan_dp_psoc_context *dp_ctx = dp_get_context();
+
+	dp_ctx->fisa_dynamic_aggr_size_support = dynamic_aggr_size_support;
+}

+ 22 - 12
components/dp/core/src/wlan_dp_fisa_rx.h

@@ -34,6 +34,14 @@
 
 #if defined(WLAN_SUPPORT_RX_FISA)
 
+/*
+ * Below is different types of max MSDU aggregation supported in FISA.
+ * Host should send one value less so that F.W will increment one
+ * and program in RXOLE reg
+ */
+#define DP_RX_FISA_MAX_AGGR_COUNT_DEFAULT	(16 - 1)
+#define	DP_RX_FISA_MAX_AGGR_COUNT_1		(32 - 1)
+
 #define FSE_CACHE_FLUSH_TIME_OUT	5 /* milliSeconds */
 #define FISA_UDP_MAX_DATA_LEN		1470 /* udp max data length */
 #define FISA_UDP_HDR_LEN		8 /* udp header length */
@@ -119,18 +127,6 @@ QDF_STATUS dp_rx_fisa_flush_by_ctx_id(struct dp_soc *soc, int napi_id);
  */
 QDF_STATUS dp_rx_fisa_flush_by_vdev_id(struct dp_soc *soc, uint8_t vdev_id);
 
-/**
- * dp_set_fisa_disallowed_for_vdev() - Set fisa disallowed flag for vdev
- * @cdp_soc: core txrx main context
- * @vdev_id: Vdev id
- * @rx_ctx_id: rx context id
- * @val: value to be set
- *
- * Return: None
- */
-void dp_set_fisa_disallowed_for_vdev(struct cdp_soc_t *cdp_soc, uint8_t vdev_id,
-				     uint8_t rx_ctx_id, uint8_t val);
-
 /**
  * dp_fisa_rx_fst_update_work() - Work functions for FST updates
  * @arg: argument passed to the work function
@@ -224,6 +220,15 @@ void dp_fisa_cfg_init(struct wlan_dp_psoc_cfg *config,
  * Return: None
  */
 void dp_set_fst_in_cmem(bool fst_in_cmem);
+
+/**
+ * dp_set_fisa_dynamic_aggr_size_support() - Set flag to indicate dynamic
+ *					     aggregation size support
+ * @dynamic_aggr_size_support: Flag to indicate dynamic aggregation support
+ *
+ * Return: None
+ */
+void dp_set_fisa_dynamic_aggr_size_support(bool dynamic_aggr_size_support);
 #else
 static inline void
 dp_rx_fst_update_pm_suspend_status(struct wlan_dp_psoc_context *dp_ctx,
@@ -243,5 +248,10 @@ static inline void dp_fisa_cfg_init(struct wlan_dp_psoc_cfg *config,
 static inline void dp_set_fst_in_cmem(bool fst_in_cmem)
 {
 }
+
+static inline void
+dp_set_fisa_dynamic_aggr_size_support(bool dynamic_aggr_size_support)
+{
+}
 #endif
 #endif

+ 387 - 89
components/dp/core/src/wlan_dp_main.c

@@ -44,6 +44,7 @@
 #ifdef FEATURE_DIRECT_LINK
 #include "dp_internal.h"
 #endif
+#include <cdp_txrx_ctrl.h>
 
 #ifdef WLAN_DP_PROFILE_SUPPORT
 /* Memory profile table based on supported caps */
@@ -177,22 +178,24 @@ dp_get_intf_by_netdev(struct wlan_dp_psoc_context *dp_ctx, qdf_netdev_t dev)
 }
 
 /**
- * validate_interface_id() - Check if interface ID is valid
- * @intf_id: interface ID
+ * validate_link_id() - Check if link ID is valid
+ * @link_id: DP link ID
  *
- * Return: 0 on success, error code on failure
+ * Return: true on success, false on failure
  */
-static int validate_interface_id(uint8_t intf_id)
+static bool validate_link_id(uint8_t link_id)
 {
-	if (intf_id == WLAN_UMAC_VDEV_ID_MAX) {
+	if (link_id == WLAN_UMAC_VDEV_ID_MAX) {
 		dp_err("Interface is not up: %ps", QDF_RET_IP);
-		return -EINVAL;
+		return false;
 	}
-	if (intf_id >= WLAN_MAX_VDEVS) {
-		dp_err("Bad interface id:%u", intf_id);
-		return -EINVAL;
+
+	if (link_id >= WLAN_MAX_VDEVS) {
+		dp_err("Bad interface id:%u", link_id);
+		return false;
 	}
-	return 0;
+
+	return true;
 }
 
 int is_dp_intf_valid(struct wlan_dp_intf *dp_intf)
@@ -213,7 +216,67 @@ int is_dp_intf_valid(struct wlan_dp_intf *dp_intf)
 		return -EAGAIN;
 	}
 
-	return validate_interface_id(dp_intf->intf_id);
+	return 0;
+}
+
+bool is_dp_link_valid(struct wlan_dp_link *dp_link)
+{
+	struct wlan_dp_intf *dp_intf;
+	int ret;
+
+	if (!dp_link) {
+		dp_err("link is NULL");
+		return false;
+	}
+
+	dp_intf = dp_link->dp_intf;
+	ret = is_dp_intf_valid(dp_intf);
+	if (ret)
+		return false;
+
+	return validate_link_id(dp_link->link_id);
+}
+
+QDF_STATUS dp_get_front_link_no_lock(struct wlan_dp_intf *dp_intf,
+				     struct wlan_dp_link **out_link)
+{
+	QDF_STATUS status;
+	qdf_list_node_t *node;
+
+	*out_link = NULL;
+
+	status = qdf_list_peek_front(&dp_intf->dp_link_list, &node);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
+
+	*out_link = qdf_container_of(node, struct wlan_dp_link, node);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS dp_get_next_link_no_lock(struct wlan_dp_intf *dp_intf,
+				    struct wlan_dp_link *cur_link,
+				    struct wlan_dp_link **out_link)
+{
+	QDF_STATUS status;
+	qdf_list_node_t *node;
+
+	if (!cur_link)
+		return QDF_STATUS_E_INVAL;
+
+	*out_link = NULL;
+
+	status = qdf_list_peek_next(&dp_intf->dp_link_list,
+				    &cur_link->node,
+				    &node);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
+
+	*out_link = qdf_container_of(node, struct wlan_dp_link, node);
+
+	return status;
 }
 
 static QDF_STATUS
@@ -691,7 +754,7 @@ __dp_process_mic_error(struct wlan_dp_intf *dp_intf)
 	struct wlan_dp_psoc_callbacks *ops = &dp_intf->dp_ctx->dp_ops;
 	struct wlan_objmgr_vdev *vdev;
 
-	vdev = dp_objmgr_get_vdev_by_user(dp_intf, WLAN_DP_ID);
+	vdev = dp_objmgr_get_vdev_by_user(dp_intf->def_link, WLAN_DP_ID);
 	if (!vdev) {
 		return;
 	}
@@ -745,6 +808,7 @@ dp_rx_mic_error_ind(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id,
 	struct dp_mic_error_info *dp_mic_info;
 	struct wlan_objmgr_vdev *vdev;
 	struct wlan_dp_intf *dp_intf;
+	struct wlan_dp_link *dp_link;
 
 	if (!psoc)
 		return;
@@ -754,12 +818,13 @@ dp_rx_mic_error_ind(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id,
 						    WLAN_DP_ID);
 	if (!vdev)
 		return;
-	dp_intf = dp_get_vdev_priv_obj(vdev);
-	if (!dp_intf) {
+	dp_link = dp_get_vdev_priv_obj(vdev);
+	if (!dp_link) {
 		dp_comp_vdev_put_ref(vdev);
 		return;
 	}
 
+	dp_intf = dp_link->dp_intf;
 	dp_mic_info = qdf_mem_malloc(sizeof(*dp_mic_info));
 	if (!dp_mic_info) {
 		dp_comp_vdev_put_ref(vdev);
@@ -858,6 +923,167 @@ void dp_mic_init_work(struct wlan_dp_intf *dp_intf)
 	dp_intf->mic_work.info = NULL;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * dp_intf_get_next_deflink_candidate() - Get a candidate link from the list of
+ *					  links available in the dp interface.
+ * @dp_intf: DP interface handle
+ * @cur_def_link: Handle to current def_link in the DP interface
+ *
+ * Return: Handle of the candidate for next def_link
+ *	   NULL, if there is no other suitable candidate found.
+ */
+static struct wlan_dp_link *
+dp_intf_get_next_deflink_candidate(struct wlan_dp_intf *dp_intf,
+				   struct wlan_dp_link *cur_def_link)
+{
+	struct wlan_dp_link *dp_link, *dp_link_next;
+
+	dp_for_each_link_held_safe(dp_intf, dp_link, dp_link_next) {
+		/*
+		 * dp_link is removed from the list when its deleted.
+		 * But check if its valid or not. Additional check to make
+		 * sure that the next deflink is valid.
+		 */
+		if (!is_dp_link_valid(dp_link))
+			continue;
+
+		if (dp_link !=  cur_def_link)
+			return dp_link;
+	}
+
+	return NULL;
+}
+
+/**
+ * dp_change_def_link() - Change default link for the dp_intf
+ * @dp_intf: DP interface for which default link is to be changed
+ * @dp_link: link on which link switch notification arrived.
+ * @lswitch_req: Link switch request params
+ *
+ * This API is called only when dp_intf->def_link == dp_link,
+ * and there is a need to change the def_link of the dp_intf,
+ * due to any reason.
+ *
+ * Return: QDF_STATUS
+ */
+static inline QDF_STATUS
+dp_change_def_link(struct wlan_dp_intf *dp_intf,
+		   struct wlan_dp_link *dp_link,
+		   struct wlan_mlo_link_switch_req *lswitch_req)
+{
+	struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
+	struct wlan_dp_link *next_def_link;
+	cdp_config_param_type peer_param = {0};
+	QDF_STATUS status;
+
+	next_def_link = dp_intf_get_next_deflink_candidate(dp_intf, dp_link);
+	if (!is_dp_link_valid(next_def_link)) {
+		/* Unable to get candidate for next def_link */
+		dp_info("Unable to get next def link %pK", next_def_link);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/*
+	 * Switch dp_vdev related params
+	 *  - Change vdev of MLD peer.
+	 */
+	dp_info("Peer " QDF_MAC_ADDR_FMT ", change vdev %d -> %d",
+		QDF_MAC_ADDR_REF(lswitch_req->peer_mld_addr.bytes),
+		dp_link->link_id, next_def_link->link_id);
+	peer_param.new_vdev_id = next_def_link->link_id;
+	status = cdp_txrx_set_peer_param(dp_ctx->cdp_soc,
+					 /* Current vdev for remote MLD peer */
+					 dp_link->link_id,
+					 lswitch_req->peer_mld_addr.bytes,
+					 CDP_CONFIG_MLD_PEER_VDEV,
+					 peer_param);
+
+	/*
+	 * DP link switch checks and process is completed successfully.
+	 * Change the def_link to the partner link
+	 */
+	if (QDF_IS_STATUS_SUCCESS(status))
+		dp_intf->def_link = next_def_link;
+
+	return status;
+}
+
+QDF_STATUS
+dp_link_switch_notification(struct wlan_objmgr_vdev *vdev,
+			    struct wlan_mlo_link_switch_req *lswitch_req)
+{
+	/* Add prints to string and print it at last, so we have only 1 print */
+	struct wlan_dp_psoc_context *dp_ctx;
+	struct wlan_dp_intf *dp_intf;
+	struct wlan_dp_link *dp_link;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	dp_ctx = dp_get_context();
+
+	dp_link = dp_get_vdev_priv_obj(vdev);
+	if (!is_dp_link_valid(dp_link)) {
+		dp_err("dp_link from vdev %pK is invalid", vdev);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	dp_intf = dp_link->dp_intf;
+	dp_info("Link switch req for dp_link %pK id %d (" QDF_MAC_ADDR_FMT
+		"), dp_intf %pK (" QDF_MAC_ADDR_FMT
+		") cur_def_link %pK id %d device_mode %d num_links %d",
+		dp_link, dp_link->link_id,
+		QDF_MAC_ADDR_REF(dp_link->mac_addr.bytes),
+		dp_intf, QDF_MAC_ADDR_REF(dp_intf->mac_addr.bytes),
+		dp_intf->def_link, dp_intf->def_link->link_id,
+		dp_intf->device_mode, dp_intf->num_links);
+
+	if (dp_intf->device_mode != QDF_STA_MODE) {
+		/* Link switch supported only for STA mode */
+		status = QDF_STATUS_E_INVAL;
+		goto exit;
+	}
+
+	if (dp_intf->num_links == 1) {
+		/* There is only one link, so we cannot switch */
+		status = QDF_STATUS_E_CANCELED;
+		goto exit;
+	}
+
+	if (dp_link != dp_intf->def_link) {
+		/* default link is not being switched, so DP is fine */
+		goto exit;
+	}
+
+	/* Recipe to be done before switching a default link */
+	status = dp_change_def_link(dp_intf, dp_link, lswitch_req);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		/* Failed to switch default link */
+		dp_info("Failed to change def_link for dp_intf %pK", dp_intf);
+		goto exit;
+	}
+
+exit:
+	dp_info("Link switch req %s (ret %d) for dp_link %pK id %d ("
+		QDF_MAC_ADDR_FMT "), dp_intf %pK (" QDF_MAC_ADDR_FMT
+		") cur_def_link %pK id %d device_mode %d num_links %d",
+		QDF_IS_STATUS_ERROR(status) ? "Failed" : "Successful",
+		status, dp_link, dp_link->link_id,
+		QDF_MAC_ADDR_REF(dp_link->mac_addr.bytes),
+		dp_intf, QDF_MAC_ADDR_REF(dp_intf->mac_addr.bytes),
+		dp_intf->def_link, dp_intf->def_link->link_id,
+		dp_intf->device_mode, dp_intf->num_links);
+
+	return status;
+}
+#else
+static struct wlan_dp_link *
+dp_intf_get_next_deflink_candidate(struct wlan_dp_intf *dp_intf,
+				   struct wlan_dp_link *cur_def_link)
+{
+	return NULL;
+}
+#endif
+
 QDF_STATUS
 dp_peer_obj_create_notification(struct wlan_objmgr_peer *peer, void *arg)
 {
@@ -919,11 +1145,13 @@ dp_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_dp_psoc_context *dp_ctx;
 	struct wlan_dp_intf *dp_intf;
+	struct wlan_dp_link *dp_link;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	struct qdf_mac_addr *mac_addr;
 	qdf_netdev_t dev;
 
-	dp_info("DP VDEV OBJ create notification");
+	dp_info("DP VDEV OBJ create notification, vdev_id %d",
+		wlan_vdev_get_id(vdev));
 
 	psoc = wlan_vdev_get_psoc(vdev);
 	if (!psoc) {
@@ -949,36 +1177,62 @@ dp_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 		return QDF_STATUS_E_INVAL;
 	}
 
-	dp_intf->device_mode = wlan_vdev_mlme_get_opmode(vdev);
-	qdf_spin_lock_bh(&dp_intf->vdev_lock);
-	dp_intf->intf_id = vdev->vdev_objmgr.vdev_id;
-	dp_intf->vdev = vdev;
-	qdf_spin_unlock_bh(&dp_intf->vdev_lock);
-	qdf_atomic_init(&dp_intf->num_active_task);
+	dp_link = qdf_mem_malloc(sizeof(*dp_link));
+	if (!dp_link) {
+		dp_err("DP link(" QDF_MAC_ADDR_FMT ") memory alloc failed",
+		       QDF_MAC_ADDR_REF(mac_addr->bytes));
+		return QDF_STATUS_E_NOMEM;
+	}
 
-	if (dp_intf->device_mode == QDF_SAP_MODE ||
-	    dp_intf->device_mode == QDF_P2P_GO_MODE) {
-		dp_intf->sap_tx_block_mask = DP_TX_FN_CLR | DP_TX_SAP_STOP;
+	/* Update Parent interface details */
+	dp_link->dp_intf = dp_intf;
+	qdf_spin_lock_bh(&dp_intf->dp_link_list_lock);
+	qdf_list_insert_front(&dp_intf->dp_link_list, &dp_link->node);
+	dp_intf->num_links++;
+	qdf_spin_unlock_bh(&dp_intf->dp_link_list_lock);
 
-		status = qdf_event_create(&dp_intf->qdf_sta_eap_frm_done_event);
-		if (!QDF_IS_STATUS_SUCCESS(status)) {
-			dp_err("eap frm done event init failed!!");
-			return status;
-		}
-		qdf_mem_zero(&dp_intf->stats, sizeof(qdf_net_dev_stats));
-	}
+	qdf_copy_macaddr(&dp_link->mac_addr, mac_addr);
+	qdf_spinlock_create(&dp_link->vdev_lock);
+
+	qdf_spin_lock_bh(&dp_link->vdev_lock);
+	dp_link->link_id = vdev->vdev_objmgr.vdev_id;
+	dp_link->vdev = vdev;
+	qdf_spin_unlock_bh(&dp_link->vdev_lock);
 
 	status = wlan_objmgr_vdev_component_obj_attach(vdev,
 						       WLAN_COMP_DP,
-						       (void *)dp_intf,
+						       (void *)dp_link,
 						       QDF_STATUS_SUCCESS);
 	if (QDF_IS_STATUS_ERROR(status)) {
-		dp_err("Failed to attach dp_intf with vdev");
+		dp_err("Failed to attach dp_link with vdev");
 		return status;
 	}
 
-	dp_nud_ignore_tracking(dp_intf, false);
-	dp_mic_enable_work(dp_intf);
+	if (dp_intf->num_links == 1) {
+		/*
+		 * Interface level operations to be done only
+		 * when the first link is created
+		 */
+		dp_intf->def_link = dp_link;
+		dp_intf->device_mode = wlan_vdev_mlme_get_opmode(vdev);
+		qdf_atomic_init(&dp_intf->num_active_task);
+		dp_nud_ignore_tracking(dp_intf, false);
+		dp_mic_enable_work(dp_intf);
+
+		if (dp_intf->device_mode == QDF_SAP_MODE ||
+		    dp_intf->device_mode == QDF_P2P_GO_MODE) {
+			dp_intf->sap_tx_block_mask = DP_TX_FN_CLR |
+						     DP_TX_SAP_STOP;
+
+			status = qdf_event_create(&dp_intf->qdf_sta_eap_frm_done_event);
+			if (!QDF_IS_STATUS_SUCCESS(status)) {
+				dp_err("eap frm done event init failed!!");
+				return status;
+			}
+			qdf_mem_zero(&dp_intf->stats,
+				     sizeof(qdf_net_dev_stats));
+		}
+	}
 
 	return status;
 }
@@ -988,48 +1242,80 @@ dp_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 
 {
 	struct wlan_dp_intf *dp_intf;
+	struct wlan_dp_link *dp_link;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
-	dp_info("DP VDEV OBJ destroy notification");
+	dp_info("DP VDEV OBJ destroy notification, vdev_id %d",
+		wlan_vdev_get_id(vdev));
 
-	dp_intf = dp_get_vdev_priv_obj(vdev);
-	if (!dp_intf) {
-		dp_err("Failed to get DP interface obj");
+	dp_link = dp_get_vdev_priv_obj(vdev);
+	if (!dp_link) {
+		dp_err("Failed to get DP link obj");
 		return QDF_STATUS_E_INVAL;
 	}
 
-	dp_nud_ignore_tracking(dp_intf, true);
-	dp_nud_reset_tracking(dp_intf);
-	dp_nud_flush_work(dp_intf);
-	dp_mic_flush_work(dp_intf);
+	dp_intf = dp_link->dp_intf;
+
+	qdf_spin_lock_bh(&dp_intf->dp_link_list_lock);
+	qdf_list_remove_node(&dp_intf->dp_link_list, &dp_link->node);
+	dp_intf->num_links--;
+	qdf_spin_unlock_bh(&dp_intf->dp_link_list_lock);
+
+	if (dp_intf->num_links == 0) {
+		/*
+		 * Interface level operations are stopped when last
+		 * link is deleted
+		 */
+		dp_nud_ignore_tracking(dp_intf, true);
+		dp_nud_reset_tracking(dp_intf);
+		dp_nud_flush_work(dp_intf);
+		dp_mic_flush_work(dp_intf);
+
+		if (dp_intf->device_mode == QDF_SAP_MODE ||
+		    dp_intf->device_mode == QDF_P2P_GO_MODE) {
+			status = qdf_event_destroy(&dp_intf->qdf_sta_eap_frm_done_event);
+			if (!QDF_IS_STATUS_SUCCESS(status)) {
+				dp_err("eap frm done event destroy failed!!");
+				return status;
+			}
+			dp_intf->txrx_ops.tx.tx = NULL;
+			dp_intf->sap_tx_block_mask |= DP_TX_FN_CLR;
+		}
+	}
+
+	qdf_mem_zero(&dp_link->conn_info, sizeof(struct wlan_dp_conn_info));
+
+	/*
+	 * If the dp_link which is being destroyed is the default link,
+	 * then find a new link to be made the default link
+	 */
+	if (dp_intf->def_link == dp_link)
+		dp_intf->def_link =
+			dp_intf_get_next_deflink_candidate(dp_intf, dp_link);
 
+	/*
+	 * Change this to link level, since during link switch,
+	 * it might not go to 0
+	 */
 	status = dp_intf_wait_for_task_complete(dp_intf);
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
 
-	if (dp_intf->device_mode == QDF_SAP_MODE ||
-	    dp_intf->device_mode == QDF_P2P_GO_MODE) {
-		status = qdf_event_destroy(&dp_intf->qdf_sta_eap_frm_done_event);
-		if (!QDF_IS_STATUS_SUCCESS(status)) {
-			dp_err("eap frm done event destroy failed!!");
-			return status;
-		}
-		dp_intf->txrx_ops.tx.tx = NULL;
-		dp_intf->sap_tx_block_mask |= DP_TX_FN_CLR;
-	}
-	qdf_mem_zero(&dp_intf->conn_info, sizeof(struct wlan_dp_conn_info));
-	dp_intf->intf_id = WLAN_UMAC_VDEV_ID_MAX;
-	qdf_spin_lock_bh(&dp_intf->vdev_lock);
-	dp_intf->vdev = NULL;
-	qdf_spin_unlock_bh(&dp_intf->vdev_lock);
+	qdf_spin_lock_bh(&dp_link->vdev_lock);
+	dp_link->vdev = NULL;
+	qdf_spin_unlock_bh(&dp_link->vdev_lock);
+
+	qdf_spinlock_destroy(&dp_link->vdev_lock);
+
 	status = wlan_objmgr_vdev_component_obj_detach(vdev,
 						       WLAN_COMP_DP,
-						       (void *)dp_intf);
+						       (void *)dp_link);
 	if (QDF_IS_STATUS_ERROR(status)) {
-		dp_err("Failed to detach dp_intf with vdev");
+		dp_err("Failed to detach dp_link with vdev");
 		return status;
 	}
 
+	qdf_mem_free(dp_link);
 	return status;
 }
 
@@ -1300,12 +1586,15 @@ err:
 
 void dp_try_send_rps_ind(struct wlan_objmgr_vdev *vdev)
 {
-	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_link *dp_link = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_intf *dp_intf;
 
-	if (!dp_intf) {
-		dp_err("dp interface is NULL");
+	if (!dp_link) {
+		dp_err("dp link is NULL");
 		return;
 	}
+
+	dp_intf = dp_link->dp_intf;
 	if (dp_intf->dp_ctx->rps)
 		dp_send_rps_ind(dp_intf);
 }
@@ -1343,6 +1632,7 @@ void dp_set_rps(uint8_t vdev_id, bool enable)
 	struct wlan_objmgr_vdev *vdev;
 	struct wlan_dp_psoc_context *dp_ctx;
 	struct wlan_dp_intf *dp_intf;
+	struct wlan_dp_link *dp_link;
 
 	dp_ctx = dp_get_context();
 	if (!dp_ctx)
@@ -1353,13 +1643,15 @@ void dp_set_rps(uint8_t vdev_id, bool enable)
 	if (!vdev)
 		return;
 
-	dp_intf = dp_get_vdev_priv_obj(vdev);
-	if (!dp_intf) {
+	dp_link = dp_get_vdev_priv_obj(vdev);
+	if (!dp_link) {
 		dp_comp_vdev_put_ref(vdev);
-		dp_err_rl("DP interface not found for vdev_id: %d", vdev_id);
+		dp_err_rl("DP link not found for vdev_id: %d", vdev_id);
 		return;
 	}
 
+	dp_intf = dp_link->dp_intf;
+
 	dp_info("Set RPS to %d for vdev_id %d", enable, vdev_id);
 	if (!dp_ctx->rps) {
 		if (enable)
@@ -1437,6 +1729,7 @@ QDF_STATUS dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
 					  struct dp_rsp_stats *rsp)
 {
 	struct wlan_dp_intf *dp_intf;
+	struct wlan_dp_link *dp_link;
 	struct wlan_objmgr_vdev *vdev;
 
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
@@ -1447,13 +1740,15 @@ QDF_STATUS dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_INVAL;
 	}
 
-	dp_intf = dp_get_vdev_priv_obj(vdev);
-	if (!dp_intf) {
-		dp_err("Unable to get DP interface");
+	dp_link = dp_get_vdev_priv_obj(vdev);
+	if (!dp_link) {
+		dp_err("Unable to get DP link for vdev_id %d", rsp->vdev_id);
 		wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID);
 		return QDF_STATUS_E_INVAL;
 	}
 
+	dp_intf = dp_link->dp_intf;
+
 	dp_info("rsp->arp_req_enqueue :%x", rsp->arp_req_enqueue);
 	dp_info("rsp->arp_req_tx_success :%x", rsp->arp_req_tx_success);
 	dp_info("rsp->arp_req_tx_failure :%x", rsp->arp_req_tx_failure);
@@ -1484,27 +1779,25 @@ QDF_STATUS dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
 
 #ifdef WLAN_OBJMGR_REF_ID_TRACE
 struct wlan_objmgr_vdev *
-__dp_objmgr_get_vdev_by_user(struct wlan_dp_intf *dp_intf,
+__dp_objmgr_get_vdev_by_user(struct wlan_dp_link *dp_link,
 			     wlan_objmgr_ref_dbgid id,
 			     const char *func, int line)
 {
 	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS status;
 
-	if (!dp_intf) {
-		dp_err("dp_intf is NULL (via %s, id %d)", func, id);
+	if (!dp_link)
 		return NULL;
-	}
 
-	qdf_spin_lock_bh(&dp_intf->vdev_lock);
-	vdev = dp_intf->vdev;
+	qdf_spin_lock_bh(&dp_link->vdev_lock);
+	vdev = dp_link->vdev;
 	if (vdev) {
 		status = wlan_objmgr_vdev_try_get_ref_debug(vdev, id, func,
 							    line);
 		if (QDF_IS_STATUS_ERROR(status))
 			vdev = NULL;
 	}
-	qdf_spin_unlock_bh(&dp_intf->vdev_lock);
+	qdf_spin_unlock_bh(&dp_link->vdev_lock);
 
 	if (!vdev)
 		dp_debug("VDEV is NULL (via %s, id %d)", func, id);
@@ -1526,26 +1819,24 @@ __dp_objmgr_put_vdev_by_user(struct wlan_objmgr_vdev *vdev,
 }
 #else
 struct wlan_objmgr_vdev *
-__dp_objmgr_get_vdev_by_user(struct wlan_dp_intf *dp_intf,
+__dp_objmgr_get_vdev_by_user(struct wlan_dp_link *dp_link,
 			     wlan_objmgr_ref_dbgid id,
 			     const char *func)
 {
 	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS status;
 
-	if (!dp_intf) {
-		dp_err("dp_intf is NULL (via %s, id %d)", func, id);
+	if (!dp_link)
 		return NULL;
-	}
 
-	qdf_spin_lock_bh(&dp_intf->vdev_lock);
-	vdev = dp_intf->vdev;
+	qdf_spin_lock_bh(&dp_link->vdev_lock);
+	vdev = dp_link->vdev;
 	if (vdev) {
 		status = wlan_objmgr_vdev_try_get_ref(vdev, id);
 		if (QDF_IS_STATUS_ERROR(status))
 			vdev = NULL;
 	}
-	qdf_spin_unlock_bh(&dp_intf->vdev_lock);
+	qdf_spin_unlock_bh(&dp_link->vdev_lock);
 
 	if (!vdev)
 		dp_debug("VDEV is NULL (via %s, id %d)", func, id);
@@ -2080,6 +2371,7 @@ QDF_STATUS dp_config_direct_link(struct wlan_dp_intf *dp_intf,
 {
 	struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
 	struct direct_link_info *config = &dp_intf->direct_link_config;
+	struct wlan_dp_link *dp_link, *dp_link_next;
 	void *htc_handle;
 	bool prev_ll, update_ll, vote_link;
 	cdp_config_param_type vdev_param = {0};
@@ -2107,14 +2399,20 @@ QDF_STATUS dp_config_direct_link(struct wlan_dp_intf *dp_intf,
 	vote_link = config->config_set ^ config_direct_link;
 	config->config_set = config_direct_link;
 	config->low_latency = enable_low_latency;
-	vdev_param.cdp_vdev_tx_to_fw = config_direct_link;
-	status = cdp_txrx_set_vdev_param(wlan_psoc_get_dp_handle(dp_ctx->psoc),
-					 dp_intf->intf_id, CDP_VDEV_TX_TO_FW,
-					 vdev_param);
+	dp_for_each_link_held_safe(dp_intf, dp_link, dp_link_next) {
+		vdev_param.cdp_vdev_tx_to_fw = config_direct_link;
+		status = cdp_txrx_set_vdev_param(
+				wlan_psoc_get_dp_handle(dp_ctx->psoc),
+				dp_link->link_id, CDP_VDEV_TX_TO_FW,
+				vdev_param);
+		if (QDF_IS_STATUS_ERROR(status))
+			break;
+	}
 
 	if (config_direct_link) {
 		if (vote_link)
-			htc_vote_link_up(htc_handle, HTC_LINK_VOTE_SAP_USER_ID);
+			htc_vote_link_up(htc_handle,
+					 HTC_LINK_VOTE_DIRECT_LINK_USER_ID);
 		if (update_ll)
 			hif_prevent_link_low_power_states(
 						htc_get_hif_device(htc_handle));
@@ -2126,7 +2424,7 @@ QDF_STATUS dp_config_direct_link(struct wlan_dp_intf *dp_intf,
 	} else {
 		if (vote_link)
 			htc_vote_link_down(htc_handle,
-					   HTC_LINK_VOTE_SAP_USER_ID);
+					   HTC_LINK_VOTE_DIRECT_LINK_USER_ID);
 		if (update_ll)
 			hif_allow_link_low_power_states(
 						htc_get_hif_device(htc_handle));

+ 36 - 19
components/dp/core/src/wlan_dp_nud_tracking.c

@@ -39,19 +39,30 @@
  */
 static uint32_t dp_txrx_get_tx_ack_count(struct wlan_dp_intf *dp_intf)
 {
-	return cdp_get_tx_ack_stats(cds_get_context(QDF_MODULE_ID_SOC),
-				    dp_intf->intf_id);
+	struct cdp_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	struct wlan_dp_link *dp_link;
+	struct wlan_dp_link *dp_link_next;
+	uint32_t ack_count = 0;
+
+	dp_for_each_link_held_safe(dp_intf, dp_link, dp_link_next) {
+		ack_count += cdp_get_tx_ack_stats(soc, dp_link->link_id);
+	}
+
+	return ack_count;
 }
 
 void dp_nud_set_gateway_addr(struct wlan_objmgr_vdev *vdev,
 			     struct qdf_mac_addr gw_mac_addr)
 {
-	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_link *dp_link = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_intf *dp_intf;
 
-	if (!dp_intf) {
-		dp_err("Unable to get DP Interface");
+	if (!dp_link) {
+		dp_err("Unable to get DP link");
 		return;
 	}
+
+	dp_intf = dp_link->dp_intf;
 	qdf_mem_copy(dp_intf->nud_tracking.gw_mac_addr.bytes,
 		     gw_mac_addr.bytes,
 		     sizeof(struct qdf_mac_addr));
@@ -77,11 +88,6 @@ void dp_nud_incr_gw_rx_pkt_cnt(struct wlan_dp_intf *dp_intf,
 void dp_nud_flush_work(struct wlan_dp_intf *dp_intf)
 {
 	struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
-	struct wlan_dp_psoc_callbacks *dp_ops = &dp_ctx->dp_ops;
-
-	if (dp_ops->dp_is_link_adapter(dp_ops->callback_ctx,
-				       dp_intf->intf_id))
-		return;
 
 	if (dp_intf->device_mode == QDF_STA_MODE &&
 	    dp_ctx->dp_cfg.enable_nud_tracking) {
@@ -143,7 +149,7 @@ static void dp_nud_stats_info(struct wlan_dp_intf *dp_intf)
 	struct wlan_dp_psoc_callbacks *cb = &dp_intf->dp_ctx->dp_ops;
 	uint32_t pause_map;
 
-	vdev = dp_objmgr_get_vdev_by_user(dp_intf, WLAN_DP_ID);
+	vdev = dp_objmgr_get_vdev_by_user(dp_intf->def_link, WLAN_DP_ID);
 	if (!vdev) {
 		return;
 	}
@@ -161,7 +167,7 @@ static void dp_nud_stats_info(struct wlan_dp_intf *dp_intf)
 	cb->os_if_dp_nud_stats_info(vdev);
 
 	pause_map = cb->dp_get_pause_map(cb->callback_ctx,
-					 dp_intf->intf_id);
+					 dp_intf->dev);
 	dp_info("Current pause_map value %x", pause_map);
 	dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
 }
@@ -213,7 +219,7 @@ static bool dp_nud_honour_failure(struct wlan_dp_intf *dp_intf)
 	uint8_t bssid[QDF_MAC_ADDR_SIZE];
 	bool ap_is_gateway;
 
-	vdev = dp_objmgr_get_vdev_by_user(dp_intf, WLAN_DP_ID);
+	vdev = dp_objmgr_get_vdev_by_user(dp_intf->def_link, WLAN_DP_ID);
 	if (!vdev)
 		goto fail;
 	wlan_vdev_mgr_get_param_bssid(vdev, bssid);
@@ -279,7 +285,7 @@ static void dp_nud_failure_work(void *data)
 	}
 
 	dp_ctx->dp_ops.dp_nud_failure_work(dp_ctx->dp_ops.callback_ctx,
-					   dp_intf->intf_id);
+					   dp_intf->dev);
 }
 
 void dp_nud_init_tracking(struct wlan_dp_intf *dp_intf)
@@ -346,6 +352,7 @@ static void dp_nud_filter_netevent(struct qdf_mac_addr *netdev_addr,
 {
 	int status;
 	struct wlan_dp_intf *dp_intf;
+	struct wlan_dp_link *dp_link;
 	struct wlan_dp_psoc_context *dp_ctx;
 	struct wlan_objmgr_vdev *vdev;
 
@@ -383,7 +390,13 @@ static void dp_nud_filter_netevent(struct qdf_mac_addr *netdev_addr,
 		return;
 	}
 
-	vdev = dp_objmgr_get_vdev_by_user(dp_intf, WLAN_DP_ID);
+	/*
+	 * NUD is used for STATION mode only, where all the MLO links
+	 * are assumed to be connected. Hence use the deflink here to check
+	 * if the interface is connected.
+	 */
+	dp_link = dp_intf->def_link;
+	vdev = dp_objmgr_get_vdev_by_user(dp_link, WLAN_DP_ID);
 	if (!vdev)
 		return;
 
@@ -393,7 +406,8 @@ static void dp_nud_filter_netevent(struct qdf_mac_addr *netdev_addr,
 		return;
 	}
 	dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
-	if (!dp_intf->conn_info.is_authenticated) {
+
+	if (!dp_link->conn_info.is_authenticated) {
 		dp_info("client " QDF_MAC_ADDR_FMT
 			" is in the middle of WPS/EAPOL exchange.",
 			QDF_MAC_ADDR_REF(dp_intf->mac_addr.bytes));
@@ -463,12 +477,15 @@ void dp_nud_netevent_cb(struct qdf_mac_addr *netdev_addr,
 
 void dp_nud_indicate_roam(struct wlan_objmgr_vdev *vdev)
 {
-	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_link *dp_link = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_intf *dp_intf;
 
-	if (!dp_intf) {
-		dp_err("Unable to get DP Interface");
+	if (!dp_link) {
+		dp_err("Unable to get DP link");
 		return;
 	}
+
+	dp_intf = dp_link->dp_intf;
 	dp_nud_set_tracking(dp_intf, DP_NUD_NONE, false);
 }
 #endif

+ 11 - 7
components/dp/core/src/wlan_dp_periodic_sta_stats.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -84,14 +84,16 @@ void dp_periodic_sta_stats_config(struct dp_config *config,
 
 void dp_periodic_sta_stats_start(struct wlan_objmgr_vdev *vdev)
 {
-	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_link *dp_link = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_intf *dp_intf;
 	struct dp_config *dp_cfg;
 
-	if (!dp_intf) {
-		dp_nofl_err("Unable to get DP interface");
+	if (!dp_link) {
+		dp_nofl_err("Unable to get DP link");
 		return;
 	}
 
+	dp_intf = dp_link->dp_intf;
 	dp_cfg = dp_intf->dp_ctx->dp_cfg;
 
 	if ((dp_intf->device_mode == QDF_STA_MODE) &&
@@ -108,14 +110,16 @@ void dp_periodic_sta_stats_start(struct wlan_objmgr_vdev *vdev)
 
 void dp_periodic_sta_stats_stop(struct wlan_objmgr_vdev *vdev)
 {
-	struct wlan_dp_intf *dp_intf = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_link *dp_link = dp_get_vdev_priv_obj(vdev);
+	struct wlan_dp_intf *dp_intf;
 	struct dp_config *dp_cfg;
 
-	if (!dp_intf) {
-		dp_nofl_err("Unable to get DP interface");
+	if (!dp_link) {
+		dp_nofl_err("Unable to get DP link");
 		return;
 	}
 
+	dp_intf = dp_link->dp_intf;
 	dp_cfg = dp_intf->dp_ctx->dp_cfg;
 
 	if ((dp_intf->device_mode == QDF_STA_MODE) &&

+ 19 - 2
components/dp/core/src/wlan_dp_rx_fst.c

@@ -145,7 +145,7 @@ static QDF_STATUS dp_rx_dump_fisa_stats(struct wlan_dp_psoc_context *dp_ctx)
 				 tuple_str,
 				 sizeof(tuple_str));
 
-		dp_info("Flow[%d][%s][%s] ring %d msdu-aggr %d flushes %d bytes-agg %llu avg-bytes-aggr %llu",
+		dp_info("Flow[%d][%s][%s] ring %d msdu-aggr %d flushes %d bytes-agg %llu avg-bytes-aggr %llu same_mld_vdev_mismatch %llu",
 			sw_ft_entry->flow_id,
 			sw_ft_entry->is_flow_udp ? "udp" : "tcp",
 			tuple_str,
@@ -154,7 +154,8 @@ static QDF_STATUS dp_rx_dump_fisa_stats(struct wlan_dp_psoc_context *dp_ctx)
 			sw_ft_entry->flush_count,
 			sw_ft_entry->bytes_aggregated,
 			qdf_do_div(sw_ft_entry->bytes_aggregated,
-				   sw_ft_entry->flush_count));
+				   sw_ft_entry->flush_count),
+			sw_ft_entry->same_mld_vdev_mismatch);
 	}
 	return QDF_STATUS_SUCCESS;
 }
@@ -713,6 +714,20 @@ QDF_STATUS dp_rx_fst_target_config(struct wlan_dp_psoc_context *dp_ctx)
 	return status;
 }
 
+static uint8_t
+dp_rx_fisa_get_max_aggr_supported(struct wlan_dp_psoc_context *dp_ctx)
+{
+	if (!dp_ctx->fisa_dynamic_aggr_size_support)
+		return DP_RX_FISA_MAX_AGGR_COUNT_DEFAULT;
+
+	switch (hal_get_target_type(dp_ctx->hal_soc)) {
+	case TARGET_TYPE_WCN6450:
+		return DP_RX_FISA_MAX_AGGR_COUNT_1;
+	default:
+		return DP_RX_FISA_MAX_AGGR_COUNT_DEFAULT;
+	}
+}
+
 #define FISA_MAX_TIMEOUT 0xffffffff
 #define FISA_DISABLE_TIMEOUT 0
 QDF_STATUS dp_rx_fisa_config(struct wlan_dp_psoc_context *dp_ctx)
@@ -722,6 +737,8 @@ QDF_STATUS dp_rx_fisa_config(struct wlan_dp_psoc_context *dp_ctx)
 
 	fisa_config.pdev_id = 0;
 	fisa_config.fisa_timeout = FISA_MAX_TIMEOUT;
+	fisa_config.max_aggr_supported =
+		dp_rx_fisa_get_max_aggr_supported(dp_ctx);
 
 	cfg.fisa_config = &fisa_config;
 

+ 1 - 0
components/dp/core/src/wlan_dp_rx_thread.c

@@ -1521,6 +1521,7 @@ QDF_STATUS dp_txrx_init(ol_txrx_soc_handle soc, uint8_t pdev_id,
 		if (qdf_status != QDF_STATUS_SUCCESS) {
 			dp_err("Failed to initialize RX refill thread status:%d",
 			       qdf_status);
+			qdf_mem_free(dp_ext_hdl);
 			return qdf_status;
 		}
 		cdp_register_rx_refill_thread_sched_handler(soc,

+ 49 - 41
components/dp/core/src/wlan_dp_softap_txrx.c

@@ -206,15 +206,16 @@ void dp_softap_check_wait_for_tx_eap_pkt(struct wlan_dp_intf *dp_intf,
 #ifdef SAP_DHCP_FW_IND
 /**
  * dp_post_dhcp_ind() - Send DHCP START/STOP indication to FW
- * @dp_intf: pointer to DP interface
+ * @dp_link: DP link handle
  * @mac_addr: mac address
  * @dhcp_start: dhcp start
  *
  * Return: error number
  */
-int dp_post_dhcp_ind(struct wlan_dp_intf *dp_intf, uint8_t *mac_addr,
+int dp_post_dhcp_ind(struct wlan_dp_link *dp_link, uint8_t *mac_addr,
 		     bool dhcp_start)
 {
+	struct wlan_dp_intf *dp_intf;
 	struct dp_dhcp_ind msg;
 	struct wlan_dp_psoc_sb_ops *sb_ops;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -222,11 +223,12 @@ int dp_post_dhcp_ind(struct wlan_dp_intf *dp_intf, uint8_t *mac_addr,
 	dp_info("Post DHCP indication,sta_mac=" QDF_MAC_ADDR_FMT
 		 " ,  start=%u", QDF_MAC_ADDR_REF(mac_addr), dhcp_start);
 
-	if (!dp_intf) {
-		dp_err("NULL DP interface");
+	if (!is_dp_link_valid(dp_link)) {
+		dp_err("NULL DP link");
 		return QDF_STATUS_E_INVAL;
 	}
 
+	dp_intf = dp_link->dp_intf;
 	sb_ops = &dp_intf->dp_ctx->sb_ops;
 	msg.dhcp_start = dhcp_start;
 	msg.device_mode = dp_intf->device_mode;
@@ -237,7 +239,7 @@ int dp_post_dhcp_ind(struct wlan_dp_intf *dp_intf, uint8_t *mac_addr,
 		     mac_addr,
 		     QDF_MAC_ADDR_SIZE);
 
-	status = sb_ops->dp_send_dhcp_ind(dp_intf->intf_id, &msg);
+	status = sb_ops->dp_send_dhcp_ind(dp_link->link_id, &msg);
 	if (!QDF_IS_STATUS_SUCCESS(status)) {
 		dp_err("Post DHCP Ind MSG fail");
 		return QDF_STATUS_E_FAULT;
@@ -250,29 +252,30 @@ int dp_post_dhcp_ind(struct wlan_dp_intf *dp_intf, uint8_t *mac_addr,
 
 /**
  * dp_softap_notify_dhcp_ind() - Notify SAP for DHCP indication for tx desc
- * @intf_context: pointer to DP interface context
+ * @link_context: DP link context
  * @nbuf: pointer to OS packet (sk_buff)
  *
  * Return: None
  */
-static void dp_softap_notify_dhcp_ind(void *intf_context, qdf_nbuf_t nbuf)
+static void dp_softap_notify_dhcp_ind(void *link_context, qdf_nbuf_t nbuf)
 {
 	uint8_t *dest_mac_addr;
-	struct wlan_dp_intf *dp_intf = intf_context;
+	struct wlan_dp_link *dp_link = link_context;
 
-	if (is_dp_intf_valid(dp_intf))
+	if (!is_dp_link_valid(dp_link))
 		return;
 
 	dest_mac_addr = qdf_nbuf_data(nbuf) + DHCP_CLIENT_MAC_ADDR_OFFSET;
 
 	/*stop dhcp indication*/
-	dp_post_dhcp_ind(dp_intf, dest_mac_addr, false);
+	dp_post_dhcp_ind(dp_link, dest_mac_addr, false);
 }
 
-int dp_softap_inspect_dhcp_packet(struct wlan_dp_intf *dp_intf,
+int dp_softap_inspect_dhcp_packet(struct wlan_dp_link *dp_link,
 				  qdf_nbuf_t nbuf,
 				  enum qdf_proto_dir dir)
 {
+	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
 	struct wlan_objmgr_peer *peer;
 	struct wlan_dp_sta_info *sta_info;
@@ -314,7 +317,8 @@ int dp_softap_inspect_dhcp_packet(struct wlan_dp_intf *dp_intf,
 			if (dir != QDF_RX)
 				break;
 			if (sta_info->dhcp_nego_status == DHCP_NEGO_STOP)
-				errno =	dp_post_dhcp_ind(dp_intf,
+				errno =	dp_post_dhcp_ind(
+						dp_link,
 						sta_info->sta_mac.bytes,
 						true);
 			sta_info->dhcp_phase = DHCP_PHASE_DISCOVER;
@@ -328,7 +332,7 @@ int dp_softap_inspect_dhcp_packet(struct wlan_dp_intf *dp_intf,
 				break;
 			if (sta_info->dhcp_nego_status == DHCP_NEGO_STOP)
 				errno = dp_post_dhcp_ind(
-						dp_intf,
+						dp_link,
 						sta_info->sta_mac.bytes,
 						true);
 			sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS;
@@ -392,13 +396,15 @@ qdf_nbuf_t dp_sap_nbuf_orphan(struct wlan_dp_intf *dp_intf,
 
 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
 static
-void dp_softap_get_tx_resource(struct wlan_dp_intf *dp_intf,
+void dp_softap_get_tx_resource(struct wlan_dp_link *dp_link,
 			       qdf_nbuf_t nbuf)
 {
+	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
+
 	if (QDF_NBUF_CB_GET_IS_BCAST(nbuf) || QDF_NBUF_CB_GET_IS_MCAST(nbuf))
-		dp_get_tx_resource(dp_intf, &dp_intf->mac_addr);
+		dp_get_tx_resource(dp_link, &dp_intf->mac_addr);
 	else
-		dp_get_tx_resource(dp_intf,
+		dp_get_tx_resource(dp_link,
 				   (struct qdf_mac_addr *)(qdf_nbuf_data(nbuf) +
 							   QDF_NBUF_DEST_MAC_OFFSET));
 }
@@ -407,8 +413,8 @@ void dp_softap_get_tx_resource(struct wlan_dp_intf *dp_intf,
 #endif
 
 #ifdef FEATURE_WDS
-void
-dp_wds_replace_peer_mac(void *soc, struct wlan_dp_intf *dp_intf,
+static void
+dp_wds_replace_peer_mac(void *soc, struct wlan_dp_link *dp_link,
 			uint8_t *mac_addr)
 {
 	struct cdp_ast_entry_info ast_entry_info = {0};
@@ -416,7 +422,7 @@ dp_wds_replace_peer_mac(void *soc, struct wlan_dp_intf *dp_intf,
 	QDF_STATUS status;
 
 	if (!cdp_find_peer_exist(soc, OL_TXRX_PDEV_ID, mac_addr)) {
-		status = cdp_txrx_get_vdev_param(soc, dp_intf->intf_id,
+		status = cdp_txrx_get_vdev_param(soc, dp_link->link_id,
 						 CDP_ENABLE_WDS, &val);
 		if (!QDF_IS_STATUS_SUCCESS(status))
 			return;
@@ -434,13 +440,13 @@ dp_wds_replace_peer_mac(void *soc, struct wlan_dp_intf *dp_intf,
 }
 #else
 static inline
-void dp_wds_replace_peer_mac(void *soc, struct wlan_dp_intf *dp_intf,
+void dp_wds_replace_peer_mac(void *soc, struct wlan_dp_link *dp_link,
 			     uint8_t *mac_addr)
 {
 }
 #endif /* FEATURE_WDS*/
 
-static QDF_STATUS dp_softap_validate_peer_state(struct wlan_dp_intf *dp_intf,
+static QDF_STATUS dp_softap_validate_peer_state(struct wlan_dp_link *dp_link,
 						qdf_nbuf_t nbuf)
 {
 	struct qdf_mac_addr *dest_mac_addr;
@@ -458,8 +464,8 @@ static QDF_STATUS dp_softap_validate_peer_state(struct wlan_dp_intf *dp_intf,
 	qdf_copy_macaddr(&mac_addr, dest_mac_addr);
 	soc = cds_get_context(QDF_MODULE_ID_SOC);
 	QDF_BUG(soc);
-	dp_wds_replace_peer_mac(soc, dp_intf, mac_addr.bytes);
-	peer_state = cdp_peer_state_get(soc, dp_intf->intf_id,
+	dp_wds_replace_peer_mac(soc, dp_link, mac_addr.bytes);
+	peer_state = cdp_peer_state_get(soc, dp_link->link_id,
 					mac_addr.bytes);
 
 	if (peer_state == OL_TXRX_PEER_STATE_INVALID) {
@@ -613,12 +619,13 @@ dp_softap_inspect_traffic_end_indication_pkt(struct wlan_dp_intf *dp_intf,
 /**
  * dp_softap_start_xmit() - Transmit a frame
  * @nbuf: pointer to Network buffer
- * @dp_intf: DP interface
+ * @dp_link: DP link handle
  *
  * Return: QDF_STATUS_SUCCESS on successful transmission
  */
-QDF_STATUS dp_softap_start_xmit(qdf_nbuf_t nbuf, struct wlan_dp_intf *dp_intf)
+QDF_STATUS dp_softap_start_xmit(qdf_nbuf_t nbuf, struct wlan_dp_link *dp_link)
 {
+	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
 	struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
 	struct qdf_mac_addr *dest_mac_addr;
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
@@ -636,10 +643,10 @@ QDF_STATUS dp_softap_start_xmit(qdf_nbuf_t nbuf, struct wlan_dp_intf *dp_intf)
 
 	wlan_dp_pkt_add_timestamp(dp_intf, QDF_PKT_TX_DRIVER_ENTRY, nbuf);
 
-	if (QDF_IS_STATUS_ERROR(dp_softap_validate_peer_state(dp_intf, nbuf)))
+	if (QDF_IS_STATUS_ERROR(dp_softap_validate_peer_state(dp_link, nbuf)))
 		goto drop_pkt;
 
-	dp_softap_get_tx_resource(dp_intf, nbuf);
+	dp_softap_get_tx_resource(dp_link, nbuf);
 
 	nbuf = dp_sap_nbuf_orphan(dp_intf, nbuf);
 	if (!nbuf)
@@ -661,7 +668,7 @@ QDF_STATUS dp_softap_start_xmit(qdf_nbuf_t nbuf, struct wlan_dp_intf *dp_intf)
 
 	if (qdf_unlikely(QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) ==
 			 QDF_NBUF_CB_PACKET_TYPE_DHCP))
-		dp_softap_inspect_dhcp_packet(dp_intf, nbuf, QDF_TX);
+		dp_softap_inspect_dhcp_packet(dp_link, nbuf, QDF_TX);
 
 	if (qdf_unlikely(QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) ==
 			 QDF_NBUF_CB_PACKET_TYPE_EAPOL)) {
@@ -680,7 +687,7 @@ QDF_STATUS dp_softap_start_xmit(qdf_nbuf_t nbuf, struct wlan_dp_intf *dp_intf)
 		goto drop_pkt_and_release_skb;
 	}
 
-	if (dp_intf->txrx_ops.tx.tx(soc, dp_intf->intf_id, nbuf)) {
+	if (dp_intf->txrx_ops.tx.tx(soc, dp_link->link_id, nbuf)) {
 		dp_debug("Failed to send packet to txrx for sta: "
 			 QDF_MAC_ADDR_FMT,
 			 QDF_MAC_ADDR_REF(dest_mac_addr->bytes));
@@ -736,13 +743,13 @@ void dp_softap_tx_timeout(struct wlan_dp_intf *dp_intf)
 void dp_softap_notify_tx_compl_cbk(qdf_nbuf_t nbuf,
 				   void *context, uint16_t flag)
 {
-	int errno;
-	struct wlan_dp_intf *dp_intf = context;
+	struct wlan_dp_link *dp_link = context;
+	struct wlan_dp_intf *dp_intf;
 
-	errno = is_dp_intf_valid(dp_intf);
-	if (errno)
+	if (!is_dp_link_valid(dp_link))
 		return;
 
+	dp_intf = dp_link->dp_intf;
 	if (QDF_NBUF_CB_PACKET_TYPE_DHCP == QDF_NBUF_CB_GET_PACKET_TYPE(nbuf)) {
 		dp_debug("sending DHCP indication");
 		dp_softap_notify_dhcp_ind(context, nbuf);
@@ -774,8 +781,7 @@ static inline bool dp_nbuf_dst_addr_is_mld_addr(struct wlan_dp_intf *dp_intf,
 {
 	struct qdf_mac_addr *mld_addr;
 
-	mld_addr = (struct qdf_mac_addr *)
-		wlan_vdev_mlme_get_mldaddr(dp_intf->vdev);
+	mld_addr = (struct qdf_mac_addr *)&dp_intf->mac_addr;
 
 	if (!qdf_is_macaddr_zero(mld_addr) &&
 	    !qdf_mem_cmp(mld_addr->bytes,
@@ -794,9 +800,10 @@ static inline bool dp_nbuf_dst_addr_is_mld_addr(struct wlan_dp_intf *dp_intf,
 }
 #endif
 
-QDF_STATUS dp_softap_rx_packet_cbk(void *intf_ctx, qdf_nbuf_t rx_buf)
+QDF_STATUS dp_softap_rx_packet_cbk(void *link_ctx, qdf_nbuf_t rx_buf)
 {
 	struct wlan_dp_intf *dp_intf = NULL;
+	struct wlan_dp_link *dp_link = NULL;
 	QDF_STATUS qdf_status;
 	unsigned int cpu_index;
 	qdf_nbuf_t nbuf = NULL;
@@ -806,12 +813,13 @@ QDF_STATUS dp_softap_rx_packet_cbk(void *intf_ctx, qdf_nbuf_t rx_buf)
 	struct dp_tx_rx_stats *stats;
 
 	/* Sanity check on inputs */
-	if (unlikely((!intf_ctx) || (!rx_buf))) {
+	if (unlikely(!link_ctx || !rx_buf)) {
 		dp_err("Null params being passed");
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	dp_intf = (struct wlan_dp_intf *)intf_ctx;
+	dp_link = (struct wlan_dp_link *)link_ctx;
+	dp_intf = dp_link->dp_intf;
 	dp_ctx = dp_intf->dp_ctx;
 
 	stats = &dp_intf->dp_stats.tx_rx_stats;
@@ -836,7 +844,7 @@ QDF_STATUS dp_softap_rx_packet_cbk(void *intf_ctx, qdf_nbuf_t rx_buf)
 		qdf_net_stats_add_rx_bytes(&dp_intf->stats,
 					   qdf_nbuf_len(nbuf));
 
-		dp_softap_inspect_dhcp_packet(dp_intf, nbuf, QDF_RX);
+		dp_softap_inspect_dhcp_packet(dp_link, nbuf, QDF_RX);
 
 		if (qdf_nbuf_is_ipv4_eapol_pkt(nbuf))
 			is_eapol = true;
@@ -855,7 +863,7 @@ QDF_STATUS dp_softap_rx_packet_cbk(void *intf_ctx, qdf_nbuf_t rx_buf)
 					  QDF_PKT_RX_DRIVER_EXIT, nbuf);
 
 		dp_event_eapol_log(nbuf, QDF_RX);
-		qdf_dp_trace_log_pkt(dp_intf->intf_id,
+		qdf_dp_trace_log_pkt(dp_link->link_id,
 				     nbuf, QDF_RX, QDF_TRACE_DEFAULT_PDEV_ID,
 				     dp_intf->device_mode);
 		DPTRACE(qdf_dp_trace(nbuf,
@@ -893,7 +901,7 @@ QDF_STATUS dp_softap_rx_packet_cbk(void *intf_ctx, qdf_nbuf_t rx_buf)
 
 		if (is_eapol && dp_ctx->dp_ops.dp_send_rx_pkt_over_nl) {
 			if (dp_ctx->dp_ops.dp_send_rx_pkt_over_nl(dp_intf->dev,
-					(u8 *)&dp_intf->conn_info.peer_macaddr,
+					(u8 *)&dp_link->conn_info.peer_macaddr,
 								  nbuf, false))
 				qdf_status = QDF_STATUS_SUCCESS;
 			else

+ 83 - 66
components/dp/core/src/wlan_dp_txrx.c

@@ -64,12 +64,13 @@ void dp_rx_skip_fisa(struct wlan_dp_psoc_context *dp_ctx, uint32_t value)
 #endif
 
 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
-void dp_get_tx_resource(struct wlan_dp_intf *dp_intf,
+void dp_get_tx_resource(struct wlan_dp_link *dp_link,
 			struct qdf_mac_addr *mac_addr)
 {
+	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
 	struct wlan_dp_psoc_callbacks *dp_ops = &dp_intf->dp_ctx->dp_ops;
 
-	dp_ops->dp_get_tx_resource(dp_intf->intf_id,
+	dp_ops->dp_get_tx_resource(dp_link->link_id,
 				   mac_addr);
 }
 #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
@@ -209,7 +210,8 @@ dp_tx_rx_collect_connectivity_stats_info(qdf_nbuf_t nbuf, void *context,
 		enum connectivity_stats_pkt_status action, uint8_t *pkt_type)
 {
 	uint32_t pkt_type_bitmap;
-	struct wlan_dp_intf *dp_intf =  (struct  wlan_dp_intf *)context;
+	struct wlan_dp_link *dp_link = (struct wlan_dp_link *)context;
+	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
 
 	/* ARP tracking is done already. */
 	pkt_type_bitmap = dp_intf->pkt_type_bitmap;
@@ -404,23 +406,24 @@ dp_tx_rx_collect_connectivity_stats_info(qdf_nbuf_t nbuf, void *context,
 
 /**
  * dp_get_transmit_mac_addr() - Get the mac address to validate the xmit
- * @dp_intf: DP interface
+ * @dp_link: DP link handle
  * @nbuf: The network buffer
  * @mac_addr_tx_allowed: The mac address to be filled
  *
  * Return: None
  */
 static
-void dp_get_transmit_mac_addr(struct wlan_dp_intf *dp_intf,
+void dp_get_transmit_mac_addr(struct wlan_dp_link *dp_link,
 			      qdf_nbuf_t nbuf,
 			      struct qdf_mac_addr *mac_addr_tx_allowed)
 {
+	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
 	bool is_mc_bc_addr = false;
 	enum nan_datapath_state state;
 
 	switch (dp_intf->device_mode) {
 	case QDF_NDI_MODE:
-		state = wlan_nan_get_ndi_state(dp_intf->vdev);
+		state = wlan_nan_get_ndi_state(dp_link->vdev);
 		if (state == NAN_DATA_NDI_CREATED_STATE ||
 		    state == NAN_DATA_CONNECTED_STATE ||
 		    state == NAN_DATA_CONNECTING_STATE ||
@@ -438,9 +441,9 @@ void dp_get_transmit_mac_addr(struct wlan_dp_intf *dp_intf,
 		break;
 	case QDF_STA_MODE:
 	case QDF_P2P_CLIENT_MODE:
-		if (wlan_cm_is_vdev_active(dp_intf->vdev))
+		if (wlan_cm_is_vdev_active(dp_link->vdev))
 			qdf_copy_macaddr(mac_addr_tx_allowed,
-					 &dp_intf->conn_info.bssid);
+					 &dp_link->conn_info.bssid);
 		break;
 	default:
 		break;
@@ -450,19 +453,19 @@ void dp_get_transmit_mac_addr(struct wlan_dp_intf *dp_intf,
 #ifdef HANDLE_BROADCAST_EAPOL_TX_FRAME
 /**
  * dp_fix_broadcast_eapol() - Fix broadcast eapol
- * @dp_intf: pointer to dp interface
+ * @dp_link: pointer to dp link
  * @nbuf: pointer to nbuf
  *
  * Override DA of broadcast eapol with bssid addr.
  *
  * Return: None
  */
-static void dp_fix_broadcast_eapol(struct wlan_dp_intf *dp_intf,
+static void dp_fix_broadcast_eapol(struct wlan_dp_link *dp_link,
 				   qdf_nbuf_t nbuf)
 {
 	qdf_ether_header_t *eth_hdr = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
 	unsigned char *ap_mac_addr =
-		&dp_intf->conn_info.bssid.bytes[0];
+		&dp_link->conn_info.bssid.bytes[0];
 
 	if (qdf_unlikely((QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) ==
 			  QDF_NBUF_CB_PACKET_TYPE_EAPOL) &&
@@ -477,7 +480,7 @@ static void dp_fix_broadcast_eapol(struct wlan_dp_intf *dp_intf,
 	}
 }
 #else
-static void dp_fix_broadcast_eapol(struct wlan_dp_intf *dp_intf,
+static void dp_fix_broadcast_eapol(struct wlan_dp_link *dp_link,
 				   qdf_nbuf_t nbuf)
 {
 }
@@ -541,7 +544,7 @@ void wlan_dp_pkt_add_timestamp(struct wlan_dp_intf *dp_intf,
 		uint64_t tsf_time;
 
 		dp_ops = &dp_intf->dp_ctx->dp_ops;
-		dp_ops->dp_get_tsf_time(dp_intf->intf_id,
+		dp_ops->dp_get_tsf_time(dp_intf->dev,
 					qdf_get_log_timestamp(),
 					&tsf_time);
 		qdf_add_dp_pkt_timestamp(nbuf, index, tsf_time);
@@ -550,8 +553,9 @@ void wlan_dp_pkt_add_timestamp(struct wlan_dp_intf *dp_intf,
 #endif
 
 QDF_STATUS
-dp_start_xmit(struct wlan_dp_intf *dp_intf, qdf_nbuf_t nbuf)
+dp_start_xmit(struct wlan_dp_link *dp_link, qdf_nbuf_t nbuf)
 {
+	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
 	struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
 	struct dp_tx_rx_stats *stats;
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
@@ -615,17 +619,17 @@ dp_start_xmit(struct wlan_dp_intf *dp_intf, qdf_nbuf_t nbuf)
 
 	/* track connectivity stats */
 	if (dp_intf->pkt_type_bitmap)
-		dp_tx_rx_collect_connectivity_stats_info(nbuf, dp_intf,
+		dp_tx_rx_collect_connectivity_stats_info(nbuf, dp_link,
 							 PKT_TYPE_REQ,
 							 &pkt_type);
 
-	dp_get_transmit_mac_addr(dp_intf, nbuf, &mac_addr_tx_allowed);
+	dp_get_transmit_mac_addr(dp_link, nbuf, &mac_addr_tx_allowed);
 	if (qdf_is_macaddr_zero(&mac_addr_tx_allowed)) {
 		dp_info_rl("tx not allowed, transmit operation suspended");
 		goto drop_pkt;
 	}
 
-	dp_get_tx_resource(dp_intf, &mac_addr_tx_allowed);
+	dp_get_tx_resource(dp_link, &mac_addr_tx_allowed);
 
 	if (!qdf_nbuf_ipa_owned_get(nbuf)) {
 		nbuf = dp_nbuf_orphan(dp_intf, nbuf);
@@ -661,7 +665,7 @@ dp_start_xmit(struct wlan_dp_intf *dp_intf, qdf_nbuf_t nbuf)
 			     sizeof(qdf_nbuf_data(nbuf)),
 			     QDF_TX));
 
-	if (!dp_intf_is_tx_allowed(nbuf, dp_intf->intf_id, soc,
+	if (!dp_intf_is_tx_allowed(nbuf, dp_link->link_id, soc,
 				   mac_addr_tx_allowed.bytes)) {
 		dp_info("Tx not allowed for sta:" QDF_MAC_ADDR_FMT,
 			QDF_MAC_ADDR_REF(mac_addr_tx_allowed.bytes));
@@ -682,11 +686,11 @@ dp_start_xmit(struct wlan_dp_intf *dp_intf, qdf_nbuf_t nbuf)
 		goto drop_pkt_and_release_nbuf;
 	}
 
-	dp_fix_broadcast_eapol(dp_intf, nbuf);
+	dp_fix_broadcast_eapol(dp_link, nbuf);
 
-	if (dp_intf->txrx_ops.tx.tx(soc, dp_intf->intf_id, nbuf)) {
+	if (dp_intf->txrx_ops.tx.tx(soc, dp_link->link_id, nbuf)) {
 		dp_debug_rl("Failed to send packet from adapter %u",
-			    dp_intf->intf_id);
+			    dp_link->link_id);
 		goto drop_pkt_and_release_nbuf;
 	}
 
@@ -698,7 +702,7 @@ drop_pkt:
 
 	/* track connectivity stats */
 	if (dp_intf->pkt_type_bitmap)
-		dp_tx_rx_collect_connectivity_stats_info(nbuf, dp_intf,
+		dp_tx_rx_collect_connectivity_stats_info(nbuf, dp_link,
 							 PKT_TYPE_TX_DROPPED,
 							 &pkt_type);
 	qdf_dp_trace_data_pkt(nbuf, QDF_TRACE_DEFAULT_PDEV_ID,
@@ -773,7 +777,8 @@ void dp_tx_timeout(struct wlan_dp_intf *dp_intf)
 
 void dp_sta_notify_tx_comp_cb(qdf_nbuf_t nbuf, void *ctx, uint16_t flag)
 {
-	struct wlan_dp_intf *dp_intf = ctx;
+	struct wlan_dp_link *dp_link = ctx;
+	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
 	enum qdf_proto_subtype subtype;
 	struct qdf_mac_addr *dest_mac_addr;
 	QDF_STATUS status;
@@ -812,10 +817,10 @@ void dp_sta_notify_tx_comp_cb(qdf_nbuf_t nbuf, void *ctx, uint16_t flag)
 	}
 
 	/* Since it is TDLS call took TDLS vdev ref*/
-	status = wlan_objmgr_vdev_try_get_ref(dp_intf->vdev, WLAN_TDLS_SB_ID);
+	status = wlan_objmgr_vdev_try_get_ref(dp_link->vdev, WLAN_TDLS_SB_ID);
 	if (QDF_IS_STATUS_SUCCESS(status)) {
-		wlan_tdls_update_tx_pkt_cnt(dp_intf->vdev, dest_mac_addr);
-		wlan_objmgr_vdev_release_ref(dp_intf->vdev, WLAN_TDLS_SB_ID);
+		wlan_tdls_update_tx_pkt_cnt(dp_link->vdev, dest_mac_addr);
+		wlan_objmgr_vdev_release_ref(dp_link->vdev, WLAN_TDLS_SB_ID);
 	}
 }
 
@@ -823,6 +828,7 @@ void dp_sta_notify_tx_comp_cb(qdf_nbuf_t nbuf, void *ctx, uint16_t flag)
 QDF_STATUS dp_mon_rx_packet_cbk(void *context, qdf_nbuf_t rxbuf)
 {
 	struct wlan_dp_intf *dp_intf;
+	struct wlan_dp_link *dp_link;
 	QDF_STATUS status;
 	qdf_nbuf_t nbuf;
 	qdf_nbuf_t nbuf_next;
@@ -835,7 +841,12 @@ QDF_STATUS dp_mon_rx_packet_cbk(void *context, qdf_nbuf_t rxbuf)
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	dp_intf = (struct wlan_dp_intf *)context;
+	dp_link = (struct wlan_dp_link *)context;
+	dp_intf = dp_link->dp_intf;
+	if (!dp_intf) {
+		dp_err("dp_intf is NULL for dp_link %pK", dp_link);
+		return QDF_STATUS_E_FAILURE;
+	}
 
 	cpu_index = qdf_get_cpu();
 	stats = &dp_intf->dp_stats.tx_rx_stats;
@@ -1316,16 +1327,19 @@ static inline void dp_tsf_timestamp_rx(struct wlan_dp_psoc_context *dp_ctx,
 #endif
 
 QDF_STATUS
-dp_rx_thread_gro_flush_ind_cbk(void *intf_ctx, int rx_ctx_id)
+dp_rx_thread_gro_flush_ind_cbk(void *link_ctx, int rx_ctx_id)
 {
-	struct wlan_dp_intf *dp_intf = intf_ctx;
+	struct wlan_dp_link *dp_link = link_ctx;
+	struct wlan_dp_intf *dp_intf;
 	enum dp_rx_gro_flush_code gro_flush_code = DP_RX_GRO_NORMAL_FLUSH;
 
-	if (qdf_unlikely((!dp_intf) || (!dp_intf->dp_ctx))) {
+	if (qdf_unlikely((!dp_link) || (!dp_link->dp_intf) ||
+			 (!dp_link->dp_intf->dp_ctx))) {
 		dp_err("Null params being passed");
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	dp_intf = dp_link->dp_intf;
 	if (dp_intf->runtime_disable_rx_thread)
 		return QDF_STATUS_SUCCESS;
 
@@ -1338,32 +1352,34 @@ dp_rx_thread_gro_flush_ind_cbk(void *intf_ctx, int rx_ctx_id)
 				   rx_ctx_id, gro_flush_code);
 }
 
-QDF_STATUS dp_rx_pkt_thread_enqueue_cbk(void *intf_ctx,
+QDF_STATUS dp_rx_pkt_thread_enqueue_cbk(void *link_ctx,
 					qdf_nbuf_t nbuf_list)
 {
 	struct wlan_dp_intf *dp_intf;
-	uint8_t intf_id;
+	struct wlan_dp_link *dp_link;
+	uint8_t link_id;
 	qdf_nbuf_t head_ptr;
 
-	if (qdf_unlikely(!intf_ctx || !nbuf_list)) {
+	if (qdf_unlikely(!link_ctx || !nbuf_list)) {
 		dp_err("Null params being passed");
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	dp_intf = (struct wlan_dp_intf *)intf_ctx;
-	if (is_dp_intf_valid(dp_intf))
+	dp_link = (struct wlan_dp_link *)link_ctx;
+	if (!is_dp_link_valid(dp_link))
 		return QDF_STATUS_E_FAILURE;
 
+	dp_intf = dp_link->dp_intf;
 	if (dp_intf->runtime_disable_rx_thread &&
 	    dp_intf->txrx_ops.rx.rx_stack)
-		return dp_intf->txrx_ops.rx.rx_stack(dp_intf, nbuf_list);
+		return dp_intf->txrx_ops.rx.rx_stack(dp_link, nbuf_list);
 
-	intf_id = dp_intf->intf_id;
+	link_id = dp_link->link_id;
 
 	head_ptr = nbuf_list;
 	while (head_ptr) {
 		qdf_nbuf_cb_update_vdev_id(head_ptr,
-					   intf_id);
+					   link_id);
 		head_ptr = qdf_nbuf_next(head_ptr);
 	}
 
@@ -1385,9 +1401,9 @@ QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
 
 #if defined(WLAN_SUPPORT_RX_FISA)
 /**
- * wlan_dp_set_fisa_disallowed_for_vdev() - Set fisa disallowed bit for a vdev
+ * wlan_dp_set_fisa_disallowed_for_intf() - Set fisa disallowed bit for an intf
  * @soc: DP soc handle
- * @vdev_id: Vdev id
+ * @dp_intf: DP interface handle
  * @rx_ctx_id: rx context id
  * @val: Enable or disable
  *
@@ -1396,16 +1412,16 @@ QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
  * Return: None
  */
 static inline
-void wlan_dp_set_fisa_disallowed_for_vdev(ol_txrx_soc_handle soc,
-					  uint8_t vdev_id,
+void wlan_dp_set_fisa_disallowed_for_intf(ol_txrx_soc_handle soc,
+					  struct wlan_dp_intf *dp_intf,
 					  uint8_t rx_ctx_id, uint8_t val)
 {
-	dp_set_fisa_disallowed_for_vdev(soc, vdev_id, rx_ctx_id, val);
+	dp_intf->fisa_disallowed[rx_ctx_id] = val;
 }
 #else
 static inline
-void wlan_dp_set_fisa_disallowed_for_vdev(ol_txrx_soc_handle soc,
-					  uint8_t vdev_id,
+void wlan_dp_set_fisa_disallowed_for_intf(ol_txrx_soc_handle soc,
+					  struct wlan_dp_intf *dp_intf,
 					  uint8_t rx_ctx_id, uint8_t val)
 {
 }
@@ -1432,15 +1448,13 @@ QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
 	if (gro_disallowed == 0 &&
 	    dp_intf->gro_flushed[rx_ctx_id] != 0) {
 		if (qdf_likely(soc))
-			wlan_dp_set_fisa_disallowed_for_vdev(soc,
-							     dp_intf->intf_id,
+			wlan_dp_set_fisa_disallowed_for_intf(soc, dp_intf,
 							     rx_ctx_id, 0);
 		dp_intf->gro_flushed[rx_ctx_id] = 0;
 	} else if (gro_disallowed &&
 		   dp_intf->gro_flushed[rx_ctx_id] == 0) {
 		if (qdf_likely(soc))
-			wlan_dp_set_fisa_disallowed_for_vdev(soc,
-							     dp_intf->intf_id,
+			wlan_dp_set_fisa_disallowed_for_intf(soc, dp_intf,
 							     rx_ctx_id, 1);
 	}
 
@@ -1563,9 +1577,10 @@ dp_is_gratuitous_arp_unsolicited_na(struct wlan_dp_psoc_context *dp_ctx,
 	return false;
 }
 
-QDF_STATUS dp_rx_flush_packet_cbk(void *dp_intf_context, uint8_t intf_id)
+QDF_STATUS dp_rx_flush_packet_cbk(void *dp_link_context, uint8_t link_id)
 {
-	struct wlan_dp_intf *dp_intf = (struct wlan_dp_intf *)dp_intf_context;
+	struct wlan_dp_link *dp_link = (struct wlan_dp_link *)dp_link_context;
+	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
 	struct wlan_dp_psoc_context *dp_ctx;
 	ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
 
@@ -1580,10 +1595,10 @@ QDF_STATUS dp_rx_flush_packet_cbk(void *dp_intf_context, uint8_t intf_id)
 
 	/* do fisa flush for this vdev */
 	if (wlan_dp_cfg_is_rx_fisa_enabled(&dp_ctx->dp_cfg))
-		wlan_dp_rx_fisa_flush_by_vdev_id((struct dp_soc *)soc, intf_id);
+		wlan_dp_rx_fisa_flush_by_vdev_id((struct dp_soc *)soc, link_id);
 
 	if (dp_ctx->enable_dp_rx_threads)
-		dp_txrx_flush_pkts_by_vdev_id(soc, intf_id);
+		dp_txrx_flush_pkts_by_vdev_id(soc, link_id);
 
 	qdf_atomic_dec(&dp_intf->num_active_task);
 
@@ -1610,10 +1625,11 @@ QDF_STATUS wlan_dp_rx_fisa_flush_by_vdev_id(void *dp_soc, uint8_t vdev_id)
 }
 #endif
 
-QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context,
+QDF_STATUS dp_rx_packet_cbk(void *dp_link_context,
 			    qdf_nbuf_t rxBuf)
 {
 	struct wlan_dp_intf *dp_intf = NULL;
+	struct wlan_dp_link *dp_link = NULL;
 	struct wlan_dp_psoc_context *dp_ctx = NULL;
 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
 	qdf_nbuf_t nbuf = NULL;
@@ -1630,12 +1646,13 @@ QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context,
 	uint8_t pkt_type;
 
 	/* Sanity check on inputs */
-	if (qdf_unlikely((!dp_intf_context) || (!rxBuf))) {
+	if (qdf_unlikely((!dp_link_context) || (!rxBuf))) {
 		dp_err("Null params being passed");
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	dp_intf = (struct wlan_dp_intf *)dp_intf_context;
+	dp_link = (struct wlan_dp_link *)dp_link_context;
+	dp_intf = dp_link->dp_intf;
 	dp_ctx = dp_intf->dp_ctx;
 
 	cpu_index = qdf_get_cpu();
@@ -1693,11 +1710,11 @@ QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context,
 
 		/* track connectivity stats */
 		if (dp_intf->pkt_type_bitmap)
-			dp_tx_rx_collect_connectivity_stats_info(nbuf, dp_intf,
+			dp_tx_rx_collect_connectivity_stats_info(nbuf, dp_link,
 								 PKT_TYPE_RSP,
 								 &pkt_type);
 
-		if ((dp_intf->conn_info.proxy_arp_service) &&
+		if ((dp_link->conn_info.proxy_arp_service) &&
 		    dp_is_gratuitous_arp_unsolicited_na(dp_ctx, nbuf)) {
 			qdf_atomic_inc(&stats->rx_usolict_arp_n_mcast_drp);
 			/* Remove SKB from internal tracking table before
@@ -1708,7 +1725,7 @@ QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context,
 		}
 
 		dp_event_eapol_log(nbuf, QDF_RX);
-		qdf_dp_trace_log_pkt(dp_intf->intf_id, nbuf, QDF_RX,
+		qdf_dp_trace_log_pkt(dp_link->link_id, nbuf, QDF_RX,
 				     QDF_TRACE_DEFAULT_PDEV_ID,
 				     dp_intf->device_mode);
 
@@ -1727,12 +1744,12 @@ QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context,
 		mac_addr = (struct qdf_mac_addr *)(qdf_nbuf_data(nbuf) +
 						   QDF_NBUF_SRC_MAC_OFFSET);
 
-		status = wlan_objmgr_vdev_try_get_ref(dp_intf->vdev,
+		status = wlan_objmgr_vdev_try_get_ref(dp_link->vdev,
 						      WLAN_TDLS_SB_ID);
 		if (QDF_IS_STATUS_SUCCESS(status)) {
-			wlan_tdls_update_rx_pkt_cnt(dp_intf->vdev, mac_addr,
+			wlan_tdls_update_rx_pkt_cnt(dp_link->vdev, mac_addr,
 						    dest_mac_addr);
-			wlan_objmgr_vdev_release_ref(dp_intf->vdev,
+			wlan_objmgr_vdev_release_ref(dp_link->vdev,
 						     WLAN_TDLS_SB_ID);
 		}
 
@@ -1763,7 +1780,7 @@ QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context,
 		/* hold configurable wakelock for unicast traffic */
 		if (!dp_is_current_high_throughput(dp_ctx) &&
 		    dp_ctx->dp_cfg.rx_wakelock_timeout &&
-		    dp_intf->conn_info.is_authenticated)
+		    dp_link->conn_info.is_authenticated)
 			wake_lock = dp_is_rx_wake_lock_needed(nbuf);
 
 		if (wake_lock) {
@@ -1783,7 +1800,7 @@ QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context,
 
 		if (send_over_nl && dp_ctx->dp_ops.dp_send_rx_pkt_over_nl) {
 			if (dp_ctx->dp_ops.dp_send_rx_pkt_over_nl(dp_intf->dev,
-					(u8 *)&dp_intf->conn_info.peer_macaddr,
+					(u8 *)&dp_link->conn_info.peer_macaddr,
 								  nbuf, false))
 				qdf_status = QDF_STATUS_SUCCESS;
 			else
@@ -1807,7 +1824,7 @@ QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context,
 			/* track connectivity stats */
 			if (dp_intf->pkt_type_bitmap)
 				dp_tx_rx_collect_connectivity_stats_info(
-					nbuf, dp_intf,
+					nbuf, dp_link,
 					PKT_TYPE_RX_DELIVERED,
 					&pkt_type);
 		} else {
@@ -1825,7 +1842,7 @@ QDF_STATUS dp_rx_packet_cbk(void *dp_intf_context,
 			/* track connectivity stats */
 			if (dp_intf->pkt_type_bitmap)
 				dp_tx_rx_collect_connectivity_stats_info(
-					nbuf, dp_intf,
+					nbuf, dp_link,
 					PKT_TYPE_RX_REFUSED,
 					&pkt_type);
 		}

+ 8 - 2
components/dp/core/src/wlan_dp_wfds.c

@@ -22,6 +22,7 @@
 #include "wlan_objmgr_psoc_obj.h"
 #include <qdf_mem.h>
 #include "wlan_dp_prealloc.h"
+#include <htc_api.h>
 
 static struct dp_direct_link_wfds_context *gp_dl_wfds_ctx;
 
@@ -551,12 +552,14 @@ dp_wfds_handle_ipcc_map_n_cfg_ind(struct wlan_qmi_wfds_ipcc_map_n_cfg_ind_msg *i
 QDF_STATUS dp_wfds_new_server(void)
 {
 	struct dp_direct_link_wfds_context *dl_wfds = gp_dl_wfds_ctx;
+	void *htc_handle = cds_get_context(QDF_MODULE_ID_HTC);
 
-	if (!dl_wfds)
+	if (!dl_wfds || !htc_handle)
 		return QDF_STATUS_E_INVAL;
 
 	qdf_atomic_set(&dl_wfds->wfds_state, DP_WFDS_SVC_CONNECTED);
 
+	htc_vote_link_up(htc_handle, HTC_LINK_VOTE_DIRECT_LINK_USER_ID);
 	dp_debug("Connected to WFDS QMI service, state: 0x%x",
 		 qdf_atomic_read(&dl_wfds->wfds_state));
 
@@ -567,12 +570,13 @@ void dp_wfds_del_server(void)
 {
 	struct dp_direct_link_wfds_context *dl_wfds = gp_dl_wfds_ctx;
 	qdf_device_t qdf_ctx = dl_wfds->direct_link_ctx->dp_ctx->qdf_dev;
+	void *htc_handle = cds_get_context(QDF_MODULE_ID_HTC);
 	void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
 	enum dp_wfds_state dl_wfds_state;
 	uint8_t i;
 	uint16_t page_idx;
 
-	if (!dl_wfds || !qdf_ctx || !hif_ctx)
+	if (!dl_wfds || !qdf_ctx || !hif_ctx || !htc_handle)
 		return;
 
 	dp_debug("WFDS QMI server exiting");
@@ -640,6 +644,8 @@ void dp_wfds_del_server(void)
 			dl_wfds->iommu_cfg.direct_link_refill_ring_base_paddr,
 			dl_wfds->iommu_cfg.direct_link_refill_ring_map_size);
 	}
+
+	htc_vote_link_down(htc_handle, HTC_LINK_VOTE_DIRECT_LINK_USER_ID);
 }
 
 QDF_STATUS dp_wfds_init(struct dp_direct_link_context *dp_direct_link_ctx)

+ 27 - 0
components/dp/dispatcher/inc/wlan_dp_api.h

@@ -64,4 +64,31 @@ void wlan_dp_print_fisa_rx_stats(enum cdp_fisa_stats_id stats_id);
  * Return: None
  */
 void wlan_dp_set_fst_in_cmem(bool fst_in_cmem);
+
+/**
+ * wlan_dp_set_fisa_dynamic_aggr_size_support - Set flag to indicate dynamic
+ *						MSDU aggregation size programming supported
+ * @dynamic_aggr_size_support: Flag to indicate dynamic aggregation size support
+ *
+ * Return: None
+ */
+void wlan_dp_set_fisa_dynamic_aggr_size_support(bool dynamic_aggr_size_support);
+
+#ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
+/**
+ * wlan_dp_is_local_pkt_capture_enabled() - Get local packet capture config
+ * @psoc: pointer to psoc object
+ *
+ * Return: true if local packet capture is enabled from ini
+ *         false otherwise
+ */
+bool
+wlan_dp_is_local_pkt_capture_enabled(struct wlan_objmgr_psoc *psoc);
+#else
+static inline bool
+wlan_dp_is_local_pkt_capture_enabled(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
+#endif /* WLAN_FEATURE_LOCAL_PKT_CAPTURE */
 #endif

+ 13 - 13
components/dp/dispatcher/inc/wlan_dp_public_struct.h

@@ -640,11 +640,11 @@ struct wlan_dp_psoc_callbacks {
 
 	qdf_netdev_t (*dp_get_netdev_by_vdev_mac)(struct qdf_mac_addr *mac_addr);
 	unsigned int (*dp_get_tx_flow_low_watermark)(hdd_cb_handle cb_ctx,
-						     uint8_t intf_id);
-	void (*dp_get_tx_resource)(uint8_t intf_id, struct qdf_mac_addr *mac_addr);
-	void (*dp_get_tsf_time)(uint8_t intf_id,
-				uint64_t input_time, uint64_t *tsf_time);
-
+						     qdf_netdev_t netdev);
+	void (*dp_get_tx_resource)(uint8_t link_id_id,
+				   struct qdf_mac_addr *mac_addr);
+	void (*dp_get_tsf_time)(qdf_netdev_t netdev, uint64_t input_time,
+				uint64_t *tsf_time);
 	void (*dp_tsf_timestamp_rx)(hdd_cb_handle ctx, qdf_nbuf_t nbuf);
 
 	QDF_STATUS (*dp_nbuf_push_pkt)(qdf_nbuf_t nbuf,
@@ -674,13 +674,13 @@ struct wlan_dp_psoc_callbacks {
 	bool (*dp_send_rx_pkt_over_nl)(qdf_netdev_t dev, uint8_t *addr,
 				       qdf_nbuf_t nbuf, bool unecrypted);
 	bool
-	(*wlan_dp_sta_get_dot11mode)(hdd_cb_handle context, uint8_t vdev_id,
+	(*wlan_dp_sta_get_dot11mode)(hdd_cb_handle context, qdf_netdev_t netdev,
 				     enum qca_wlan_802_11_mode *dot11_mode);
 	bool (*wlan_dp_get_ap_client_count)(hdd_cb_handle context,
-					    uint8_t vdev_id,
+					    qdf_netdev_t netdev,
 					    uint16_t *client_count);
 	bool (*wlan_dp_sta_ndi_connected)(hdd_cb_handle context,
-					  uint8_t vdev_id);
+					  qdf_netdev_t netdev);
 	bool (*dp_any_adapter_connected)(hdd_cb_handle context);
 	void (*dp_send_svc_nlink_msg)(int radio, int type, void *data, int len);
 
@@ -689,7 +689,7 @@ struct wlan_dp_psoc_callbacks {
 					       union wlan_tp_data *data,
 					       uint8_t dir);
 	void (*dp_send_mscs_action_frame)(hdd_cb_handle context,
-					  uint8_t vdev_id);
+					  qdf_netdev_t netdev);
 	void (*dp_pm_qos_add_request)(hdd_cb_handle context);
 	void (*dp_pm_qos_remove_request)(hdd_cb_handle context);
 	void (*dp_pm_qos_update_request)(hdd_cb_handle context,
@@ -700,22 +700,22 @@ struct wlan_dp_psoc_callbacks {
 					bool enable_disable_flag,
 					uint8_t user_triggered, int size);
 	bool (*dp_is_roaming_in_progress)(hdd_cb_handle context);
-	bool (*dp_is_ap_active)(hdd_cb_handle context, uint8_t vdev_id);
+	bool (*dp_is_ap_active)(hdd_cb_handle context, qdf_netdev_t netdev);
 	void (*dp_disable_rx_ol_for_low_tput)(hdd_cb_handle context,
 					      bool disable);
 	int (*dp_napi_apply_throughput_policy)(hdd_cb_handle context,
 					       uint64_t tx_packets,
 					       uint64_t rx_packets);
 	void (*wlan_dp_display_tx_multiq_stats)(hdd_cb_handle context,
-						uint8_t vdev_id);
+						qdf_netdev_t netdev);
 	void (*wlan_dp_display_netif_queue_history)(hdd_cb_handle context,
 				enum qdf_stats_verbosity_level verb_lvl);
 	void (*osif_dp_process_mic_error)(struct dp_mic_error_info *info,
 					  struct wlan_objmgr_vdev *vdev);
 	bool (*dp_is_link_adapter)(hdd_cb_handle context, uint8_t vdev_id);
 	void (*os_if_dp_nud_stats_info)(struct wlan_objmgr_vdev *vdev);
-	uint32_t (*dp_get_pause_map)(hdd_cb_handle context, uint8_t vdev_id);
-	void (*dp_nud_failure_work)(hdd_cb_handle context, uint8_t vdev_id);
+	uint32_t (*dp_get_pause_map)(hdd_cb_handle context, qdf_netdev_t dev);
+	void (*dp_nud_failure_work)(hdd_cb_handle context, qdf_netdev_t dev);
 	void (*link_monitoring_cb)(struct wlan_objmgr_psoc *psoc,
 				   uint8_t vdev_id,
 				   bool is_link_speed_good);

+ 26 - 10
components/dp/dispatcher/inc/wlan_dp_ucfg_api.h

@@ -62,15 +62,31 @@ ucfg_dp_is_disconect_after_roam_fail(struct wlan_objmgr_psoc *psoc)
 #endif
 
 /**
- * ucfg_dp_update_inf_mac() - update DP interface MAC address
+ * ucfg_dp_update_link_mac_addr() - Update the dp_link mac address, during MLO
+ *				    link switch.
+ * @vdev: Objmgr vdev corresponding to the dp_link
+ * @new_mac_addr: New mac address of the dp_link
+ * @is_link_switch: Flag to indicate if the link mac addr update is as a part
+ *		    of MLO link switch.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS ucfg_dp_update_link_mac_addr(struct wlan_objmgr_vdev *vdev,
+					struct qdf_mac_addr *new_mac_addr,
+					bool is_link_switch);
+
+/**
+ * ucfg_dp_update_intf_mac() - update DP interface MAC address
  * @psoc: psoc handle
  * @cur_mac: Current MAC address
  * @new_mac: new MAC address
+ * @vdev: objmgr vdev handle to set the def_link in dp_intf
  *
  */
-void ucfg_dp_update_inf_mac(struct wlan_objmgr_psoc *psoc,
-			    struct qdf_mac_addr *cur_mac,
-			    struct qdf_mac_addr *new_mac);
+void ucfg_dp_update_intf_mac(struct wlan_objmgr_psoc *psoc,
+			     struct qdf_mac_addr *cur_mac,
+			     struct qdf_mac_addr *new_mac,
+			     struct wlan_objmgr_vdev *vdev);
 
 /**
  * ucfg_dp_destroy_intf() - DP module interface deletion
@@ -924,12 +940,12 @@ bool ucfg_dp_get_dad_value(struct wlan_objmgr_vdev *vdev);
 bool ucfg_dp_get_con_status_value(struct wlan_objmgr_vdev *vdev);
 
 /**
- * ucfg_dp_get_intf_id() - Get intf_id
+ * ucfg_dp_get_link_id() - Get link_id
  * @vdev: vdev context
  *
- * Return: intf_id
+ * Return: link_id
  */
-uint8_t ucfg_dp_get_intf_id(struct wlan_objmgr_vdev *vdev);
+uint8_t ucfg_dp_get_link_id(struct wlan_objmgr_vdev *vdev);
 
 /**
  * ucfg_dp_get_arp_stats() - Get ARP stats
@@ -1414,13 +1430,13 @@ void ucfg_dp_wfds_del_server(void);
 
 /**
  * ucfg_dp_config_direct_link() - Set direct link config for vdev
- * @vdev: objmgr Vdev handle
+ * @dev: netdev
  * @config_direct_link: Flag to enable direct link path
  * @enable_low_latency: Flag to enable low link latency
  *
  * Return: QDF Status
  */
-QDF_STATUS ucfg_dp_config_direct_link(struct wlan_objmgr_vdev *vdev,
+QDF_STATUS ucfg_dp_config_direct_link(qdf_netdev_t dev,
 				      bool config_direct_link,
 				      bool enable_low_latency);
 #else
@@ -1457,7 +1473,7 @@ static inline void ucfg_dp_wfds_del_server(void)
 #endif
 
 static inline
-QDF_STATUS ucfg_dp_config_direct_link(struct wlan_objmgr_vdev *vdev,
+QDF_STATUS ucfg_dp_config_direct_link(qdf_netdev_t dev,
 				      bool config_direct_link,
 				      bool enable_low_latency)
 {

+ 14 - 0
components/dp/dispatcher/src/wlan_dp_api.c

@@ -46,3 +46,17 @@ void wlan_dp_set_fst_in_cmem(bool fst_in_cmem)
 {
 	dp_set_fst_in_cmem(fst_in_cmem);
 }
+
+void wlan_dp_set_fisa_dynamic_aggr_size_support(bool dynamic_aggr_size_support)
+{
+	dp_set_fisa_dynamic_aggr_size_support(dynamic_aggr_size_support);
+}
+
+#ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
+bool wlan_dp_is_local_pkt_capture_enabled(struct wlan_objmgr_psoc *psoc)
+{
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+
+	return cdp_cfg_get(soc, cfg_dp_local_pkt_capture);
+}
+#endif

Datei-Diff unterdrückt, da er zu groß ist
+ 427 - 184
components/dp/dispatcher/src/wlan_dp_ucfg_api.c


+ 4 - 3
components/ftm_time_sync/core/src/ftm_time_sync_main.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -395,8 +395,9 @@ ssize_t ftm_time_sync_show(struct wlan_objmgr_vdev *vdev, char *buf)
 		return 0;
 	}
 
-	size = qdf_scnprintf(buf, PAGE_SIZE, "%s %pM\n", "BSSID",
-			     vdev_priv->bssid.bytes);
+	size = qdf_scnprintf(buf, PAGE_SIZE,
+			     "%s " QDF_MAC_ADDR_FMT "\n", "BSSID",
+			     QDF_MAC_ADDR_REF(vdev_priv->bssid.bytes));
 
 	for (iter = 0; iter < vdev_priv->num_qtime_pair; iter++) {
 		q_initiator = vdev_priv->ftm_ts_priv.time_pair[iter].qtime_initiator;

+ 1 - 1
components/fw_offload/core/inc/wlan_fw_offload_main.h

@@ -265,7 +265,7 @@ struct wlan_fwol_cfg {
 	struct wlan_fwol_ie_allowlist ie_allowlist_cfg;
 	struct wlan_fwol_neighbor_report_cfg neighbor_report_cfg;
 	bool ani_enabled;
-	bool pcie_config;
+	uint8_t pcie_config;
 	bool enable_rts_sifsbursting;
 	uint8_t enable_sifs_burst;
 	uint8_t max_mpdus_inampdu;

+ 2 - 2
components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h

@@ -227,7 +227,7 @@ QDF_STATUS ucfg_fwol_get_ani_enabled(struct wlan_objmgr_psoc *psoc,
  * Return: QDF Status
  */
 QDF_STATUS ucfg_fwol_get_pcie_config(struct wlan_objmgr_psoc *psoc,
-				     bool *pcie_config);
+				     uint8_t *pcie_config);
 
 /**
  * ucfg_get_enable_rts_sifsbursting() - Assigns the enable_rts_sifsbursting
@@ -894,7 +894,7 @@ ucfg_fwol_get_ani_enabled(struct wlan_objmgr_psoc *psoc,
 
 static inline QDF_STATUS
 ucfg_fwol_get_pcie_config(struct wlan_objmgr_psoc *psoc,
-			  bool *pcie_config)
+			  uint8_t *pcie_config)
 {
 	return QDF_STATUS_E_FAILURE;
 }

+ 1 - 1
components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c

@@ -323,7 +323,7 @@ QDF_STATUS ucfg_fwol_get_ani_enabled(struct wlan_objmgr_psoc *psoc,
 }
 
 QDF_STATUS ucfg_fwol_get_pcie_config(struct wlan_objmgr_psoc *psoc,
-				     bool *pcie_config)
+				     uint8_t *pcie_config)
 {
 	struct wlan_fwol_psoc_obj *fwol_obj;
 

+ 4 - 0
components/mlme/core/inc/wlan_mlme_main.h

@@ -765,6 +765,8 @@ struct enhance_roam_info {
  * @ba_2k_jump_iot_ap: This is set to true if connected to the ba 2k jump IOT AP
  * @is_usr_ps_enabled: Is Power save enabled
  * @notify_co_located_ap_upt_rnr: Notify co located AP to update RNR or not
+ * @is_user_std_set: true if user set the @wifi_std
+ * @wifi_std: wifi standard version
  * @max_mcs_index: Max supported mcs index of vdev
  * @vdev_traffic_type: to set if vdev is LOW_LATENCY or HIGH_TPUT
  * @country_ie_for_all_band: take all band channel info in country ie
@@ -833,6 +835,8 @@ struct mlme_legacy_priv {
 	bool ba_2k_jump_iot_ap;
 	bool is_usr_ps_enabled;
 	bool notify_co_located_ap_upt_rnr;
+	bool is_user_std_set;
+	WMI_HOST_WIFI_STANDARD wifi_std;
 #ifdef WLAN_FEATURE_SON
 	uint8_t max_mcs_index;
 #endif

+ 6 - 0
components/mlme/core/inc/wlan_mlme_twt_api.h

@@ -328,5 +328,11 @@ bool mlme_is_flexible_twt_enabled(struct wlan_objmgr_psoc *psoc)
 {
 	return false;
 }
+
+static inline bool
+mlme_is_24ghz_twt_enabled(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
 #endif /* WLAN_SUPPORT_TWT */
 #endif /* _WLAN_MLME_TWT_API_H_ */

+ 8 - 0
components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h

@@ -440,6 +440,14 @@ void mlme_set_notify_co_located_ap_update_rnr(struct wlan_objmgr_vdev *vdev,
  */
 bool wlan_is_vdev_traffic_ll_ht(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * mlme_get_vdev_wifi_std() - get the wifi std version for the vdev
+ * @vdev: vdev pointer
+ *
+ * Return: WMI_HOST_WIFI_STANDARD
+ */
+WMI_HOST_WIFI_STANDARD mlme_get_vdev_wifi_std(struct wlan_objmgr_vdev *vdev);
+
 /**
  * mlme_get_assoc_type() - get associate type
  * @vdev: vdev pointer

+ 16 - 0
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c

@@ -1233,6 +1233,22 @@ bool wlan_is_vdev_traffic_ll_ht(struct wlan_objmgr_vdev *vdev)
 	return false;
 }
 
+WMI_HOST_WIFI_STANDARD mlme_get_vdev_wifi_std(struct wlan_objmgr_vdev *vdev)
+{
+	struct mlme_legacy_priv *mlme_priv;
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv) {
+		mlme_legacy_err("vdev legacy private object is NULL");
+		return WMI_HOST_WIFI_STANDARD_7;
+	}
+
+	if (!mlme_priv->is_user_std_set)
+		return WMI_HOST_WIFI_STANDARD_7;
+
+	return mlme_priv->wifi_std;
+}
+
 enum vdev_assoc_type  mlme_get_assoc_type(struct wlan_objmgr_vdev *vdev)
 {
 	struct mlme_legacy_priv *mlme_priv;

+ 73 - 0
components/mlme/dispatcher/inc/wlan_mlme_api.h

@@ -87,6 +87,19 @@ void
 wlan_mlme_update_cfg_with_tgt_caps(struct wlan_objmgr_psoc *psoc,
 				   struct mlme_tgt_caps *tgt_caps);
 
+/**
+ * wlan_mlme_update_aux_dev_caps() - Update mlme aux capability
+ * @psoc: pointer to psoc object
+ * @wlan_mlme_aux_dev_caps:  array for aux dev capability
+ *
+ * Return: None
+ */
+
+void
+wlan_mlme_update_aux_dev_caps(struct wlan_objmgr_psoc *psoc,
+			      struct wlan_mlme_aux_dev_caps
+			      wlan_mlme_aux_dev_caps[]);
+
 /*
  * mlme_get_wep_key() - get the wep key to process during auth frame
  * @vdev: VDEV object for which the wep key is being requested
@@ -1002,6 +1015,23 @@ QDF_STATUS wlan_mlme_get_oce_sap_enabled_info(struct wlan_objmgr_psoc *psoc,
  */
 void wlan_mlme_update_oce_flags(struct wlan_objmgr_pdev *pdev);
 
+/**
+ * wlan_mlme_cfg_get_aux_supported_modes() - get supported mode of aux.
+ *             definition of bitmap refer WMI_AUX_DEV_CAPS_SUPPORTED_MODE.
+ *
+ * @psoc: pointer to psoc object
+ * @aux_index: aux index, current only support aux0.
+ * @hw_mode_id: hw mode id
+ * @supported_modes_bitmap: output for value
+ *
+ * Return: true for getting value. false for failure check.
+ */
+bool wlan_mlme_cfg_get_aux_supported_modes(
+		struct wlan_objmgr_psoc *psoc,
+		uint32_t aux_index,
+		enum wlan_mlme_hw_mode_config_type hw_mode_id,
+		uint32_t *supported_modes_bitmap);
+
 #ifdef WLAN_FEATURE_11AX
 /**
  * wlan_mlme_cfg_get_he_ul_mumimo() - Get the HE Ul Mumio
@@ -3992,6 +4022,32 @@ uint8_t wlan_mlme_get_sta_mlo_conn_max_num(struct wlan_objmgr_psoc *psoc);
 QDF_STATUS wlan_mlme_set_sta_mlo_conn_max_num(struct wlan_objmgr_psoc *psoc,
 					      uint8_t value);
 
+/**
+ * wlan_mlme_set_user_set_link_num() - set number of links that config by user
+ * @psoc: pointer to psoc object
+ * @value: value to set
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS wlan_mlme_set_user_set_link_num(struct wlan_objmgr_psoc *psoc,
+					   uint8_t value);
+
+/**
+ * wlan_mlme_restore_user_set_link_num() - restore link num when SSR happens
+ * @psoc: pointer to psoc object
+ *
+ * Return: void
+ */
+void wlan_mlme_restore_user_set_link_num(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_mlme_clear_user_set_link_num() - clear user set link num
+ * @psoc: pointer to psoc object
+ *
+ * Return: void
+ */
+void wlan_mlme_clear_user_set_link_num(struct wlan_objmgr_psoc *psoc);
+
 /**
  * wlan_mlme_get_sta_mlo_conn_band_bmp() - get band bitmap that sta mlo
  *                                         connection can support
@@ -4031,6 +4087,23 @@ uint8_t wlan_mlme_get_sta_mlo_simultaneous_links(struct wlan_objmgr_psoc *psoc);
 QDF_STATUS wlan_mlme_set_sta_mlo_conn_band_bmp(struct wlan_objmgr_psoc *psoc,
 					       uint8_t value);
 #else
+static inline QDF_STATUS
+wlan_mlme_set_user_set_link_num(struct wlan_objmgr_psoc *psoc,
+				uint8_t value)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline
+void wlan_mlme_restore_user_set_link_num(struct wlan_objmgr_psoc *psoc)
+{
+}
+
+static inline
+void wlan_mlme_clear_user_set_link_num(struct wlan_objmgr_psoc *psoc)
+{
+}
+
 static inline QDF_STATUS
 wlan_mlme_set_sta_mlo_conn_max_num(struct wlan_objmgr_psoc *psoc,
 				   uint8_t value)

+ 70 - 0
components/mlme/dispatcher/inc/wlan_mlme_public_struct.h

@@ -1337,6 +1337,71 @@ struct wlan_user_mcc_quota {
 	uint8_t vdev_id;
 };
 
+/**
+ * enum wlan_mlme_hw_mode_config_type - HW mode config type replicated from
+ *                                     wmi_hw_mode_config_type in FW header.
+ *                                     similar as wmi_host_hw_mode_config_type.
+ * @WLAN_MLME_HW_MODE_SINGLE: Only one PHY is active.
+ * @WLAN_MLME_HW_MODE_DBS: Both PHYs are active in different bands,
+ *                        one in 2G and another in 5G.
+ * @WLAN_MLME_HW_MODE_SBS_PASSIVE: Both PHYs are in passive mode (only rx) in
+ *                        same band; no tx allowed.
+ * @WLAN_MLME_HW_MODE_SBS: Both PHYs are active in the same band.
+ *                        Support for both PHYs within one band is planned
+ *                        for 5G only(as indicated in WMI_MAC_PHY_CAPABILITIES),
+ *                        but could be extended to other bands in the future.
+ *                        The separation of the band between the two PHYs needs
+ *                        to be communicated separately.
+ * @WLAN_MLME_HW_MODE_DBS_SBS: 3 PHYs, with 2 on the same band doing SBS
+ *                           as in WMI_HW_MODE_SBS, and 3rd on the other band
+ * @WLAN_MLME_HW_MODE_DBS_OR_SBS: Two PHY with one PHY capabale of both 2G and
+ *                        5G. It can support SBS (5G + 5G) OR DBS (5G + 2G).
+ * @WLAN_MLME_HW_MODE_DBS_2G_5G: Both PHYs are active in different bands.
+ *                               PhyA 2G and PhyB 5G
+ * @WLAN_MLME_HW_MODE_2G_PHYB: Only one phy is active. 2G mode on PhyB.
+ * @WLAN_MLME_HW_MODE_EMLSR: Both PHYs are active in listen mode in 1x1
+ *                          and Tx/Rx trigger on any PHY will switch
+ *                          from 1x1 to 2x2 on that Phy
+ * @WLAN_MLME_HW_MODE_AUX_EMLSR_SINGLE:  PHYA0 and AUX are active in listen mode
+ *                                      in 1x1 and Tx/Rx trigger on any.
+ *                                      PHY will switch from 1x1 to 2x2
+ *                                      on that Phy.
+ * @WLAN_MLME_HW_MODE_AUX_EMLSR_SPLIT: PHYA1 and AUX are active in listen mode
+ *                                    in 1x1 and Tx/Rx trigger on any.
+ *                                    PHY will switch from 1x1 to 2x2
+ *                                    on that Phy.
+ * @WLAN_MLME_HW_MODE_MAX: Max hw_mode_id.
+ */
+enum wlan_mlme_hw_mode_config_type {
+	WLAN_MLME_HW_MODE_SINGLE       = 0,
+	WLAN_MLME_HW_MODE_DBS          = 1,
+	WLAN_MLME_HW_MODE_SBS_PASSIVE  = 2,
+	WLAN_MLME_HW_MODE_SBS          = 3,
+	WLAN_MLME_HW_MODE_DBS_SBS      = 4,
+	WLAN_MLME_HW_MODE_DBS_OR_SBS   = 5,
+	WLAN_MLME_HW_MODE_DBS_2G_5G    = 6,
+	WLAN_MLME_HW_MODE_2G_PHYB      = 7,
+	WLAN_MLME_HW_MODE_EMLSR        = 8,
+	WLAN_MLME_HW_MODE_AUX_EMLSR_SINGLE = 9,
+	WLAN_MLME_HW_MODE_AUX_EMLSR_SPLIT  = 10,
+	WLAN_MLME_HW_MODE_MAX,
+};
+
+/* struct wlan_mlme_aux_dev_caps - wlan mlme aux dev capability
+ *
+ * @supported_modes_bitmap: indicate which mode this AUX supports for the
+ *                          HW mode defined in hw_mode_id
+ * @listen_pdev_id_map: indicate which AUX MAC can listen/scan for the HW mode
+ *                      described in hw_mode_id
+ * @emlsr_pdev_id_map: indicate which AUX MAC can perform eMLSR for the HW mode
+ *                     described in hw_mode_id.
+ */
+struct wlan_mlme_aux_dev_caps {
+	uint32_t supported_modes_bitmap;
+	uint32_t listen_pdev_id_map;
+	uint32_t emlsr_pdev_id_map;
+};
+
 /* struct wlan_mlme_generic - Generic CFG config items
  *
  * @band_capability: HW Band Capability - Both or 2.4G only or 5G only
@@ -1396,6 +1461,7 @@ struct wlan_user_mcc_quota {
  * @safe_mode_enable: safe mode to bypass some strict 6 GHz checks for
  * connection, bypass strict power levels
  * @sr_enable_modes: modes for which SR(Spatial Reuse) is enabled
+ * @wlan_mlme_aux0_dev_caps: capability for aux0
  */
 struct wlan_mlme_generic {
 	uint32_t band_capability;
@@ -1460,6 +1526,8 @@ struct wlan_mlme_generic {
 #if defined(WLAN_FEATURE_SR)
 	uint32_t sr_enable_modes;
 #endif
+	struct wlan_mlme_aux_dev_caps
+		wlan_mlme_aux0_dev_caps[WLAN_MLME_HW_MODE_MAX];
 };
 
 /**
@@ -1723,6 +1791,7 @@ enum station_prefer_bw {
  * @usr_scan_probe_unicast_ra:      User config unicast probe req in scan
  * @event_payload:                  Diagnostic event payload
  * @max_li_modulated_dtim_time_ms:  Max modulated DTIM time in ms.
+ * @user_set_link_num:              save link num set by vendor command
  * @mlo_support_link_num:           max number of links that sta mlo supports
  * @mlo_support_link_band:          band bitmap that sta mlo supports
  * @mlo_max_simultaneous_links:     number of simultaneous links
@@ -1757,6 +1826,7 @@ struct wlan_mlme_sta_cfg {
 #endif
 	uint16_t max_li_modulated_dtim_time_ms;
 #ifdef WLAN_FEATURE_11BE_MLO
+	uint8_t user_set_link_num;
 	uint8_t mlo_support_link_num;
 	uint8_t mlo_support_link_band;
 	uint8_t mlo_max_simultaneous_links;

+ 37 - 0
components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h

@@ -30,6 +30,7 @@
 #include <wlan_mlme_api.h>
 #include <wlan_mlme_main.h>
 #include "wma_tgt_cfg.h"
+#include "wlan_mlme_vdev_mgr_interface.h"
 
 /**
  * ucfg_mlme_init() - initialize mlme_ctx context.
@@ -282,6 +283,30 @@ ucfg_mlme_peer_config_vlan(struct wlan_objmgr_vdev *vdev,
 	return wlan_mlme_peer_config_vlan(vdev, macaddr);
 }
 
+/**
+ * ucfg_mlme_get_tdls_prohibited() - get if TDLS prohibited is advertised by
+ * the connected AP.
+ * @vdev: vdev pointer
+ *
+ * Return: bool
+ */
+static inline
+bool ucfg_mlme_get_tdls_prohibited(struct wlan_objmgr_vdev *vdev)
+{
+	return mlme_get_tdls_prohibited(vdev);
+}
+
+/**
+ * ucfg_mlme_get_tdls_chan_switch_prohibited() - get tdls chan switch prohibited
+ * @vdev: vdev pointer
+ *
+ * Return: bool
+ */
+static inline
+bool ucfg_mlme_get_tdls_chan_switch_prohibited(struct wlan_objmgr_vdev *vdev)
+{
+	return mlme_get_tdls_chan_switch_prohibited(vdev);
+}
 #ifdef MULTI_CLIENT_LL_SUPPORT
 /**
  * ucfg_mlme_get_wlm_multi_client_ll_caps() - Get multi client latency level
@@ -4678,6 +4703,18 @@ ucfg_mlme_set_roam_reason_vsie_status(struct wlan_objmgr_psoc *psoc,
 
 #endif
 
+/**
+ * ucfg_mlme_set_vdev_wifi_std()  - Set vdev wifi standard support
+ * @psoc: pointer to psoc object
+ * @vdev_id: Vdev id
+ * @wifi_std: wifi standard version
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+ucfg_mlme_set_vdev_wifi_std(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+			    WMI_HOST_WIFI_STANDARD wifi_std);
+
 /**
  * ucfg_mlme_set_vdev_traffic_low_latency()  - Set/clear vdev low latency
  * config

+ 95 - 1
components/mlme/dispatcher/src/wlan_mlme_api.c

@@ -662,6 +662,52 @@ wlan_mlme_update_cfg_with_tgt_caps(struct wlan_objmgr_psoc *psoc,
 	mlme_obj->cfg.gen.ocv_support = tgt_caps->ocv_support;
 }
 
+void
+wlan_mlme_update_aux_dev_caps(
+		struct wlan_objmgr_psoc *psoc,
+		struct wlan_mlme_aux_dev_caps wlan_mlme_aux_dev_caps[])
+{
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj)
+		return;
+
+	qdf_mem_copy(&mlme_obj->cfg.gen.wlan_mlme_aux0_dev_caps[0],
+		     &wlan_mlme_aux_dev_caps[0],
+		     sizeof(mlme_obj->cfg.gen.wlan_mlme_aux0_dev_caps));
+}
+
+bool wlan_mlme_cfg_get_aux_supported_modes(
+			struct wlan_objmgr_psoc *psoc,
+			uint32_t aux_index,
+			enum wlan_mlme_hw_mode_config_type hw_mode_id,
+			uint32_t *supported_modes_bitmap)
+{
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+	struct wlan_mlme_aux_dev_caps *wlan_mlme_aux0_dev_caps;
+
+	if (aux_index != 0) {
+		mlme_err("current only support aux0");
+		return false;
+	}
+
+	if (hw_mode_id >= WLAN_MLME_HW_MODE_MAX) {
+		mlme_err("invalid hw mode id %d.", hw_mode_id);
+		return false;
+	}
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj) {
+		mlme_err("MLME obj is NULL");
+		return false;
+	}
+	wlan_mlme_aux0_dev_caps = mlme_obj->cfg.gen.wlan_mlme_aux0_dev_caps;
+	*supported_modes_bitmap =
+		wlan_mlme_aux0_dev_caps[hw_mode_id].supported_modes_bitmap;
+	return true;
+}
+
 #ifdef WLAN_FEATURE_11AX
 QDF_STATUS wlan_mlme_cfg_get_he_ul_mumimo(struct wlan_objmgr_psoc *psoc,
 					  uint32_t *value)
@@ -1358,12 +1404,60 @@ QDF_STATUS wlan_mlme_set_sta_mlo_conn_max_num(struct wlan_objmgr_psoc *psoc,
 	if (!mlme_obj)
 		return QDF_STATUS_E_FAILURE;
 
-	mlme_obj->cfg.sta.mlo_support_link_num = value;
+	if (!value)
+		mlme_obj->cfg.sta.mlo_support_link_num =
+					  cfg_default(CFG_MLO_SUPPORT_LINK_NUM);
+	else
+		mlme_obj->cfg.sta.mlo_support_link_num = value;
+
 	mlme_legacy_debug("mlo_support_link_num %d", value);
 
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS wlan_mlme_set_user_set_link_num(struct wlan_objmgr_psoc *psoc,
+					   uint8_t value)
+{
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj)
+		return QDF_STATUS_E_FAILURE;
+
+	mlme_obj->cfg.sta.user_set_link_num = value;
+	mlme_legacy_debug("user_set_link_num %d", value);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+void wlan_mlme_restore_user_set_link_num(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj)
+		return;
+
+	if (!mlme_obj->cfg.sta.user_set_link_num)
+		return;
+
+	mlme_obj->cfg.sta.mlo_support_link_num =
+				mlme_obj->cfg.sta.user_set_link_num;
+	mlme_legacy_debug("restore mlo_support_link_num %d",
+			  mlme_obj->cfg.sta.user_set_link_num);
+}
+
+void wlan_mlme_clear_user_set_link_num(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj)
+		return;
+
+	mlme_obj->cfg.sta.user_set_link_num = 0;
+}
+
 uint8_t wlan_mlme_get_sta_mlo_conn_band_bmp(struct wlan_objmgr_psoc *psoc)
 {
 	struct wlan_mlme_psoc_ext_obj *mlme_obj;

+ 35 - 0
components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c

@@ -415,6 +415,41 @@ release:
 	return status;
 }
 
+QDF_STATUS
+ucfg_mlme_set_vdev_wifi_std(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+			    WMI_HOST_WIFI_STANDARD wifi_std)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct mlme_legacy_priv *mlme_priv;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_MLME_OBJMGR_ID);
+	if (!vdev) {
+		mlme_legacy_err("vdev %d: vdev not found",
+				vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv) {
+		mlme_legacy_err("vdev %d: vmlme_priv is null", vdev_id);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	mlme_priv->wifi_std = wifi_std;
+	mlme_priv->is_user_std_set = true;
+
+	if (wifi_std < WMI_HOST_WIFI_STANDARD_7)
+		wlan_vdev_mlme_set_user_dis_eht_flag(vdev, true);
+	else
+		wlan_vdev_mlme_set_user_dis_eht_flag(vdev, false);
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS
 ucfg_mlme_set_vdev_traffic_low_latency(struct wlan_objmgr_psoc *psoc,
 				       uint8_t vdev_id, bool set)

+ 13 - 0
components/pmo/core/inc/wlan_pmo_main.h

@@ -445,4 +445,17 @@ QDF_STATUS pmo_set_vdev_bridge_addr(struct wlan_objmgr_vdev *vdev,
 
 #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */
 
+/**
+ * pmo_core_get_listen_interval() - function to get configured
+ * listen interval
+ * @vdev: vdev objmgr vdev
+ * @listen_interval: Pointer variable to return listen interval
+ *
+ * This function allows get configured listen interval
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS pmo_core_get_listen_interval(struct wlan_objmgr_vdev *vdev,
+					uint32_t *listen_interval);
+
 #endif /* end  of _WLAN_PMO_MAIN_H_ */

+ 18 - 0
components/pmo/core/src/wlan_pmo_main.c

@@ -574,3 +574,21 @@ QDF_STATUS pmo_set_vdev_bridge_addr(struct wlan_objmgr_vdev *vdev,
 
 	return QDF_STATUS_SUCCESS;
 }
+
+QDF_STATUS pmo_core_get_listen_interval(struct wlan_objmgr_vdev *vdev,
+					uint32_t *listen_interval)
+{
+	struct pmo_vdev_priv_obj *vdev_ctx;
+
+	if (!vdev || !listen_interval) {
+		pmo_err("vdev NULL or NULL ptr");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	vdev_ctx = pmo_vdev_get_priv(vdev);
+	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
+	*listen_interval = vdev_ctx->dyn_listen_interval;
+	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
+
+	return QDF_STATUS_SUCCESS;
+}

+ 9 - 0
components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h

@@ -322,6 +322,9 @@ uint32_t
 wlan_pmo_get_interval_for_pagefault_wakeup_counts(
 						struct wlan_objmgr_psoc *psoc);
 
+QDF_STATUS wlan_pmo_get_listen_interval(struct wlan_objmgr_vdev *vdev,
+					uint32_t *listen_interval);
+
 #else /* WLAN_POWER_MANAGEMENT_OFFLOAD */
 
 static inline QDF_STATUS pmo_init(void)
@@ -503,6 +506,12 @@ wlan_pmo_get_interval_for_pagefault_wakeup_counts(struct wlan_objmgr_psoc *psoc)
 	return 0;
 }
 
+static QDF_STATUS wlan_pmo_get_listen_interval(struct wlan_objmgr_vdev *vdev,
+					       uint32_t *listen_interval)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
 #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */
 
 #endif /* end  of _WLAN_PMO_OBJ_MGMT_API_H_ */

+ 6 - 0
components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c

@@ -900,3 +900,9 @@ wlan_pmo_get_interval_for_pagefault_wakeup_counts(struct wlan_objmgr_psoc *psoc)
 {
 	return pmo_get_interval_for_pagefault_wakeup_counts(psoc);
 }
+
+QDF_STATUS wlan_pmo_get_listen_interval(struct wlan_objmgr_vdev *vdev,
+					uint32_t *listen_interval)
+{
+	return pmo_core_get_listen_interval(vdev, listen_interval);
+}

+ 1 - 13
components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c

@@ -568,19 +568,7 @@ QDF_STATUS ucfg_pmo_config_listen_interval(struct wlan_objmgr_vdev *vdev,
 QDF_STATUS ucfg_pmo_get_listen_interval(struct wlan_objmgr_vdev *vdev,
 					uint32_t *listen_interval)
 {
-	struct pmo_vdev_priv_obj *vdev_ctx;
-
-	if (!vdev)
-		return QDF_STATUS_E_INVAL;
-
-	vdev_ctx = pmo_vdev_get_priv(vdev);
-	if (!vdev_ctx)
-		return QDF_STATUS_E_INVAL;
-
-	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
-	*listen_interval = vdev_ctx->dyn_listen_interval;
-	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
-	return QDF_STATUS_SUCCESS;
+	return pmo_core_get_listen_interval(vdev, listen_interval);
 }
 
 QDF_STATUS ucfg_pmo_config_modulated_dtim(struct wlan_objmgr_vdev *vdev,

+ 6 - 6
components/son/dispatcher/src/son_api.c

@@ -528,8 +528,8 @@ int wlan_son_deliver_opmode(struct wlan_objmgr_vdev *vdev,
 	opmode.num_streams = nss;
 	qdf_mem_copy(opmode.macaddr, addr, QDF_MAC_ADDR_SIZE);
 
-	son_debug("bw %d, nss %d, addr " QDF_FULL_MAC_FMT,
-		  bw, nss, QDF_FULL_MAC_REF(addr));
+	son_debug("bw %d, nss %d, addr " QDF_MAC_ADDR_FMT,
+		  bw, nss, QDF_MAC_ADDR_REF(addr));
 
 	if (!g_son_mlme_deliver_cbs.deliver_opmode) {
 		son_err("invalid deliver opmode cb");
@@ -560,8 +560,8 @@ int wlan_son_deliver_smps(struct wlan_objmgr_vdev *vdev,
 	smps.is_static = is_static;
 	qdf_mem_copy(smps.macaddr, addr, QDF_MAC_ADDR_SIZE);
 
-	son_debug("is_static %d, addr" QDF_FULL_MAC_FMT,
-		  is_static, QDF_FULL_MAC_REF(addr));
+	son_debug("is_static %d, addr" QDF_MAC_ADDR_FMT,
+		  is_static, QDF_MAC_ADDR_REF(addr));
 
 	if (!g_son_mlme_deliver_cbs.deliver_smps) {
 		son_err("invalid deliver smps cb");
@@ -643,9 +643,9 @@ int wlan_son_deliver_rrm_rpt(struct wlan_objmgr_vdev *vdev,
 
 	rrm_info.data.rrm_data.num_meas_rpts = total_bcnrpt_count;
 
-	son_debug("Sta: " QDF_FULL_MAC_FMT
+	son_debug("Sta: " QDF_MAC_ADDR_FMT
 		  "Category %d Action %d Num_Report %d Rptlen %d",
-		  QDF_FULL_MAC_REF(mac_addr),
+		  QDF_MAC_ADDR_REF(mac_addr),
 		  ACTION_CATEGORY_RRM,
 		  RRM_RADIO_MEASURE_RPT,
 		  total_bcnrpt_count,

+ 0 - 11
components/target_if/connection_mgr/src/target_if_cm_roam_offload.c

@@ -518,17 +518,6 @@ target_if_cm_roam_rssi_diff_6ghz(struct wlan_objmgr_vdev *vdev,
 }
 #endif
 
-/**
- * target_if_is_vdev_valid - vdev id is valid or not
- * @vdev_id: vdev id
- *
- * Return: true or false
- */
-static bool target_if_is_vdev_valid(uint8_t vdev_id)
-{
-	return (vdev_id < WLAN_MAX_VDEVS ? true : false);
-}
-
 /**
  * target_if_vdev_set_param() - set per vdev params in fw
  * @wmi_handle: wmi handle

+ 2 - 1
components/target_if/cp_stats/src/target_if_mc_cp_stats.c

@@ -904,6 +904,7 @@ target_if_cp_stats_extract_vdev_extd_stats(struct wmi_unified *wmi_hdl,
 		ev->vdev_extd_stats[i].vdev_id = stats[0].vdev_id;
 		ev->vdev_extd_stats[i].is_mlo_vdev_active =
 						stats[0].is_mlo_vdev_active;
+		ev->vdev_extd_stats[i].vdev_tx_power = stats[i].vdev_tx_power;
 	}
 
 	qdf_mem_free(stats);
@@ -1611,7 +1612,7 @@ static uint32_t get_stats_id(enum stats_req_type type)
 	default:
 		break;
 	case TYPE_CONNECTION_TX_POWER:
-		return WMI_REQUEST_PDEV_STAT;
+		return WMI_REQUEST_PDEV_STAT | WMI_REQUEST_VDEV_EXTD_STAT;
 	case TYPE_CONGESTION_STATS:
 		return WMI_REQUEST_PDEV_STAT | WMI_REQUEST_PDEV_EXTD_STAT;
 	case TYPE_PEER_STATS:

+ 8 - 0
components/target_if/nan/src/target_if_nan.c

@@ -26,6 +26,7 @@
 #include "nan_ucfg_api.h"
 #include "target_if_nan.h"
 #include "wlan_nan_api.h"
+#include "target_if.h"
 #include "wmi_unified_api.h"
 #include "scheduler_api.h"
 #include <wmi_unified.h>
@@ -1164,6 +1165,13 @@ void target_if_nan_set_vdev_feature_config(struct wlan_objmgr_psoc *psoc,
 		return;
 	}
 
+	if (!target_if_is_vdev_valid(vdev_id)) {
+		target_if_err("vdev_id: %d is invalid, reject the req: param id %d",
+			      vdev_id,
+			      wmi_vdev_param_enable_disable_nan_config_features);
+		return;
+	}
+
 	ucfg_get_nan_feature_config(psoc, &nan_features);
 	target_if_debug("vdev_id:%d NAN features:0x%x", vdev_id, nan_features);
 

+ 35 - 0
components/tdls/core/src/wlan_tdls_main.c

@@ -927,6 +927,11 @@ uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
 }
 #endif
 
+bool tdls_check_is_user_tdls_enable(struct tdls_soc_priv_obj *tdls_soc_obj)
+{
+	return tdls_soc_obj->is_user_tdls_enable;
+}
+
 bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
 {
 	struct tdls_vdev_priv_obj *tdls_vdev_obj;
@@ -958,6 +963,11 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
 		goto exit;
 	}
 
+	if (!tdls_check_is_user_tdls_enable(tdls_soc_obj)) {
+		tdls_err("TDLS Disabled from userspace");
+		goto exit;
+	}
+
 	connection_count =
 		policy_mgr_get_connection_count_with_mlo(tdls_soc_obj->soc);
 	sta_count =
@@ -1090,6 +1100,31 @@ set_state:
 		   tdls_soc_obj->tdls_current_mode, tdls_feature_flags);
 }
 
+void tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+			       bool is_user_tdls_enable)
+{
+	QDF_STATUS status;
+	struct tdls_vdev_priv_obj *tdls_vdev_obj;
+	struct tdls_soc_priv_obj *tdls_soc_obj;
+
+	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
+	if (QDF_IS_STATUS_ERROR(status))
+		return;
+
+	status = tdls_get_vdev_objects(vdev, &tdls_vdev_obj, &tdls_soc_obj);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		tdls_err("Failed to get TDLS objects");
+		goto exit;
+	}
+
+	tdls_soc_obj->is_user_tdls_enable = is_user_tdls_enable;
+	tdls_debug("TDLS enable:%d via userspace",
+		   tdls_soc_obj->is_user_tdls_enable);
+
+exit:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
+}
+
 QDF_STATUS
 tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
 {

+ 21 - 2
components/tdls/core/src/wlan_tdls_main.h

@@ -197,6 +197,7 @@ struct tdls_set_state_info {
  * @bss_sta_power_type: bss sta power type
  * @timer_cnt: used for mlo tdls to monitor discovery response
  * @fw_tdls_wideband_capability: bool for tdls wideband fw capability
+ * @is_user_tdls_enable: bool to check whether TDLS enable through userspace
  */
 struct tdls_soc_priv_obj {
 	struct wlan_objmgr_psoc *soc;
@@ -256,6 +257,7 @@ struct tdls_soc_priv_obj {
 #endif
 	qdf_atomic_t timer_cnt;
 	bool fw_tdls_wideband_capability;
+	bool is_user_tdls_enable;
 };
 
 /**
@@ -576,6 +578,15 @@ QDF_STATUS tdls_get_vdev_objects(struct wlan_objmgr_vdev *vdev,
 void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc,
 		      struct wlan_objmgr_vdev *vdev);
 
+/**
+ * tdls_set_user_tdls_enable()- Set the tdls enable from userspace
+ * @vdev: Pointer to vdev object
+ * @is_user_tdls_enable: true if tdls is enable from userspace
+ *
+ * return: NONE
+ */
+void tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+			       bool is_user_tdls_enable);
 /**
  * tdls_set_operation_mode() - set tdls operating mode
  * @tdls_set_mode: tdls mode set params
@@ -602,7 +613,7 @@ QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify);
  * connection tracker
  * @vdev: Pointer to vdev object
  *
- * Return: None
+ * Return: void
  */
 void tdls_process_enable_for_vdev(struct wlan_objmgr_vdev *vdev);
 
@@ -671,7 +682,7 @@ void tdls_notify_decrement_session(struct wlan_objmgr_psoc *psoc);
  * bits set in Ext Cap IE in received Assoc/Re-assoc response
  * from AP.
  *
- * Return: None.
+ * Return: void
  */
 void tdls_send_update_to_fw(struct tdls_vdev_priv_obj *tdls_vdev_obj,
 			    struct tdls_soc_priv_obj *tdls_soc_obj,
@@ -716,6 +727,14 @@ uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
  */
 bool tdls_is_6g_freq_allowed(struct wlan_objmgr_vdev *vdev, qdf_freq_t freq);
 
+/**
+ * tdls_check_is_user_tdls_enable() - Check is tdls enabled or not
+ * @tdls_soc_obj: TDLS soc object
+ *
+ * Return: true or false
+ */
+bool tdls_check_is_user_tdls_enable(struct tdls_soc_priv_obj *tdls_soc_obj);
+
 /**
  * tdls_check_is_tdls_allowed() - check is tdls allowed or not
  * @vdev: vdev object

+ 1 - 1
components/tdls/core/src/wlan_tdls_peer.c

@@ -714,7 +714,7 @@ void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
 							REG_CURRENT_PWR_MODE);
 
 		if (CHANNEL_STATE_INVALID != ch_state &&
-		    CHANNEL_STATE_DFS != ch_state &&
+		    !wlan_reg_is_dfs_for_freq(pdev, ch_freq) &&
 		    !wlan_reg_is_dsrc_freq(ch_freq)) {
 			peer_param->peer_cap.peer_chan[num].ch_freq = ch_freq;
 			if (!wlan_reg_is_6ghz_chan_freq(ch_freq)) {

+ 15 - 0
components/tdls/dispatcher/inc/wlan_tdls_cfg_api.h

@@ -274,6 +274,14 @@ cfg_tdls_set_scan_enable(struct wlan_objmgr_psoc *psoc,
  * This function gets tdls max peer count
  */
 uint16_t cfg_tdls_get_max_peer_count(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * cfg_tdls_get_connected_peer_count() - get tdls connected peer count
+ * @psoc: pointer to psoc object
+ *
+ * This function gets tdls connected peer count
+ */
+uint16_t cfg_tdls_get_connected_peer_count(struct wlan_objmgr_psoc *psoc);
 #else
 static inline QDF_STATUS
 cfg_tdls_get_support_enable(struct wlan_objmgr_psoc *psoc,
@@ -450,5 +458,12 @@ cfg_tdls_get_max_peer_count(struct wlan_objmgr_psoc *psoc)
 {
 	return 0;
 }
+
+static inline uint16_t
+cfg_tdls_get_connected_peer_count(struct wlan_objmgr_psoc *psoc)
+{
+	return 0;
+}
+
 #endif /* FEATURE_WLAN_TDLS */
 #endif /* _WLAN_TDLS_CFG_API_H_ */

+ 33 - 0
components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h

@@ -459,6 +459,27 @@ uint16_t ucfg_get_tdls_conn_peer_count(struct wlan_objmgr_vdev *vdev);
 struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc,
 					    wlan_objmgr_ref_dbgid dbg_id);
 
+/**
+ * ucfg_tdls_check_is_tdls_allowed() - Ucfg api to check is tdls allowed or not
+ * @vdev: vdev object
+ *
+ * Function determines the whether TDLS allowed in the system
+ *
+ * Return: true or false
+ */
+bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ucfg_tdls_set_user_tdls_enable() - ucfg api to set tdls is enable or not
+ * from userspace
+ * @vdev: vdev object
+ * @is_user_tdls_enable: true if tdls is enabled from userspace
+ *
+ * Return: void
+ */
+void ucfg_tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+				    bool is_user_tdls_enable);
+
 #else
 static inline
 bool ucfg_tdls_link_vdev_is_matching(struct wlan_objmgr_vdev *vdev)
@@ -560,6 +581,18 @@ struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc,
 	return NULL;
 }
 
+static inline
+bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
+{
+	return false;
+}
+
+static inline
+void ucfg_tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+				    bool is_user_tdls_enable)
+{
+}
+
 static inline
 void ucfg_tdls_update_fw_11ax_capability(struct wlan_objmgr_psoc *psoc,
 					 bool is_fw_tdls_11ax_capable)

+ 14 - 0
components/tdls/dispatcher/src/wlan_tdls_cfg.c

@@ -413,3 +413,17 @@ cfg_tdls_get_max_peer_count(struct wlan_objmgr_psoc *psoc)
 
 	return soc_obj->max_num_tdls_sta;
 }
+
+uint16_t
+cfg_tdls_get_connected_peer_count(struct wlan_objmgr_psoc *psoc)
+{
+	struct tdls_soc_priv_obj *soc_obj;
+
+	soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
+	if (!soc_obj) {
+		tdls_err("tdls soc null");
+		return 0;
+	}
+
+	return soc_obj->connected_peer_count;
+}

+ 12 - 0
components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c

@@ -289,6 +289,7 @@ static QDF_STATUS tdls_global_init(struct tdls_soc_priv_obj *soc_obj)
 	soc_obj->tdls_nss_transition_mode = TDLS_NSS_TRANSITION_S_UNKNOWN;
 	soc_obj->enable_tdls_connection_tracker = false;
 	soc_obj->tdls_external_peer_count = 0;
+	soc_obj->is_user_tdls_enable = true;
 
 	qdf_spinlock_create(&soc_obj->tdls_ct_spinlock);
 	tdls_wow_init(soc_obj);
@@ -1287,3 +1288,14 @@ struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc,
 {
 	return tdls_get_vdev(psoc, dbg_id);
 }
+
+bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
+{
+	return tdls_check_is_tdls_allowed(vdev);
+}
+
+void ucfg_tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+				    bool is_user_tdls_enable)
+{
+	return tdls_set_user_tdls_enable(vdev, is_user_tdls_enable);
+}

+ 48 - 0
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c

@@ -49,6 +49,7 @@
 #include "wlan_mlo_mgr_sta.h"
 #include "wlan_mlme_api.h"
 #include "wlan_policy_mgr_api.h"
+#include "wlan_mlo_mgr_link_switch.h"
 
 
 #ifdef WLAN_FEATURE_SAE
@@ -2193,6 +2194,47 @@ cm_update_rso_freq_list(struct rso_config *rso_cfg,
 	}
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+static void cm_update_rso_freq_list_from_partner_link(
+				struct wlan_objmgr_vdev *vdev,
+				struct wlan_mlme_psoc_ext_obj *mlme_obj,
+				struct wlan_roam_scan_channel_list *chan_info)
+{
+	struct mlo_link_info *mlo_link_info;
+	uint8_t link_info_iter = 0;
+	qdf_freq_t chan_freq;
+
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
+		return;
+
+	mlo_link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[0];
+	for (link_info_iter = 0; link_info_iter < WLAN_MAX_ML_BSS_LINKS;
+	     link_info_iter++, mlo_link_info++) {
+		if (qdf_is_macaddr_zero(&mlo_link_info->ap_link_addr) ||
+		    mlo_link_info->link_id == WLAN_INVALID_LINK_ID)
+			continue;
+		chan_freq = mlo_link_info->link_chan_info->ch_freq;
+		if (wlan_is_channel_present_in_list(chan_info->chan_freq_list,
+						    chan_info->chan_count,
+						    chan_freq))
+			continue;
+		chan_info->chan_freq_list[chan_info->chan_count++] =
+								chan_freq;
+		mlme_debug("link_id: %d added freq:%d ",
+			   mlo_link_info->link_id,
+			   mlo_link_info->link_chan_info->ch_freq);
+	}
+}
+
+#else
+static void cm_update_rso_freq_list_from_partner_link(
+			struct wlan_objmgr_vdev *vdev,
+			struct wlan_mlme_psoc_ext_obj *mlme_obj,
+			struct wlan_roam_scan_channel_list *chan_info)
+{
+}
+#endif
+
 static void
 cm_fill_rso_channel_list(struct wlan_objmgr_psoc *psoc,
 			 struct wlan_objmgr_vdev *vdev,
@@ -2243,6 +2285,12 @@ cm_fill_rso_channel_list(struct wlan_objmgr_psoc *psoc,
 			cm_add_ch_lst_from_roam_scan_list(vdev, mlme_obj,
 							  chan_info, rso_cfg);
 
+			/*
+			 * update channel list for non assoc link
+			 */
+			cm_update_rso_freq_list_from_partner_link(
+						vdev, mlme_obj, chan_info);
+
 			/*
 			 * update the roam channel list on the top of entries
 			 * present in the scan db which gets stored in the rso

+ 41 - 12
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c

@@ -43,6 +43,8 @@
 #include "wlan_t2lm_api.h"
 #include "wlan_mlo_t2lm.h"
 #include "wlan_mlo_link_force.h"
+#include "wlan_mlo_mgr_link_switch.h"
+#include "wlan_dp_api.h"
 
 #ifdef WLAN_FEATURE_FILS_SK
 void cm_update_hlp_info(struct wlan_objmgr_vdev *vdev,
@@ -1053,7 +1055,9 @@ QDF_STATUS cm_connect_start_ind(struct wlan_objmgr_vdev *vdev,
 		mlme_err("vdev_id: %d psoc not found", req->vdev_id);
 		return QDF_STATUS_E_INVAL;
 	}
-	if (policy_mgr_is_sta_mon_concurrency(psoc))
+
+	if (!wlan_dp_is_local_pkt_capture_enabled(psoc) &&
+	    policy_mgr_is_sta_mon_concurrency(psoc))
 		return QDF_STATUS_E_NOSUPPORT;
 
 	rso_cfg = wlan_cm_get_rso_config(vdev);
@@ -1177,12 +1181,42 @@ cm_get_ml_partner_info(struct scan_cache_entry *scan_entry,
 
 	partner_info->num_partner_links = j;
 	mlme_debug("sta and ap integrate link num: %d", j);
-
 	wlan_objmgr_psoc_release_ref(psoc, WLAN_MLME_CM_ID);
 
 	return QDF_STATUS_SUCCESS;
 }
 
+static void cm_update_mlo_mgr_info(struct wlan_objmgr_vdev *vdev,
+				   struct cm_vdev_join_req *join_req)
+{
+	struct qdf_mac_addr link_addr;
+	uint8_t link_id, i;
+	struct wlan_channel channel = {0};
+	struct mlo_partner_info *partner_info;
+
+	if (wlan_vdev_mlme_is_mlo_link_vdev(vdev))
+		return;
+
+	link_id = join_req->entry->ml_info.self_link_id;
+	qdf_mem_copy(link_addr.bytes, join_req->entry->bssid.bytes,
+		     QDF_MAC_ADDR_SIZE);
+
+	/* Reset Previous info if any and update the AP self link info */
+	mlo_mgr_reset_ap_link_info(vdev);
+	mlo_mgr_update_ap_link_info(vdev, link_id, link_addr.bytes, channel);
+
+	partner_info = &join_req->partner_info;
+	for (i = 0; i < partner_info->num_partner_links; i++) {
+		link_id = partner_info->partner_link_info[i].link_id;
+		qdf_mem_copy(link_addr.bytes,
+			     partner_info->partner_link_info[i].link_addr.bytes,
+			     QDF_MAC_ADDR_SIZE);
+		/* Updating AP partner link info */
+		mlo_mgr_update_ap_link_info(vdev, link_id, link_addr.bytes,
+					    channel);
+	}
+}
+
 static void
 cm_copy_join_req_info_from_cm_connect_req(struct wlan_objmgr_vdev *vdev,
 					  struct cm_vdev_join_req *join_req,
@@ -1200,6 +1234,8 @@ cm_copy_join_req_info_from_cm_connect_req(struct wlan_objmgr_vdev *vdev,
 	mlme_debug("Num of partner links %d assoc_link_id:%d",
 		   join_req->partner_info.num_partner_links,
 		   join_req->assoc_link_id);
+
+	cm_update_mlo_mgr_info(vdev, join_req);
 }
 #else
 static inline void
@@ -1609,12 +1645,6 @@ cm_install_link_vdev_keys(struct wlan_objmgr_vdev *vdev)
 		return;
 	}
 
-	if (!mlo_get_keys_saved(vdev, wlan_peer_get_macaddr(peer))) {
-		mlo_debug("keys are not saved for vdev_id %d", vdev_id);
-		wlan_objmgr_peer_release_ref(peer, WLAN_MLME_CM_ID);
-		return;
-	}
-
 	for (i = 0; i < max_key_index; i++) {
 		crypto_key = wlan_crypto_get_key(vdev, i);
 		if (!crypto_key)
@@ -1626,9 +1656,7 @@ cm_install_link_vdev_keys(struct wlan_objmgr_vdev *vdev)
 		mlme_cm_osif_send_keys(vdev, i, pairwise,
 				       crypto_key->cipher_type);
 	}
-	mlo_set_keys_saved(vdev,
-			   (struct qdf_mac_addr *)wlan_peer_get_macaddr(peer),
-			   false);
+
 	wlan_objmgr_peer_release_ref(peer, WLAN_MLME_CM_ID);
 }
 
@@ -1668,7 +1696,8 @@ cm_connect_complete_ind(struct wlan_objmgr_vdev *vdev,
 			rsp->freq);
 
 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
-		if (policy_mgr_ml_link_vdev_need_to_be_disabled(psoc, vdev))
+		if (policy_mgr_ml_link_vdev_need_to_be_disabled(psoc, vdev,
+								false))
 			policy_mgr_move_vdev_from_connection_to_disabled_tbl(
 								psoc, vdev_id);
 		else

+ 5 - 2
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_disconnect.c

@@ -84,7 +84,9 @@ QDF_STATUS cm_disconnect_start_ind(struct wlan_objmgr_vdev *vdev,
 		cm_csr_set_ss_none(req->vdev_id);
 	}
 
-	user_disconnect = req->source == CM_OSIF_DISCONNECT ? true : false;
+	user_disconnect =
+		(req->source == CM_OSIF_DISCONNECT ||
+		 req->source == CM_MLO_LINK_SWITCH_DISCONNECT) ? true : false;
 	if (user_disconnect) {
 		wlan_p2p_cleanup_roc_by_vdev(vdev, false);
 		wlan_tdls_notify_sta_disconnect(req->vdev_id, false,
@@ -92,7 +94,8 @@ QDF_STATUS cm_disconnect_start_ind(struct wlan_objmgr_vdev *vdev,
 	}
 	cm_abort_connect_request_timers(vdev);
 
-	if (req->source != CM_MLO_ROAM_INTERNAL_DISCONNECT) {
+	if (req->source != CM_MLO_ROAM_INTERNAL_DISCONNECT &&
+	    req->source != CM_MLO_LINK_SWITCH_DISCONNECT) {
 		mlme_debug("Free copied reassoc rsp");
 		mlo_roam_free_copied_reassoc_rsp(vdev);
 	}

+ 2 - 1
components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c

@@ -4248,7 +4248,8 @@ cm_roam_stats_event_handler(struct wlan_objmgr_psoc *psoc,
 			    ROAM_TRIGGER_REASON_BTM) {
 				cm_roam_handle_btm_stats(psoc, stats_info, i,
 							 &rem_tlv);
-				continue;
+				if (!stats_info->trigger[i].common_roam)
+					continue;
 			}
 
 			cm_roam_stats_print_trigger_info(

+ 61 - 1
components/umac/mlme/mlo_mgr/inc/wlan_mlo_link_force.h

@@ -53,6 +53,7 @@ enum ml_nlink_change_event_type {
 
 /**
  * struct ml_nlink_change_event - connection change event data struct
+ * @evt: event parameters
  */
 struct ml_nlink_change_event {
 };
@@ -73,13 +74,14 @@ static inline const char *force_mode_to_string(uint32_t mode)
 };
 
 #define ml_nlink_dump_force_state(_force_state, format, args...) \
-	mlo_debug("inactive 0x%x active 0x%x inact num %d 0x%x act num %d 0x%x "format, \
+	mlo_debug("inactive 0x%x active 0x%x inact num %d 0x%x act num %d 0x%x dyn 0x%x"format, \
 			 (_force_state)->force_inactive_bitmap, \
 			 (_force_state)->force_active_bitmap, \
 			 (_force_state)->force_inactive_num, \
 			 (_force_state)->force_inactive_num_bitmap, \
 			 (_force_state)->force_active_num, \
 			 (_force_state)->force_active_num_bitmap, \
+			 (_force_state)->curr_dynamic_inactive_bitmap, \
 			 ##args);
 
 static inline const char *link_evt_to_string(uint32_t evt)
@@ -165,6 +167,20 @@ ml_nlink_convert_vdev_bitmap_to_linkid_bitmap(
 				uint32_t *link_bitmap,
 				uint32_t *associated_bitmap);
 
+/**
+ * ml_nlink_convert_link_bitmap_to_ids() - convert link bitmap
+ * to link ids
+ * @link_bitmap: link bitmap
+ * @link_id_sz: array size of link_ids
+ * @link_ids: link id array
+ *
+ * Return: number of link ids
+ */
+uint32_t
+ml_nlink_convert_link_bitmap_to_ids(uint32_t link_bitmap,
+				    uint8_t link_id_sz,
+				    uint8_t *link_ids);
+
 /**
  * enum set_curr_control - control flag to update current force bitmap
  * @LINK_OVERWRITE: use bitmap to overwrite existing force bitmap
@@ -246,6 +262,36 @@ ml_nlink_set_curr_force_inactive_num_state(struct wlan_objmgr_psoc *psoc,
 					   uint8_t link_num,
 					   uint16_t link_bitmap);
 
+/**
+ * ml_nlink_set_dynamic_inactive_links() - set link dynamic inactive
+ * link bitmap
+ * @psoc: psoc object
+ * @vdev: vdev object
+ * @dynamic_link_bitmap: dynamic inactive bitmap
+ *
+ * Return: None
+ */
+void
+ml_nlink_set_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc,
+				    struct wlan_objmgr_vdev *vdev,
+				    uint16_t dynamic_link_bitmap);
+
+/**
+ * ml_nlink_get_dynamic_inactive_links() - get link dynamic inactive
+ * link bitmap
+ * @psoc: psoc object
+ * @vdev: vdev object
+ * @dynamic_link_bitmap: dynamic inactive bitmap
+ * @force_link_bitmap: forced inactive bitmap
+ *
+ * Return: None
+ */
+void
+ml_nlink_get_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc,
+				    struct wlan_objmgr_vdev *vdev,
+				    uint16_t *dynamic_link_bitmap,
+				    uint16_t *force_link_bitmap);
+
 /**
  * ml_nlink_get_curr_force_state() - get link force state
  * @psoc: psoc object
@@ -269,6 +315,14 @@ ml_nlink_get_curr_force_state(struct wlan_objmgr_psoc *psoc,
 void
 ml_nlink_clr_force_state(struct wlan_objmgr_psoc *psoc,
 			 struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ml_is_nlink_service_supported() - support nlink or not
+ * @psoc: psoc object
+ *
+ * Return: true if supported
+ */
+bool ml_is_nlink_service_supported(struct wlan_objmgr_psoc *psoc);
 #else
 static inline QDF_STATUS
 ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
@@ -278,5 +332,11 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline bool
+ml_is_nlink_service_supported(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
 #endif
 #endif

+ 340 - 36
components/umac/mlme/mlo_mgr/src/wlan_mlo_link_force.c

@@ -24,6 +24,7 @@
 #include "wlan_cm_roam_api.h"
 #include "wlan_mlo_mgr_roam.h"
 #include "wlan_mlme_main.h"
+#include "wlan_mlo_mgr_link_switch.h"
 
 void
 ml_nlink_convert_linkid_bitmap_to_vdev_bitmap(
@@ -333,6 +334,50 @@ ml_nlink_set_curr_force_inactive_num_state(struct wlan_objmgr_psoc *psoc,
 	mlo_dev_lock_release(mlo_dev_ctx);
 }
 
+void
+ml_nlink_set_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc,
+				    struct wlan_objmgr_vdev *vdev,
+				    uint16_t dynamic_link_bitmap)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct ml_link_force_state *force_state;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state;
+	force_state->curr_dynamic_inactive_bitmap = dynamic_link_bitmap;
+	ml_nlink_dump_force_state(force_state, ":dynamic bitmap 0x%x",
+				  dynamic_link_bitmap);
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
+void
+ml_nlink_get_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc,
+				    struct wlan_objmgr_vdev *vdev,
+				    uint16_t *dynamic_link_bitmap,
+				    uint16_t *force_link_bitmap)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct ml_link_force_state *force_state;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state;
+	*dynamic_link_bitmap = force_state->curr_dynamic_inactive_bitmap;
+	*force_link_bitmap = force_state->force_inactive_bitmap;
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
 /**
  * ml_nlink_get_affect_ml_sta() - Get ML STA whose link can be
  * force inactive
@@ -376,7 +421,7 @@ ml_nlink_get_affect_ml_sta(struct wlan_objmgr_psoc *psoc)
 	return vdev;
 }
 
-static bool ml_is_nlink_service_supported(void)
+bool ml_is_nlink_service_supported(struct wlan_objmgr_psoc *psoc)
 {
 	/*todo: check WMI_SERVICE_N_LINK_MLO_SUPPORT service bit */
 	return false;
@@ -389,6 +434,79 @@ static bool ml_is_nlink_service_supported(void)
 /* Exclude QUITE link */
 #define NLINK_EXCLUDE_QUIET_LINK	0x04
 
+static void
+ml_nlink_get_standby_link_info(struct wlan_objmgr_psoc *psoc,
+			       struct wlan_objmgr_vdev *vdev,
+			       uint8_t flag,
+			       uint8_t ml_num_link_sz,
+			       struct ml_link_info *ml_link_info,
+			       qdf_freq_t *ml_freq_lst,
+			       uint8_t *ml_vdev_lst,
+			       uint8_t *ml_linkid_lst,
+			       uint8_t *ml_num_link,
+			       uint32_t *ml_link_bitmap)
+{
+	struct mlo_link_info *link_info;
+	uint8_t link_info_iter;
+
+	link_info = mlo_mgr_get_ap_link(vdev);
+	if (!link_info)
+		return;
+
+	for (link_info_iter = 0; link_info_iter < WLAN_MAX_ML_BSS_LINKS;
+	     link_info_iter++) {
+		if (qdf_is_macaddr_zero(&link_info->ap_link_addr))
+			break;
+
+		if (link_info->vdev_id == WLAN_INVALID_VDEV_ID) {
+			if (*ml_num_link >= ml_num_link_sz) {
+				mlo_debug("link lst overflow");
+				break;
+			}
+			if (!link_info->link_chan_info->ch_freq) {
+				mlo_debug("link freq 0!");
+				break;
+			}
+			if (*ml_link_bitmap & (1 << link_info->link_id)) {
+				mlo_debug("unexpected standby linkid %d",
+					  link_info->link_id);
+				break;
+			}
+			if (link_info->link_id >= MAX_MLO_LINK_ID) {
+				mlo_debug("invalid standby link id %d",
+					  link_info->link_id);
+				break;
+			}
+
+			if ((flag & NLINK_EXCLUDE_REMOVED_LINK) &&
+			    link_info->link_status_flags) {
+				mlo_debug("standby link %d is removed",
+					  link_info->link_id);
+				continue;
+			}
+			if ((flag & NLINK_INCLUDE_REMOVED_LINK_ONLY) &&
+			    !link_info->link_status_flags) {
+				continue;
+			}
+
+			ml_freq_lst[*ml_num_link] =
+				link_info->link_chan_info->ch_freq;
+			ml_vdev_lst[*ml_num_link] = WLAN_INVALID_VDEV_ID;
+			ml_linkid_lst[*ml_num_link] = link_info->link_id;
+			*ml_link_bitmap |= 1 << link_info->link_id;
+
+			mlo_debug("vdev %d link %d freq %d bitmap 0x%x flag 0x%x",
+				  ml_vdev_lst[*ml_num_link],
+				  ml_linkid_lst[*ml_num_link],
+				  ml_freq_lst[*ml_num_link],
+				  *ml_link_bitmap, flag);
+			(*ml_num_link)++;
+		}
+
+		link_info++;
+	}
+}
+
 /**
  * ml_nlink_get_link_info() - Get ML STA link info
  * @psoc: PSOC object information
@@ -422,6 +540,7 @@ static void ml_nlink_get_link_info(struct wlan_objmgr_psoc *psoc,
 	uint32_t link_bitmap = 0;
 	uint16_t link_id;
 	uint8_t vdev_id;
+	bool connected = false;
 
 	*ml_num_link = 0;
 	*ml_link_bitmap = 0;
@@ -441,7 +560,6 @@ static void ml_nlink_get_link_info(struct wlan_objmgr_psoc *psoc,
 
 	link_bitmap = 0;
 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
-		/*todo: add standby link */
 		if (!mlo_dev_ctx->wlan_vdev_list[i])
 			continue;
 		if (!qdf_test_bit(i, sta_ctx->wlan_connected_links))
@@ -454,6 +572,7 @@ static void ml_nlink_get_link_info(struct wlan_objmgr_psoc *psoc,
 					mlo_dev_ctx->wlan_vdev_list[i]));
 			continue;
 		}
+		connected = true;
 
 		vdev_id = wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]);
 		link_id = wlan_vdev_get_link_id(
@@ -496,6 +615,17 @@ static void ml_nlink_get_link_info(struct wlan_objmgr_psoc *psoc,
 			  ml_freq_lst[num_link], link_bitmap, flag);
 		num_link++;
 	}
+	/* Add standby link only if mlo sta is connected */
+	if (connected)
+		ml_nlink_get_standby_link_info(psoc, vdev, flag,
+					       ml_num_link_sz,
+					       ml_link_info,
+					       ml_freq_lst,
+					       ml_vdev_lst,
+					       ml_linkid_lst,
+					       &num_link,
+					       &link_bitmap);
+
 	mlo_dev_lock_release(mlo_dev_ctx);
 	*ml_num_link = num_link;
 	*ml_link_bitmap = link_bitmap;
@@ -543,6 +673,15 @@ convert_link_bitmap_to_link_ids(uint32_t link_bitmap,
 	return i;
 }
 
+uint32_t
+ml_nlink_convert_link_bitmap_to_ids(uint32_t link_bitmap,
+				    uint8_t link_id_sz,
+				    uint8_t *link_ids)
+{
+	return convert_link_bitmap_to_link_ids(link_bitmap, link_id_sz,
+					       link_ids);
+}
+
 /**
  * ml_nlink_handle_mcc_links() - Check force inactive needed
  * if ML STA links are in MCC channels
@@ -984,7 +1123,7 @@ ml_nlink_handle_legacy_intf_3_ports(struct wlan_objmgr_psoc *psoc,
 		return;
 
 	for (i = 0; i < ml_num_link; i++) {
-		if (ml_vdev_lst[i] == 0xff) {
+		if (ml_vdev_lst[i] == WLAN_INVALID_VDEV_ID) {
 			/*standby link will be handled later. */
 			continue;
 		}
@@ -1005,20 +1144,57 @@ ml_nlink_handle_legacy_intf_3_ports(struct wlan_objmgr_psoc *psoc,
 			  legacy_intf_freq1);
 		return;
 	}
-	/* handle standby link */
+
+	if (force_inactive_link_bitmap)
+		force_cmd->force_inactive_bitmap = force_inactive_link_bitmap;
+}
+
+static void
+ml_nlink_handle_standby_link_3_ports(
+		struct wlan_objmgr_psoc *psoc,
+		struct wlan_objmgr_vdev *vdev,
+		struct ml_link_force_state *force_cmd,
+		uint8_t num_legacy_vdev,
+		uint8_t *vdev_lst,
+		qdf_freq_t *freq_lst,
+		enum policy_mgr_con_mode *mode_lst)
+{
+	uint8_t ml_num_link = 0;
+	uint32_t ml_link_bitmap = 0;
+	uint32_t force_inactive_link_bitmap = 0;
+	uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint8_t i, j;
+
+	if (num_legacy_vdev < 2)
+		return;
+
+	ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_REMOVED_LINK,
+			       QDF_ARRAY_SIZE(ml_linkid_lst),
+			       ml_link_info, ml_freq_lst, ml_vdev_lst,
+			       ml_linkid_lst, &ml_num_link,
+			       &ml_link_bitmap);
+	if (ml_num_link < 2)
+		return;
 	for (i = 0; i < ml_num_link; i++) {
-		if (ml_vdev_lst[i] == 0xff) {
-			/*standby link will be forced inactive if mcc with
-			 * legacy sta
-			 */
-			if (ml_freq_lst[i] != legacy_intf_freq1)
+		if (ml_vdev_lst[i] != WLAN_INVALID_VDEV_ID)
+			continue;
+		/* standby link will be forced inactive if mcc with
+		 * legacy interface
+		 */
+		for (j = 0; j < num_legacy_vdev; j++) {
+			if (ml_freq_lst[i] != freq_lst[j] &&
+			    policy_mgr_are_2_freq_on_same_mac(
+					psoc, ml_freq_lst[i], freq_lst[j]))
 				force_inactive_link_bitmap |=
 						1 << ml_linkid_lst[i];
 		}
 	}
 
 	if (force_inactive_link_bitmap)
-		force_cmd->force_inactive_bitmap = force_inactive_link_bitmap;
+		force_cmd->force_inactive_bitmap |= force_inactive_link_bitmap;
 }
 
 /**
@@ -1117,7 +1293,7 @@ ml_nlink_handle_legacy_intf(struct wlan_objmgr_psoc *psoc,
 	case PM_P2P_GO_MODE:
 		if (!policy_mgr_is_vdev_high_tput_or_low_latency(
 					psoc, vdev_lst[0]))
-			return;
+			break;
 		fallthrough;
 	case PM_STA_MODE:
 		ml_nlink_handle_legacy_intf_3_ports(
@@ -1133,9 +1309,114 @@ ml_nlink_handle_legacy_intf(struct wlan_objmgr_psoc *psoc,
 		mlo_debug("unexpected legacy intf mode %d", mode_lst[0]);
 		return;
 	}
+	ml_nlink_handle_standby_link_3_ports(psoc, vdev, force_cmd,
+					     num_legacy_vdev,
+					     vdev_lst,
+					     freq_lst,
+					     mode_lst);
 	ml_nlink_dump_force_state(force_cmd, "");
 }
 
+/**
+ * ml_nlink_handle_dynamic_inactive() - Handle dynamic force inactive num
+ * with legacy SAP
+ * @psoc: PSOC object information
+ * @vdev: vdev object
+ * @curr: current force command state
+ * @new: new force command
+ *
+ * If ML STA 2 or 3 links are present and force inactive num = 1 with dynamic
+ * flag enabled for some reason, FW will report the current inactive links,
+ * host will select one and save to curr_dynamic_inactive_bitmap.
+ * If SAP starting on channel which is same mac as links in
+ * the curr_dynamic_inactive_bitmap, host will force inactive the links in
+ * curr_dynamic_inactive_bitmap to avoid FW link switch between the dynamic
+ * inactive links.
+ *
+ * Return: void
+ */
+static void
+ml_nlink_handle_dynamic_inactive(struct wlan_objmgr_psoc *psoc,
+				 struct wlan_objmgr_vdev *vdev,
+				 struct ml_link_force_state *curr,
+				 struct ml_link_force_state *new)
+{
+	uint8_t vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	qdf_freq_t freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	enum policy_mgr_con_mode mode_lst[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint8_t num;
+	uint8_t ml_num_link = 0;
+	uint32_t ml_link_bitmap;
+	uint32_t force_inactive_link_bitmap = 0;
+	uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint32_t i, j;
+
+	/* If force inactive num wasn't sent to fw, no need to handle
+	 * dynamic inactive links.
+	 */
+	if (!curr->force_inactive_num ||
+	    !curr->force_inactive_num_bitmap ||
+	    !curr->curr_dynamic_inactive_bitmap)
+		return;
+	if (curr->force_inactive_num != new->force_inactive_num ||
+	    curr->force_inactive_num_bitmap !=
+				new->force_inactive_num_bitmap)
+		return;
+	/* If links have been forced inactive by bitmap, no need to force
+	 * again.
+	 */
+	if ((new->force_inactive_bitmap &
+	     curr->curr_dynamic_inactive_bitmap) ==
+	    curr->curr_dynamic_inactive_bitmap)
+		return;
+
+	num = policy_mgr_get_legacy_conn_info(
+					psoc, vdev_lst,
+					freq_lst, mode_lst,
+					QDF_ARRAY_SIZE(vdev_lst));
+	if (!num)
+		return;
+	ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_REMOVED_LINK,
+			       QDF_ARRAY_SIZE(ml_linkid_lst),
+			       ml_link_info, ml_freq_lst, ml_vdev_lst,
+			       ml_linkid_lst, &ml_num_link,
+			       &ml_link_bitmap);
+	if (ml_num_link < 2)
+		return;
+	for (i = 0; i < ml_num_link; i++) {
+		if (!((1 << ml_linkid_lst[i]) &
+		      curr->curr_dynamic_inactive_bitmap))
+			continue;
+		for (j = 0; j < num; j++) {
+			if (mode_lst[j] != PM_SAP_MODE)
+				continue;
+			if (policy_mgr_2_freq_always_on_same_mac(
+				psoc, freq_lst[j], ml_freq_lst[i])) {
+				force_inactive_link_bitmap |=
+					1 << ml_linkid_lst[i];
+				mlo_debug("force dynamic inactive link id %d freq %d for sap freq %d",
+					  ml_linkid_lst[i], ml_freq_lst[i],
+					  freq_lst[j]);
+			} else if (num > 1 &&
+				   policy_mgr_are_2_freq_on_same_mac(
+					psoc, freq_lst[j], ml_freq_lst[i])) {
+				force_inactive_link_bitmap |=
+					1 << ml_linkid_lst[i];
+				mlo_debug("force dynamic inactive link id %d freq %d for sap freq %d",
+					  ml_linkid_lst[i], ml_freq_lst[i],
+					  freq_lst[j]);
+			}
+		}
+	}
+	if (force_inactive_link_bitmap) {
+		new->force_inactive_bitmap |= force_inactive_link_bitmap;
+		ml_nlink_dump_force_state(new, "");
+	}
+}
+
 /**
  * ml_nlink_sta_inactivity_allowed_with_quiet() - Check force inactive allowed
  * for links in bitmap
@@ -1355,7 +1636,7 @@ ml_nlink_update_force_inactive_num(struct wlan_objmgr_psoc *psoc,
 					new->force_inactive_num,
 					new->force_inactive_num_bitmap,
 					0,
-					0);
+					link_ctrl_f_dynamic_force_link_num);
 	}
 
 	return status;
@@ -1386,6 +1667,8 @@ ml_nlink_update_force_active_num(struct wlan_objmgr_psoc *psoc,
  * with concurrency internal function
  * @psoc: PSOC object information
  * @reason: reason code of trigger force mode change.
+ * @evt: event type
+ * @data: event data
  *
  * This API handle link force for connected ML STA.
  * At present we only support one ML STA. so ml_nlink_get_affect_ml_sta
@@ -1398,11 +1681,13 @@ ml_nlink_update_force_active_num(struct wlan_objmgr_psoc *psoc,
  * record after get successful respone from target.
  *
  * Return: QDF_STATUS_SUCCESS if no new command updated to target.
- *         QDF_STATUS_E_PENDING if new command is sent to target.
- *         otherwise QDF_STATUS error code
+ *	   QDF_STATUS_E_PENDING if new command is sent to target.
+ *	   otherwise QDF_STATUS error code
  */
 static QDF_STATUS ml_nlink_state_change(struct wlan_objmgr_psoc *psoc,
-					enum mlo_link_force_reason reason)
+					enum mlo_link_force_reason reason,
+					enum ml_nlink_change_event_type evt,
+					struct ml_nlink_change_event *data)
 {
 	struct ml_link_force_state force_state = {0};
 	struct ml_link_force_state legacy_intf_force_state = {0};
@@ -1446,6 +1731,9 @@ static QDF_STATUS ml_nlink_state_change(struct wlan_objmgr_psoc *psoc,
 		legacy_intf_force_state.force_inactive_num_bitmap;
 	}
 
+	ml_nlink_handle_dynamic_inactive(psoc, vdev, &curr_force_state,
+					 &force_state);
+
 	status = ml_nlink_update_no_force_for_all(psoc, vdev,
 						  &curr_force_state,
 						  &force_state,
@@ -1501,16 +1789,21 @@ end:
  * @psoc: PSOC object information
  * @vdev: ml sta vdev object
  * @reason: reason code of trigger force mode change.
+ * @evt: event type
+ * @data: event data
  *
- * Return: void
+ * Return: QDF_STATUS_SUCCESS if successfully
  */
-static void
+static QDF_STATUS
 ml_nlink_state_change_handler(struct wlan_objmgr_psoc *psoc,
 			      struct wlan_objmgr_vdev *vdev,
-			      enum mlo_link_force_reason reason)
+			      enum mlo_link_force_reason reason,
+			      enum ml_nlink_change_event_type evt,
+			      struct ml_nlink_change_event *data)
 {
 	enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(vdev);
 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	/* If WMI_SERVICE_N_LINK_MLO_SUPPORT = 381 is enabled,
 	 * indicate FW support N MLO link & vdev re-purpose between links,
@@ -1519,14 +1812,16 @@ ml_nlink_state_change_handler(struct wlan_objmgr_psoc *psoc,
 	 * Otherwise, use legacy policy mgr API to inactive/active based
 	 * on vdev id bitmap.
 	 */
-	if (ml_is_nlink_service_supported())
-		ml_nlink_state_change(psoc, reason);
+	if (ml_is_nlink_service_supported(psoc))
+		status = ml_nlink_state_change(psoc, reason, evt, data);
 	else if (reason == MLO_LINK_FORCE_REASON_CONNECT)
 		policy_mgr_handle_ml_sta_links_on_vdev_up_csa(psoc, mode,
 							      vdev_id);
 	else
 		policy_mgr_handle_ml_sta_links_on_vdev_down(psoc, mode,
 							    vdev_id);
+
+	return status;
 }
 
 QDF_STATUS
@@ -1537,8 +1832,10 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 {
 	struct wlan_objmgr_vdev *vdev;
 	enum QDF_OPMODE mode;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
-	mlo_debug("vdev %d %s", vdev_id, link_evt_to_string(evt));
+	mlo_debug("vdev %d %s(%d)", vdev_id, link_evt_to_string(evt),
+		  evt);
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
 						    WLAN_MLO_MGR_ID);
 	if (!vdev) {
@@ -1552,37 +1849,43 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 		/* todo: allow concurrenct check */
 		break;
 	case ml_nlink_link_switch_completion_evt:
-		ml_nlink_state_change_handler(
-			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT);
+		status = ml_nlink_state_change_handler(
+			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT,
+			evt, data);
 		break;
 	case ml_nlink_roam_sync_start_evt:
 		ml_nlink_clr_force_state(psoc, vdev);
 		break;
 	case ml_nlink_roam_sync_completion_evt:
-		ml_nlink_state_change_handler(
-			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT);
+		status = ml_nlink_state_change_handler(
+			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT,
+			evt, data);
 		break;
 	case ml_nlink_connect_start_evt:
 		ml_nlink_clr_force_state(psoc, vdev);
 		break;
 	case ml_nlink_connect_completion_evt:
-		ml_nlink_state_change_handler(
-			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT);
+		status = ml_nlink_state_change_handler(
+			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT,
+			evt, data);
 		break;
 	case ml_nlink_disconnect_start_evt:
 		ml_nlink_clr_force_state(psoc, vdev);
 		break;
 	case ml_nlink_disconnect_completion_evt:
-		ml_nlink_state_change_handler(
-			psoc, vdev, MLO_LINK_FORCE_REASON_DISCONNECT);
+		status = ml_nlink_state_change_handler(
+			psoc, vdev, MLO_LINK_FORCE_REASON_DISCONNECT,
+			evt, data);
 		break;
 	case ml_nlink_ap_started_evt:
-		ml_nlink_state_change_handler(
-			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT);
+		status = ml_nlink_state_change_handler(
+			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT,
+			evt, data);
 		break;
 	case ml_nlink_ap_stopped_evt:
-		ml_nlink_state_change_handler(
-			psoc, vdev, MLO_LINK_FORCE_REASON_DISCONNECT);
+		status = ml_nlink_state_change_handler(
+			psoc, vdev, MLO_LINK_FORCE_REASON_DISCONNECT,
+			evt, data);
 		break;
 	case ml_nlink_connection_updated_evt:
 		if (mode == QDF_STA_MODE &&
@@ -1591,8 +1894,9 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 			mlo_debug("vdev id %d in roam sync", vdev_id);
 			break;
 		}
-		ml_nlink_state_change_handler(
-			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT);
+		status = ml_nlink_state_change_handler(
+			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT,
+			evt, data);
 		break;
 	default:
 		break;
@@ -1601,5 +1905,5 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 	if (vdev)
 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
 
-	return QDF_STATUS_SUCCESS;
+	return status;
 }

+ 2 - 1
components/wmi/src/wmi_unified_roam_tlv.c

@@ -2260,7 +2260,8 @@ wmi_fill_roam_mlo_info(wmi_unified_t wmi_handle,
 						   link->link_addr.bytes);
 			wmi_debug("link_id: %u vdev_id: %u flags: 0x%x addr:" QDF_MAC_ADDR_FMT,
 				  link->link_id, link->vdev_id,
-				  link->flags, link->link_addr.bytes);
+				  link->flags,
+				  QDF_MAC_ADDR_REF(link->link_addr.bytes));
 			wmi_debug("channel: %u mhz center_freq1: %u center_freq2: %u",
 				  link->channel.mhz,
 				  link->channel.band_center_freq1,

+ 52 - 2
configs/config_to_feature.h

@@ -2821,8 +2821,6 @@
 #define WLAN_OPEN_SOURCE (1)
 #endif
 
-#define MULTI_IF_NAME "kiwi_v2"
-
 #ifdef CONFIG_DP_MULTIPASS_SUPPORT
 #define QCA_MULTIPASS_SUPPORT (1)
 #define WLAN_REPEATER_NOT_SUPPORTED (1)
@@ -2845,4 +2843,56 @@
 #define NL80211_EXT_FEATURE_PUNCT_SUPPORT (1)
 #endif
 
+#ifdef CONFIG_DP_MLO_LINK_STATS_SUPPORT
+#define DP_MLO_LINK_STATS_SUPPORT (1)
+#endif
+
+#ifdef CONFIG_MULTI_IF_NAME
+#define MULTI_IF_NAME CONFIG_MULTI_IF_NAME
+#endif
+
+#ifdef CONFIG_FEATURE_HIF_DELAYED_REG_WRITE
+#define FEATURE_HIF_DELAYED_REG_WRITE (1)
+#endif
+
+#ifdef CONFIG_WLAN_FEATURE_11BE_MLO
+#ifndef CONFIG_WLAN_MAX_ML_DEFAULT_LINK
+#define CONFIG_WLAN_MAX_ML_DEFAULT_LINK (2)
+#endif
+#else
+#ifndef CONFIG_WLAN_MAX_ML_DEFAULT_LINK
+#define CONFIG_WLAN_MAX_ML_DEFAULT_LINK (1)
+#endif
+#endif
+
+#ifdef CONFIG_WLAN_MAX_ML_DEFAULT_LINK
+#define WLAN_MAX_ML_DEFAULT_LINK CONFIG_WLAN_MAX_ML_DEFAULT_LINK
+#endif
+
+#ifdef CONFIG_WLAN_FEATURE_11BE_MLO
+#ifndef CONFIG_WLAN_MAX_ML_BSS_LINKS
+#define CONFIG_WLAN_MAX_ML_BSS_LINKS (3)
+#endif
+#else
+#ifndef CONFIG_WLAN_MAX_ML_BSS_LINKS
+#define CONFIG_WLAN_MAX_ML_BSS_LINKS (1)
+#endif
+#endif
+
+#ifdef CONFIG_WLAN_MAX_ML_BSS_LINKS
+#define WLAN_MAX_ML_BSS_LINKS CONFIG_WLAN_MAX_ML_BSS_LINKS
+#endif
+
+#ifdef CONFIG_WALT_GET_CPU_TAKEN_SUPPORT
+#define WALT_GET_CPU_TAKEN_SUPPORT (1)
+#endif
+
+#ifdef CONFIG_WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
+#define WLAN_HDD_MULTI_VDEV_SINGLE_NDEV (1)
+#endif
+
+#ifdef CONFIG_WLAN_FEATURE_CE_RX_BUFFER_REUSE
+#define WLAN_FEATURE_CE_RX_BUFFER_REUSE (1)
+#endif
+
 #endif /* CONFIG_TO_FEATURE_H */

+ 8 - 1
configs/default_defconfig

@@ -761,7 +761,7 @@ CONFIG_MAX_ALLOC_PAGE_SIZE := y
 CONFIG_REO_DESC_DEFER_FREE := y
 CONFIG_RXDMA_ERR_PKT_DROP := y
 CONFIG_DELIVERY_TO_STACK_STATUS_CHECK := y
-CONFIG_WLAN_TRACE_HIDE_MAC_ADDRESS := n
+CONFIG_WLAN_TRACE_HIDE_MAC_ADDRESS := y
 CONFIG_WLAN_TRACE_HIDE_SSID := n
 CONFIG_DP_MEM_PRE_ALLOC := y
 CONFIG_FEATURE_GPIO_CFG := y
@@ -1318,6 +1318,7 @@ ifeq ($(CONFIG_SLUB_DEBUG_ON), y)
 	CONFIG_DESC_TIMESTAMP_DEBUG_INFO := y
 	CONFIG_FEATURE_UNIT_TEST_SUSPEND := y
 	CONFIG_LEAK_DETECTION := y
+	CONFIG_WLAN_TRACE_HIDE_MAC_ADDRESS := n
 ifndef CONFIG_MAX_LOGS_PER_SEC
 	CONFIG_MAX_LOGS_PER_SEC := 500
 endif
@@ -1349,6 +1350,7 @@ ifeq ($(CONFIG_CNSS2_DEBUG), y)
 	CONFIG_ENABLE_QDF_PTR_HASH_DEBUG := y
 	CONFIG_HAL_DEBUG := y
 	CONFIG_ATH_DIAG_EXT_DIRECT := y
+	CONFIG_WLAN_TRACE_HIDE_MAC_ADDRESS := n
 endif
 
 	CONFIG_HIF_DEBUG := y
@@ -1558,6 +1560,11 @@ CONFIG_WLAN_FEATURE_RX_BUFFER_POOL := y
 CONFIG_DP_RX_BUFFER_POOL_SIZE := 128
 CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES := 5
 CONFIG_DP_SWLM := y
+CONFIG_WLAN_FEATURE_CE_RX_BUFFER_REUSE := y
+endif
+
+ifeq ($(CONFIG_WLAN_FEATURE_CE_RX_BUFFER_REUSE), y)
+CONFIG_WLAN_WBUFF := y
 endif
 
 ifeq (y,$(filter y,$(CONFIG_ARCH_SDXLEMUR) $(CONFIG_ARCH_SDXBAAGHA)))

+ 3 - 0
configs/kiwi_v2_defconfig

@@ -30,6 +30,9 @@ CONFIG_CFG_MAX_STA_VDEVS := 4
 #Enable 11BE MLO
 CONFIG_WLAN_FEATURE_11BE_MLO := y
 
+#Enable Single NDEV Multi VDEV
+CONFIG_WLAN_HDD_MULTI_VDEV_SINGLE_NDEV := y
+
 #BMISS offload max vdev config
 CONFIG_CFG_BMISS_OFFLOAD_MAX_VDEV := 4
 

+ 2 - 6
configs/pineapple_consolidate_kiwi-v2_defconfig

@@ -12,26 +12,22 @@ CONFIG_FEATURE_UNIT_TEST_SUSPEND=y
 CONFIG_HAL_DEBUG=y
 CONFIG_HIF_CE_DEBUG_DATA_BUF=y
 CONFIG_HIF_CPU_PERF_AFFINE_MASK=y
-CONFIG_HIF_DEBUG=y
 CONFIG_LEAK_DETECTION=y
 CONFIG_MAX_LOGS_PER_SEC=500
+CONFIG_ENABLE_MAX_LOGS_PER_SEC=y
 CONFIG_QDF_NBUF_HISTORY_SIZE=16384
 CONFIG_REGISTER_OP_DEBUG=y
 CONFIG_REO_QDESC_HISTORY=y
 CONFIG_RX_DESC_DEBUG_CHECK=y
 CONFIG_SCHED_HISTORY_SIZE=256
+CONFIG_ENABLE_SCHED_HISTORY_SIZE=y
 CONFIG_TALLOC_DEBUG=y
 CONFIG_UNIT_TEST=y
 CONFIG_WLAN_FEATURE_DP_CFG_EVENT_HISTORY=y
 CONFIG_WLAN_FEATURE_DP_MON_STATUS_RING_HISTORY=y
 CONFIG_WLAN_FEATURE_DP_RX_RING_HISTORY=y
 CONFIG_WLAN_FEATURE_DP_TX_DESC_HISTORY=y
-CONFIG_WLAN_OBJMGR_DEBUG=y
-CONFIG_WLAN_OBJMGR_REF_ID_TRACE=y
 CONFIG_WLAN_RECORD_RX_PADDR=y
-CONFIG_PANIC_ON_BUG=y
-CONFIG_WLAN_WARN_ON_ASSERT=y
-CONFIG_CNSS_OUT_OF_TREE=y
 CONFIG_QDF_TEST=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_FEATURE_WLM_STATS=y

+ 16 - 4
configs/pineapple_gki_kiwi-v2_defconfig

@@ -235,6 +235,7 @@ CONFIG_WLAN_ENH_CFR_ENABLE=y
 CONFIG_WLAN_FEATURE_11AX=y
 CONFIG_WLAN_FEATURE_11BE=y
 CONFIG_WLAN_FEATURE_11BE_MLO=y
+CONFIG_WLAN_HDD_MULTI_VDEV_SINGLE_NDEV=y
 CONFIG_WLAN_FEATURE_ACTION_OUI=y
 CONFIG_WLAN_FEATURE_BIG_DATA_STATS=y
 CONFIG_WLAN_FEATURE_CAL_FAILURE_TRIGGER=y
@@ -353,12 +354,10 @@ CONFIG_WMI_INTERFACE_EVENT_LOGGING=y
 CONFIG_WMI_ROAM_SUPPORT=y
 CONFIG_WMI_SEND_RECV_QMI=y
 CONFIG_WMI_STA_SUPPORT=y
-CONFIG_CFG80211_RU_PUNCT_NOTIFY=y
-CONFIG_CFG80211_MLO_KEY_OPERATION_SUPPORT=y
 CONFIG_CFG80211_EXTERNAL_AUTH_MLO_SUPPORT=y
 CONFIG_CFG80211_EXT_FEATURE_SECURE_NAN=y
-CONFIG_CFG80211_LINK_STA_PARAMS_PRESENT=y
 CONFIG_WLAN_CTRL_NAME="wlan"
+CONFIG_MULTI_IF_NAME="kiwi_v2"
 CONFIG_NL80211_TESTMODE=y
 CONFIG_QCA_WIFI_FTM_IOCTL=y
 CONFIG_ENABLE_CE4_COMP_DISABLE_HTT_HTC_MISC_LIST=y
@@ -375,4 +374,17 @@ CONFIG_CFG80211_MLD_AP_STA_CONNECT_UPSTREAM_SUPPORT=y
 CONFIG_DP_MULTIPASS_SUPPORT=y
 CONFIG_WLAN_DP_VDEV_NO_SELF_PEER=y
 CONFIG_WLAN_FEATURE_AFFINITY_MGR=y
-CONFIG_NL80211_EXT_FEATURE_PUNCT_SUPPORT=y
+CONFIG_WALT_GET_CPU_TAKEN_SUPPORT=y
+CONFIG_DP_MLO_LINK_STATS_SUPPORT=y
+CONFIG_HIF_DEBUG=y
+CONFIG_WLAN_OBJMGR_DEBUG=y
+CONFIG_WLAN_OBJMGR_REF_ID_TRACE=y
+CONFIG_WLAN_WARN_ON_ASSERT=y
+CONFIG_WLAN_DP_FEATURE_DEFERRED_REO_QDESC_DESTROY=y
+CONFIG_PANIC_ON_BUG=y
+CONFIG_FEATURE_WLAN_CH_AVOID_EXT=y
+CONFIG_CNSS2_SSR_DRIVER_DUMP=y
+CONFIG_BUS_AUTO_SUSPEND=y
+CONFIG_CNSS_OUT_OF_TREE=y
+CONFIG_SMP=y
+CONFIG_RPS=y

+ 10 - 3
core/hdd/inc/wlan_hdd_assoc.h

@@ -65,6 +65,7 @@ enum peer_status {
  * struct hdd_conn_flag - connection flags
  * @ht_present: ht element present or not
  * @vht_present: vht element present or not
+ * @eht_present: eht element present or not
  * @hs20_present: hs20 element present or not
  * @ht_op_present: ht operation present or not
  * @vht_op_present: vht operation present or not
@@ -73,10 +74,11 @@ enum peer_status {
 struct hdd_conn_flag {
 	uint8_t ht_present:1;
 	uint8_t vht_present:1;
+	uint8_t eht_present:1;
 	uint8_t hs20_present:1;
 	uint8_t ht_op_present:1;
 	uint8_t vht_op_present:1;
-	uint8_t reserved:3;
+	uint8_t reserved:2;
 };
 
 /*defines for tx_BF_cap_info */
@@ -153,6 +155,7 @@ struct hdd_conn_flag {
  * @max_tx_bitrate: Max tx bitrate supported by the AP
  * to which currently sta is connected.
  * @prev_ap_bcn_ie: ap beacon IE information to which sta is currently connected
+ * @ieee_link_id: AP Link Id valid for MLO connection
  */
 struct hdd_connection_info {
 	eConnectionState conn_state;
@@ -193,6 +196,9 @@ struct hdd_connection_info {
 	enum phy_ch_width ch_width;
 	struct rate_info max_tx_bitrate;
 	struct element_info prev_ap_bcn_ie;
+#ifdef WLAN_FEATURE_11BE_MLO
+	int32_t ieee_link_id;
+#endif
 };
 
 /* Forward declarations */
@@ -348,15 +354,16 @@ hdd_indicate_ese_bcn_report_no_results(const struct hdd_adapter *adapter,
 
 /**
  * hdd_change_peer_state() - change peer state
- * @adapter: HDD adapter
+ * @link_info: Link info pointer of VDEV in adapter
  * @peer_mac_addr: Peer MAC address
  * @sta_state: peer state
  *
  * Return: QDF status
  */
-QDF_STATUS hdd_change_peer_state(struct hdd_adapter *adapter,
+QDF_STATUS hdd_change_peer_state(struct wlan_hdd_link_info *link_info,
 				 uint8_t *peer_mac_addr,
 				 enum ol_txrx_peer_state sta_state);
+
 /**
  * hdd_update_dp_vdev_flags() - update datapath vdev flags
  * @cbk_data: callback data

+ 10 - 0
core/hdd/inc/wlan_hdd_cfg.h

@@ -378,6 +378,16 @@ int
 hdd_vendor_mode_to_bonding_mode(enum qca_wlan_vendor_phy_mode vendor_phy_mode,
 				uint32_t *bonding_mode);
 
+/**
+ * hdd_phymode_to_dot11_mode() - Mapping phymode to dot11mode
+ * @phymode: phy mode
+ * @dot11_mode: dot11 mode
+ *
+ * Return: 0 on success, negative errno value on error
+ */
+int hdd_phymode_to_dot11_mode(eCsrPhyMode phymode,
+			      enum hdd_dot11_mode *dot11_mode);
+
 /**
  * hdd_update_phymode() - update the PHY mode of the adapter
  * @adapter: adapter being modified

+ 120 - 8
core/hdd/inc/wlan_hdd_main.h

@@ -959,6 +959,7 @@ struct hdd_chan_change_params {
  * @system_suspend: system suspend context to prevent/allow runtime pm
  * @dyn_mac_addr_update: update mac addr context to prevent/allow runtime pm
  * @vdev_destroy: vdev destroy context to prevent/allow runtime pm
+ * @oem_data_cmd: OEM data context to prevent/allow runtime pm
  *
  * Runtime PM control for underlying activities
  */
@@ -972,6 +973,7 @@ struct hdd_runtime_pm_context {
 	qdf_runtime_lock_t system_suspend;
 	qdf_runtime_lock_t dyn_mac_addr_update;
 	qdf_runtime_lock_t vdev_destroy;
+	qdf_runtime_lock_t oem_data_cmd;
 };
 
 /*
@@ -1151,6 +1153,7 @@ struct wlan_hdd_tx_power {
  * @mac_addr: Current MAC Address for the adapter
  * @mld_addr: MLD address for adapter
  * @event_flags: a bitmap of hdd_adapter_flags
+ * @curr_link_info_map: Current mapping of link info in adapter array
  * @active_links: a bitmap of active links in @link_info array
  * @num_links_on_create: No of active links set on initial hdd_open_adapter().
  * @is_ll_stats_req_pending: atomic variable to check active stats req
@@ -1248,6 +1251,7 @@ struct wlan_hdd_tx_power {
  * @delta_qtime: delta between host qtime and monotonic time
  * @traffic_end_ind_en: traffic end indication feature enable/disable
  * @is_dbam_configured:
+ * @user_phy_mode: phy mode is set per vdev
  * @deflink: Default link pointing to the 0th index of the linkinfo array
  * @link_info: Data structure to hold link specific information
  * @tx_power: Structure to hold connection tx Power info
@@ -1279,6 +1283,7 @@ struct hdd_adapter {
 	struct qdf_mac_addr mld_addr;
 #endif
 	unsigned long event_flags;
+	uint8_t curr_link_info_map[WLAN_MAX_ML_BSS_LINKS];
 	unsigned long active_links;
 	uint8_t num_links_on_create;
 
@@ -1436,6 +1441,7 @@ struct hdd_adapter {
 #ifdef WLAN_FEATURE_DBAM_CONFIG
 	bool is_dbam_configured;
 #endif
+	enum qca_wlan_vendor_phy_mode user_phy_mode;
 	struct wlan_hdd_link_info *deflink;
 	struct wlan_hdd_link_info link_info[WLAN_MAX_ML_BSS_LINKS];
 	struct wlan_hdd_tx_power tx_power;
@@ -1974,7 +1980,6 @@ enum wlan_state_ctrl_str_id {
  * @host wakeup from fw with reason as pagefault
  * @bridgeaddr: Bridge MAC address
  * @is_mlo_per_link_stats_supported: Per link mlo stats is supported or not
- * @mlo_peer_stats: Pointer to MLO Peer Stats
  * @num_mlo_peers: Total number of MLO peers
  * @more_peer_data: more mlo peer data in peer stats
  */
@@ -2255,7 +2260,6 @@ struct hdd_context {
 	uint8_t bridgeaddr[QDF_MAC_ADDR_SIZE];
 #ifdef WLAN_FEATURE_11BE_MLO
 	bool is_mlo_per_link_stats_supported;
-	struct wifi_peer_stat *mlo_peer_stats;
 	uint8_t num_mlo_peers;
 	uint32_t more_peer_data;
 #endif
@@ -2756,6 +2760,24 @@ hdd_adapter_get_next_active_link_info(struct hdd_adapter *adapter,
 struct wlan_hdd_link_info *
 wlan_hdd_get_link_info_from_objmgr(struct wlan_objmgr_vdev *vdev);
 
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
+	defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
+/**
+ * hdd_adapter_disable_all_links() - Reset the links on stop adapter.
+ * @adapter: HDD adapter
+ *
+ * Resets the MAC address in each link info and resets the link info
+ * mapping in adapter array.
+ *
+ * Return: void
+ */
+void hdd_adapter_disable_all_links(struct hdd_adapter *adapter);
+#else
+static inline void hdd_adapter_disable_all_links(struct hdd_adapter *adapter)
+{
+}
+#endif
+
 struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx,
 				     uint8_t session_type,
 				     const char *name, tSirMacAddr mac_addr,
@@ -2792,7 +2814,7 @@ void hdd_close_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held);
 QDF_STATUS hdd_stop_all_adapters(struct hdd_context *hdd_ctx);
 void hdd_deinit_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held);
 QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx);
-QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx);
+QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx, bool rtnl_held);
 
 /**
  * hdd_get_link_info_by_vdev() - Return link info with the given vdev id
@@ -2831,6 +2853,21 @@ struct hdd_adapter *hdd_adapter_get_by_reference(struct hdd_context *hdd_ctx,
  */
 void hdd_adapter_put(struct hdd_adapter *adapter);
 
+/**
+ * hdd_get_link_info_by_link_addr() - Get the link info pointer where
+ * the link address matches.
+ * @hdd_ctx: HDD context pointer
+ * @link_addr: Link address to search
+ *
+ * In the given @adapter search for @link_addr in each entry of link_info
+ * array, and return the matching link_info pointer.
+ *
+ * Return: NULL / Valid link info pointer
+ */
+struct wlan_hdd_link_info *
+hdd_get_link_info_by_link_addr(struct hdd_context *hdd_ctx,
+			       struct qdf_mac_addr *link_addr);
+
 struct hdd_adapter *hdd_get_adapter_by_macaddr(struct hdd_context *hdd_ctx,
 					       tSirMacAddr mac_addr);
 
@@ -3972,6 +4009,24 @@ QDF_STATUS hdd_sme_close_session_callback(uint8_t vdev_id);
 int hdd_register_cb(struct hdd_context *hdd_ctx);
 void hdd_deregister_cb(struct hdd_context *hdd_ctx);
 
+#ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
+static inline struct qdf_mac_addr *
+hdd_adapter_get_netdev_mac_addr(struct hdd_adapter *adapter)
+{
+	return &adapter->mac_addr;
+}
+#else
+static inline struct qdf_mac_addr *
+hdd_adapter_get_netdev_mac_addr(struct hdd_adapter *adapter)
+{
+	if (hdd_adapter_is_ml_adapter(adapter) ||
+	    hdd_adapter_is_link_adapter(adapter))
+		return &adapter->mld_addr;
+
+	return &adapter->mac_addr;
+}
+#endif
+
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
 	defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
 /**
@@ -3994,8 +4049,8 @@ QDF_STATUS hdd_adapter_fill_link_address(struct hdd_adapter *adapter)
 #endif
 
 /**
- * hdd_adapter_get_mac_address() - Returns the appropriate MAC address pointer
- * in adapter.
+ * hdd_adapter_get_link_mac_addr() - Returns the appropriate
+ * MAC address pointer in adapter.
  * @link_info: Link info in HDD adapter.
  *
  * If WLAN_HDD_MULTI_VDEV_SINGLE_NDEV flag is enabled, then MAC address pointer
@@ -4013,7 +4068,7 @@ QDF_STATUS hdd_adapter_fill_link_address(struct hdd_adapter *adapter)
  * Return: MAC address pointer based on adapter type.
  */
 struct qdf_mac_addr *
-hdd_adapter_get_mac_address(struct wlan_hdd_link_info *link_info);
+hdd_adapter_get_link_mac_addr(struct wlan_hdd_link_info *link_info);
 
 /**
  * hdd_adapter_check_duplicate_session() - Check for duplicate
@@ -4028,6 +4083,15 @@ hdd_adapter_get_mac_address(struct wlan_hdd_link_info *link_info);
  */
 QDF_STATUS hdd_adapter_check_duplicate_session(struct hdd_adapter *adapter);
 
+/**
+ * hdd_adapter_reset_station_ctx() - Resets station context with appropriate
+ * initial value.
+ * @adapter: HDD adapter
+ *
+ * Return: void
+ */
+void hdd_adapter_reset_station_ctx(struct hdd_adapter *adapter);
+
 /**
  * hdd_start_station_adapter()- Start the Station Adapter
  * @adapter: HDD adapter
@@ -4041,12 +4105,13 @@ int hdd_start_station_adapter(struct hdd_adapter *adapter);
 /**
  * hdd_start_ap_adapter()- Start AP Adapter
  * @adapter: HDD adapter
+ * @rtnl_held: True if rtnl lock is taken, otherwise false
  *
  * This function initializes the adapter for the AP mode.
  *
  * Return: 0 on success errno on failure.
  */
-int hdd_start_ap_adapter(struct hdd_adapter *adapter);
+int hdd_start_ap_adapter(struct hdd_adapter *adapter, bool rtnl_held);
 int hdd_configure_cds(struct hdd_context *hdd_ctx);
 int hdd_set_fw_params(struct hdd_adapter *adapter);
 
@@ -4117,7 +4182,7 @@ void hdd_psoc_idle_timer_stop(struct hdd_context *hdd_ctx);
  */
 int hdd_trigger_psoc_idle_restart(struct hdd_context *hdd_ctx);
 
-int hdd_start_adapter(struct hdd_adapter *adapter);
+int hdd_start_adapter(struct hdd_adapter *adapter, bool rtnl_held);
 void hdd_populate_random_mac_addr(struct hdd_context *hdd_ctx, uint32_t num);
 /**
  * hdd_is_interface_up()- Check if the given interface is up
@@ -5075,6 +5140,18 @@ static inline unsigned long wlan_hdd_get_default_pm_qos_cpu_latency(void)
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) */
 #endif /* defined(CLD_PM_QOS) || defined(FEATURE_RUNTIME_PM) */
 
+/**
+ * hdd_get_wifi_standard() - Get wifi standard
+ * @hdd_ctx: hdd context pointer
+ * @dot11_mode: hdd dot11 mode
+ * @band_capability: band capability bitmap
+ *
+ * Return: WMI_HOST_WIFI_STANDARD
+ */
+WMI_HOST_WIFI_STANDARD
+hdd_get_wifi_standard(struct hdd_context *hdd_ctx,
+		      enum hdd_dot11_mode dot11_mode, uint32_t band_capability);
+
 /**
  * hdd_is_runtime_pm_enabled - if runtime pm enabled
  * @hdd_ctx: hdd context
@@ -5184,6 +5261,41 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
  */
 void hdd_check_for_net_dev_ref_leak(struct hdd_adapter *adapter);
 
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
+
+/**
+ * hdd_link_switch_vdev_mac_addr_update() - API to update OSIF/HDD on VDEV
+ * mac addr update due to link switch.
+ * @ieee_old_link_id: Current  IEEE link ID of VDEV prior to link switch
+ * @ieee_new_link_id: New IEEE link ID of VDEV post link switch
+ * @vdev_id: VDEV undergoing link switch.
+ *
+ * Check if both @ieee_old_link_id and @ieee_new_link_id are part of adapter
+ * corresponding to @vdev_id. Then take necessary actions to support link switch
+ * MAC update and update DP to change link MAC address to new link's address.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+hdd_link_switch_vdev_mac_addr_update(int32_t ieee_old_link_id,
+				     int32_t ieee_new_link_id, uint8_t vdev_id);
+
+/**
+ * hdd_get_link_info_by_ieee_link_id() - Find link info pointer matching with
+ * IEEE link ID.
+ * @adapter: HDD adapter
+ * @link_id: IEEE link ID to search for.
+ *
+ * Search the station ctx connection info for matching link ID in @adapter and
+ * return the link info pointer on match. The IEEE link ID is updated in station
+ * context during MLO connection and reset on disconnection.
+ *
+ * Return: link info pointer
+ */
+struct wlan_hdd_link_info *
+hdd_get_link_info_by_ieee_link_id(struct hdd_adapter *adapter, int32_t link_id);
+#endif
+
 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
 /**
  * hdd_dynamic_mac_address_set(): API to set MAC address, when interface

+ 54 - 0
core/hdd/inc/wlan_hdd_mlo.h

@@ -249,6 +249,17 @@ struct hdd_adapter *hdd_get_ml_adapter(struct hdd_context *hdd_ctx)
  */
 void hdd_adapter_set_ml_adapter(struct hdd_adapter *adapter);
 
+/**
+ * hdd_adapter_link_switch_notification() - Get HDD notification on link switch
+ * start.
+ * @vdev: VDEV on which link switch will happen
+ * @non_trans_vdev_id: VDEV not part of link switch.
+ *
+ * Return: QDF_STATUS.
+ */
+QDF_STATUS hdd_adapter_link_switch_notification(struct wlan_objmgr_vdev *vdev,
+						uint8_t non_trans_vdev_id);
+
 /**
  * hdd_mlo_t2lm_register_callback() - Register T2LM callback
  * @vdev: Pointer to vdev
@@ -327,12 +338,55 @@ int wlan_hdd_cfg80211_process_ml_link_state(struct wiphy *wiphy,
 QDF_STATUS hdd_derive_link_address_from_mld(struct qdf_mac_addr *mld_addr,
 					    struct qdf_mac_addr *link_addr_list,
 					    uint8_t max_idx);
+
+#ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
+/**
+ * hdd_mlo_mgr_register_osif_ops() - Register OSIF ops with global MLO manager
+ * for callback to notify.
+ *
+ * The @ops contain callback functions which are triggered to update OSIF about
+ * necessary events from MLO manager.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS hdd_mlo_mgr_register_osif_ops(void);
+
+/**
+ * hdd_mlo_mgr_unregister_osif_ops() - Deregister OSIF ops with
+ * global MLO manager
+ *
+ * Deregister the calbacks registered with global MLO manager for OSIF
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS hdd_mlo_mgr_unregister_osif_ops(void);
+#else
+static inline QDF_STATUS hdd_mlo_mgr_register_osif_ops(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS hdd_mlo_mgr_unregister_osif_ops(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #else
 static inline void
 hdd_adapter_set_ml_adapter(struct hdd_adapter *adapter)
 {
 }
 
+static inline QDF_STATUS hdd_mlo_mgr_register_osif_ops(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS hdd_mlo_mgr_unregister_osif_ops(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
 static inline
 void hdd_mlo_t2lm_register_callback(struct wlan_objmgr_vdev *vdev)
 {

+ 9 - 7
core/hdd/inc/wlan_hdd_tx_rx.h

@@ -122,21 +122,23 @@ void hdd_tsf_timestamp_rx(hdd_cb_handle ctx, qdf_nbuf_t netbuf);
 
 /**
  * hdd_get_tsf_time_cb() - HDD helper function to get TSF time
- * @vdev_id: vdev id mapped to adapter
+ * @netdev: netdev
  * @input_time: Input time
  * @tsf_time: time from TFS module
  *
  * Return: None
  */
-void hdd_get_tsf_time_cb(uint8_t vdev_id, uint64_t input_time,
+void hdd_get_tsf_time_cb(qdf_netdev_t netdev, uint64_t input_time,
 			 uint64_t *tsf_time);
 #else
 static inline
 void hdd_tsf_timestamp_rx(hdd_cb_handle ctx, qdf_nbuf_t netbuf) { }
 
 static inline
-void hdd_get_tsf_time_cb(uint8_t vdev_id, uint64_t input_time,
-			 uint64_t *tsf_time) { }
+void hdd_get_tsf_time_cb(qdf_netdev_t netdev, uint64_t input_time,
+			 uint64_t *tsf_time)
+{
+}
 #endif
 
 /**
@@ -210,12 +212,12 @@ void hdd_get_tx_resource(uint8_t vdev_id,
 /**
  * hdd_get_tx_flow_low_watermark() - Get TX flow low watermark info
  * @cb_ctx: HDD opaque ctx
- * @intf_id: HDD adapter id
+ * @netdev: netdev
  *
  * Return: flow low watermark value
  */
 unsigned int
-hdd_get_tx_flow_low_watermark(hdd_cb_handle cb_ctx, uint8_t intf_id);
+hdd_get_tx_flow_low_watermark(hdd_cb_handle cb_ctx, qdf_netdev_t netdev);
 #else
 static inline void hdd_tx_resume_cb(void *adapter_context, bool tx_resume)
 {
@@ -246,7 +248,7 @@ void hdd_get_tx_resource(uint8_t vdev_id,
 			 struct qdf_mac_addr *mac_addr) { }
 
 static inline unsigned int
-hdd_get_tx_flow_low_watermark(hdd_cb_handle cb_ctx, uint8_t intf_id)
+hdd_get_tx_flow_low_watermark(hdd_cb_handle cb_ctx, qdf_netdev_t netdev)
 {
 	return 0;
 }

+ 0 - 15
core/hdd/inc/wlan_hdd_wext.h

@@ -165,16 +165,6 @@ typedef enum {
 #define HDD_FWTEST_MAX_VALUE 500
 
 #ifdef WLAN_WEXT_SUPPORT_ENABLE
-/**
- * hdd_unregister_wext() - unregister wext context
- * @dev: net device handle
- *
- * Unregisters wext interface context for a given net device
- *
- * Returns: None
- */
-void hdd_unregister_wext(struct net_device *dev);
-
 /**
  * hdd_register_wext() - register wext context
  * @dev: net device handle
@@ -338,11 +328,6 @@ static inline
 void hdd_set_dump_dp_trace(uint16_t cmd_type, uint16_t count) {}
 #endif
 #else /* WLAN_WEXT_SUPPORT_ENABLE */
-
-static inline void hdd_unregister_wext(struct net_device *dev)
-{
-}
-
 static inline void hdd_register_wext(struct net_device *dev)
 {
 }

+ 23 - 24
core/hdd/src/wlan_hdd_assoc.c

@@ -1254,23 +1254,21 @@ void hdd_clear_roam_profile_ie(struct hdd_adapter *adapter)
 }
 
 #if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2)
-static inline
-void hdd_set_unpause_queue(void *soc, struct hdd_adapter *adapter)
+static inline void hdd_set_unpause_queue(void *soc, uint8_t vdev_id)
 {
-	cdp_fc_vdev_unpause(soc, adapter->deflink->vdev_id,
-			    OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED,
-			    0);
+	cdp_fc_vdev_unpause(soc, vdev_id,
+			    OL_TXQ_PAUSE_REASON_PEER_UNAUTHORIZED, 0);
 }
 #else
-static inline
-void hdd_set_unpause_queue(void *soc, struct hdd_adapter *adapter)
-{ }
+static inline void hdd_set_unpause_queue(void *soc, uint8_t vdev_id)
+{
+}
 #endif
 
 #ifdef FEATURE_WDS
 /**
  * hdd_config_wds_repeater_mode() - configures vdev for wds repeater mode
- * @adapter: pointer to adapter
+ * @link_info: Link info pointer in HDD adapter
  * @peer_addr: peer mac address
  *
  * Configure dp vdev to detect and drop multicast echo packets and enable
@@ -1278,35 +1276,37 @@ void hdd_set_unpause_queue(void *soc, struct hdd_adapter *adapter)
  *
  * Return: None
  */
-static void
-hdd_config_wds_repeater_mode(struct hdd_adapter *adapter, uint8_t *peer_addr)
+static void hdd_config_wds_repeater_mode(struct wlan_hdd_link_info *link_info,
+					 uint8_t *peer_addr)
 {
 	cdp_config_param_type vdev_param;
 	ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
 
 	vdev_param.cdp_vdev_param_mec = true;
-	if (cdp_txrx_set_vdev_param(soc, adapter->deflink->vdev_id,
+	if (cdp_txrx_set_vdev_param(soc, link_info->vdev_id,
 				    CDP_ENABLE_MEC, vdev_param))
 		hdd_debug("Failed to set MEC param on DP vdev");
 
 	hdd_nofl_info("Turn on 4 address for peer: " QDF_MAC_ADDR_FMT,
 		      QDF_MAC_ADDR_REF(peer_addr));
 	if (sme_set_peer_param(peer_addr, WMI_HOST_PEER_USE_4ADDR, true,
-			       adapter->deflink->vdev_id))
+			       link_info->vdev_id))
 		hdd_err("Failed to enable WDS on vdev");
 }
 #else
 static inline void
-hdd_config_wds_repeater_mode(struct hdd_adapter *adapter, uint8_t *peer_addr)
+hdd_config_wds_repeater_mode(struct wlan_hdd_link_info *link_info,
+			     uint8_t *peer_addr)
 {
 }
 #endif
 
-QDF_STATUS hdd_change_peer_state(struct hdd_adapter *adapter,
+QDF_STATUS hdd_change_peer_state(struct wlan_hdd_link_info *link_info,
 				 uint8_t *peer_mac,
 				 enum ol_txrx_peer_state sta_state)
 {
 	QDF_STATUS err;
+	struct hdd_adapter *adapter = link_info->adapter;
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
 
@@ -1316,23 +1316,22 @@ QDF_STATUS hdd_change_peer_state(struct hdd_adapter *adapter,
 		return QDF_STATUS_E_FAULT;
 	}
 
-	if (hdd_is_roam_sync_in_progress(hdd_ctx, adapter->deflink->vdev_id)) {
+	if (hdd_is_roam_sync_in_progress(hdd_ctx, link_info->vdev_id)) {
 		if (adapter->device_mode == QDF_STA_MODE &&
 		    (wlan_mlme_get_wds_mode(hdd_ctx->psoc) ==
 		    WLAN_WDS_MODE_REPEATER))
-			hdd_config_wds_repeater_mode(adapter, peer_mac);
+			hdd_config_wds_repeater_mode(link_info, peer_mac);
 
-		hdd_son_deliver_peer_authorize_event(adapter, peer_mac);
+		hdd_son_deliver_peer_authorize_event(link_info, peer_mac);
 		return QDF_STATUS_SUCCESS;
 	}
 
 	if (sta_state == OL_TXRX_PEER_STATE_AUTH) {
 		/* Reset scan reject params on successful set key */
 		hdd_debug("Reset scan reject params");
-		hdd_init_scan_reject_params(adapter->hdd_ctx);
+		hdd_init_scan_reject_params(hdd_ctx);
 
-		err = sme_set_peer_authorized(peer_mac,
-					      adapter->deflink->vdev_id);
+		err = sme_set_peer_authorized(peer_mac, link_info->vdev_id);
 		if (err != QDF_STATUS_SUCCESS) {
 			hdd_err("Failed to set the peer state to authorized");
 			return QDF_STATUS_E_FAULT;
@@ -1340,15 +1339,15 @@ QDF_STATUS hdd_change_peer_state(struct hdd_adapter *adapter,
 
 		if (adapter->device_mode == QDF_STA_MODE ||
 		    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
-			hdd_set_unpause_queue(soc, adapter);
+			hdd_set_unpause_queue(soc, link_info->vdev_id);
 		}
 
 		if (adapter->device_mode == QDF_STA_MODE &&
 		    (wlan_mlme_get_wds_mode(hdd_ctx->psoc) ==
 		    WLAN_WDS_MODE_REPEATER))
-			hdd_config_wds_repeater_mode(adapter, peer_mac);
+			hdd_config_wds_repeater_mode(link_info, peer_mac);
 
-		hdd_son_deliver_peer_authorize_event(adapter, peer_mac);
+		hdd_son_deliver_peer_authorize_event(link_info, peer_mac);
 	}
 	return QDF_STATUS_SUCCESS;
 }

+ 2 - 2
core/hdd/src/wlan_hdd_cfg.c

@@ -1783,8 +1783,8 @@ hdd_vendor_mode_to_bonding_mode(enum qca_wlan_vendor_phy_mode vendor_phy_mode,
 	return 0;
 }
 
-static int hdd_phymode_to_dot11_mode(eCsrPhyMode phymode,
-				     enum hdd_dot11_mode *dot11_mode)
+int hdd_phymode_to_dot11_mode(eCsrPhyMode phymode,
+			      enum hdd_dot11_mode *dot11_mode)
 {
 	switch (phymode) {
 	case eCSR_DOT11_MODE_AUTO:

+ 337 - 68
core/hdd/src/wlan_hdd_cfg80211.c

@@ -209,7 +209,7 @@
 #include "wlan_epcs_api.h"
 #include "wlan_mlo_epcs_ucfg_api.h"
 #include <wlan_ll_sap_ucfg_api.h>
-
+#include <wlan_mlo_mgr_link_switch.h>
 /*
  * A value of 100 (milliseconds) can be sent to FW.
  * FW would enable Tx beamforming based on this.
@@ -1046,6 +1046,9 @@ static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
 						     int data_len)
 {
 	int status;
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct wlan_objmgr_vdev *vdev;
 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
 	struct sk_buff *skb;
 	uint32_t set = 0;
@@ -1055,6 +1058,7 @@ static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
 	bool tdls_sleep_sta_enable;
 	bool tdls_buffer_sta;
 	bool tdls_off_channel;
+	bool tdls_fw_wideband_cap;
 
 	hdd_enter_dev(wdev->netdev);
 
@@ -1063,6 +1067,9 @@ static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
 		return -EPERM;
 	}
 
+	if (hdd_validate_adapter(adapter))
+		return -EINVAL;
+
 	status = wlan_hdd_validate_context(hdd_ctx);
 	if (status)
 		return status;
@@ -1092,14 +1099,28 @@ static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
 					       &tdls_buffer_sta);
 		cfg_tdls_get_off_channel_enable(hdd_ctx->psoc,
 						&tdls_off_channel);
+		vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
+						   WLAN_OSIF_ID);
+		if (!vdev) {
+			hdd_err("Vdev is null return");
+			goto fail;
+		}
+
+		tdls_fw_wideband_cap =
+				wlan_cfg80211_tdls_is_fw_wideband_capable(vdev);
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
+
 		set = set | WIFI_TDLS_SUPPORT;
 		set = set | (tdls_external_control ?
 					WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
 		set = set | (tdls_off_channel ?
 					WIFI_TDLS_OFFCHANNEL_SUPPORT : 0);
+		set = set | (tdls_fw_wideband_cap ?
+					WIFI_TDLS_WIDER_BW_SUPPORT : 0);
 		max_num_tdls_sta = cfg_tdls_get_max_peer_count(hdd_ctx->psoc);
 
-		hdd_debug("TDLS Feature supported value %x", set);
+		hdd_debug("TDLS Feature supported value %x tdls_max_peer_count:%d",
+			  set, max_num_tdls_sta);
 		if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
 				max_num_tdls_sta) ||
 		    nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
@@ -3740,6 +3761,27 @@ wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(struct hdd_adapter *adapter)
 	return prev_acs_freq_valid;
 }
 
+/**
+ * hdd_remove_6ghz_freq_from_acs_list(): Removed 6 GHz frequecies from ACS list
+ * @org_freq_list: ACS frequecny list
+ * @org_ch_list_count: Number of frequencies in ACS list
+ *
+ * Return: None
+ */
+static void hdd_remove_6ghz_freq_from_acs_list(uint32_t *org_freq_list,
+					       uint8_t *org_ch_list_count)
+{
+	uint16_t i, ch_list_count = 0;
+
+	hdd_debug("Remove 6 GHz channels from ACS list");
+	for (i = 0; i < *org_ch_list_count; i++) {
+		if (wlan_reg_is_6ghz_chan_freq(org_freq_list[i]))
+			continue;
+		org_freq_list[ch_list_count++] = org_freq_list[i];
+	}
+	*org_ch_list_count = ch_list_count;
+}
+
 /**
  * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
  * @wiphy:  Linux wiphy struct pointer
@@ -4041,6 +4083,12 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 
 	ll_lt_sap = policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc,
 						 link_info->vdev_id);
+
+	if (wlan_reg_get_keep_6ghz_sta_cli_connection(hdd_ctx->pdev))
+		hdd_remove_6ghz_freq_from_acs_list(
+					sap_config->acs_cfg.freq_list,
+					&sap_config->acs_cfg.ch_list_count);
+
 	if ((is_external_acs_policy &&
 	    policy_mgr_is_force_scc(hdd_ctx->psoc) &&
 	    policy_mgr_get_connection_count(hdd_ctx->psoc)) || ll_lt_sap) {
@@ -5451,12 +5499,13 @@ hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context *hdd_ctx,
 		return QDF_STATUS_E_INVAL;
 	}
 
-	nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem)
+	nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
+		if (num_chan >= SIR_MAX_SUPPORTED_CHANNEL_LIST) {
+			hdd_err("number of channels (%d) supported exceeded max (%d)",
+				num_chan, SIR_MAX_SUPPORTED_CHANNEL_LIST);
+			return QDF_STATUS_E_INVAL;
+		}
 		num_chan++;
-	if (num_chan > SIR_MAX_SUPPORTED_CHANNEL_LIST) {
-		hdd_err("number of channels (%d) supported exceeded max (%d)",
-			num_chan, SIR_MAX_SUPPORTED_CHANNEL_LIST);
-		return QDF_STATUS_E_INVAL;
 	}
 	num_chan = 0;
 
@@ -8241,6 +8290,8 @@ const struct nla_policy wlan_hdd_wifi_config_policy[
 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EMLSR_MODE_SWITCH] = {
 		.type = NLA_U8},
 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UL_MU_CONFIG] = {.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST] = {
+		.type = NLA_NESTED},
 };
 
 static const struct nla_policy
@@ -8633,6 +8684,54 @@ wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct wlan_hdd_link_info *link_info,
 	return ret_val;
 }
 
+int hdd_set_vdev_phy_mode(struct hdd_adapter *adapter,
+			  enum qca_wlan_vendor_phy_mode vendor_phy_mode)
+{
+	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
+	struct wlan_hdd_link_info *link_info = adapter->deflink;
+	eCsrPhyMode phymode;
+	WMI_HOST_WIFI_STANDARD std;
+	enum hdd_dot11_mode dot11_mode;
+	uint8_t supported_band;
+	int ret;
+
+	if (hdd_cm_is_vdev_connected(link_info)) {
+		hdd_err("Station is connected, command is not supported");
+		return -EINVAL;
+	}
+
+	adapter->user_phy_mode = vendor_phy_mode;
+
+	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &phymode);
+	if (ret)
+		return ret;
+
+	ret = hdd_phymode_to_dot11_mode(phymode, &dot11_mode);
+	if (ret)
+		return ret;
+
+	ret = hdd_vendor_mode_to_band(vendor_phy_mode, &supported_band,
+				      wlan_reg_is_6ghz_supported(psoc));
+	if (ret)
+		return ret;
+
+	std = hdd_get_wifi_standard(hdd_ctx, dot11_mode, supported_band);
+	hdd_debug("wifi_standard %d, vendor_phy_mode %d", std, vendor_phy_mode);
+
+	ret = sme_cli_set_command(link_info->vdev_id,
+				  wmi_vdev_param_wifi_standard_version,
+				  std, VDEV_CMD);
+	if (ret) {
+		hdd_err("Failed to set standard version to fw");
+		return ret;
+	}
+
+	ucfg_mlme_set_vdev_wifi_std(hdd_ctx->psoc, link_info->vdev_id, std);
+
+	return 0;
+}
+
 int hdd_set_phy_mode(struct hdd_adapter *adapter,
 		     enum qca_wlan_vendor_phy_mode vendor_phy_mode)
 {
@@ -8668,18 +8767,33 @@ int hdd_set_phy_mode(struct hdd_adapter *adapter,
 /**
  * hdd_config_phy_mode() - set PHY mode
  * @link_info: Link info pointer in HDD adapter
- * @attr: nla attr sent from userspace
+ * @tb: nla attr sent from userspace
  *
  * Return: 0 on success; error number otherwise
  */
 static int hdd_config_phy_mode(struct wlan_hdd_link_info *link_info,
-			       const struct nlattr *attr)
+			       struct nlattr *tb[])
 {
 	enum qca_wlan_vendor_phy_mode vendor_phy_mode;
+	uint32_t ifindex;
+	struct nlattr *phy_mode_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE];
+	struct nlattr *ifindex_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX];
+
+	if (!phy_mode_attr)
+		return 0;
 
-	vendor_phy_mode = nla_get_u32(attr);
+	vendor_phy_mode = nla_get_u32(phy_mode_attr);
+	if (!ifindex_attr)
+		return hdd_set_phy_mode(link_info->adapter, vendor_phy_mode);
 
-	return hdd_set_phy_mode(link_info->adapter, vendor_phy_mode);
+	ifindex = nla_get_u32(ifindex_attr);
+	if (ifindex == link_info->adapter->dev->ifindex)
+		return hdd_set_vdev_phy_mode(link_info->adapter,
+					     vendor_phy_mode);
+
+	hdd_err_rl("ifindex %d, expected ifindex %d", ifindex,
+		   link_info->adapter->dev->ifindex);
+	return -EINVAL;
 }
 
 /**
@@ -11272,7 +11386,8 @@ static int hdd_set_link_force_active(struct wlan_hdd_link_info *link_info,
 			qdf_mem_copy(mac_addr_ptr, nla_data(curr_attr),
 				     ETH_ALEN);
 			hdd_debug(QDF_MAC_ADDR_FMT " is link[%d] mac address",
-				  QDF_MAC_ADDR_REF(mac_addr_ptr), num_links);
+				  QDF_MAC_ADDR_REF(mac_addr_ptr->bytes),
+				  num_links);
 			num_links++;
 		}
 		sme_activate_mlo_links(hdd_ctx->mac_handle,
@@ -11356,6 +11471,61 @@ hdd_trigger_epcs_function(struct wlan_hdd_link_info *link_info,
 }
 #endif
 
+/**
+ * hdd_set_master_channel_list() - set master channel list from set wifi
+ * attribute
+ * @link_info: hdd link info
+ * @attr: Pointer to struct nlattr
+ *
+ * Return: 0 on success, else error number
+ */
+static int
+hdd_set_master_channel_list(struct wlan_hdd_link_info *link_info,
+			    const struct nlattr *attr)
+{
+	struct sap_config *sap_config;
+	qdf_freq_t freq;
+	uint16_t count = 0;
+	qdf_freq_t *freq_list;
+	struct nlattr *nested_attr;
+	int tmp, ret = 0;
+
+	if (link_info->adapter->device_mode != QDF_SAP_MODE) {
+		hdd_debug("command not received for sap");
+		return -EINVAL;
+	}
+	freq_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(qdf_freq_t));
+	if (!freq_list)
+		return -ENOMEM;
+
+	sap_config = &link_info->adapter->deflink->session.ap.sap_config;
+
+	nla_for_each_nested(nested_attr, attr, tmp) {
+		freq = nla_get_u32(nested_attr);
+		if (!freq) {
+			hdd_err("invalid freq");
+			ret = -EINVAL;
+			goto out;
+		}
+		freq_list[count] = freq;
+		count++;
+		if (count >= NUM_CHANNELS)
+			break;
+	}
+	if (!count) {
+		hdd_err("no valid freq found");
+		ret = -EINVAL;
+		goto out;
+	}
+	ret = wlansap_update_sap_chan_list(sap_config, freq_list, count);
+	if (ret)
+		hdd_err("sap chan list update failure");
+out:
+	qdf_mem_free(freq_list);
+
+	return ret;
+}
+
 /**
  * typedef independent_setter_fn - independent attribute handler
  * @link_info: Link info pointer in HDD adapter
@@ -11454,8 +11624,6 @@ static const struct independent_setters independent_setters[] = {
 	 hdd_config_tx_stbc},
 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
 	 hdd_config_rx_stbc},
-	{QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE,
-	 hdd_config_phy_mode},
 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH,
 	 hdd_set_channel_width},
 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
@@ -11501,6 +11669,8 @@ static const struct independent_setters independent_setters[] = {
 	 hdd_set_emlsr_mode},
 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UL_MU_CONFIG,
 	 hdd_set_ul_mu_config},
+	{QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST,
+	 hdd_set_master_channel_list},
 };
 
 #ifdef WLAN_FEATURE_ELNA
@@ -12221,6 +12391,7 @@ static const interdependent_setter_fn interdependent_setters[] = {
 	hdd_config_ani,
 	hdd_config_tx_rx_nss,
 	hdd_process_generic_set_cmd,
+	hdd_config_phy_mode,
 };
 
 /**
@@ -15326,9 +15497,10 @@ uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
 }
 
 static inline QDF_STATUS
-wlan_hdd_config_dp_direct_link_profile(struct wlan_objmgr_vdev *vdev,
+wlan_hdd_config_dp_direct_link_profile(struct hdd_adapter *adapter,
 				       enum host_concurrent_ap_policy ap_policy)
 {
+	struct wlan_objmgr_vdev *vdev = adapter->deflink->vdev;
 	enum host_concurrent_ap_policy prev_ap_policy;
 
 	prev_ap_policy = ucfg_mlme_get_ap_policy(vdev);
@@ -15340,9 +15512,11 @@ wlan_hdd_config_dp_direct_link_profile(struct wlan_objmgr_vdev *vdev,
 	case HOST_CONCURRENT_AP_POLICY_UNSPECIFIED:
 		switch (ap_policy) {
 		case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
-			return ucfg_dp_config_direct_link(vdev, true, false);
+			return ucfg_dp_config_direct_link(adapter->dev, true,
+							  false);
 		case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
-			return ucfg_dp_config_direct_link(vdev, true, true);
+			return ucfg_dp_config_direct_link(adapter->dev, true,
+							  true);
 		default:
 			break;
 		}
@@ -15351,7 +15525,8 @@ wlan_hdd_config_dp_direct_link_profile(struct wlan_objmgr_vdev *vdev,
 		switch (ap_policy) {
 		case HOST_CONCURRENT_AP_POLICY_UNSPECIFIED:
 		case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
-			return ucfg_dp_config_direct_link(vdev, true, false);
+			return ucfg_dp_config_direct_link(adapter->dev, true,
+							  false);
 		default:
 			break;
 		}
@@ -15359,7 +15534,8 @@ wlan_hdd_config_dp_direct_link_profile(struct wlan_objmgr_vdev *vdev,
 	case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
 		switch (ap_policy) {
 		case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
-			return ucfg_dp_config_direct_link(vdev, true, true);
+			return ucfg_dp_config_direct_link(adapter->dev, true,
+							  true);
 		default:
 			break;
 		}
@@ -15540,14 +15716,14 @@ static int __wlan_hdd_cfg80211_dual_sta_policy(struct hdd_context *hdd_ctx,
 /**
  * __wlan_hdd_cfg80211_ap_policy() - Wrapper to configure the concurrent
  * session policies
- * @vdev: pointer to vdev
+ * @adapter: HDD adapter
  * @tb: parsed attribute array
  *
  * Configure the concurrent session policies when multiple STA ifaces are
  * (getting) active.
  * Return: 0 on success; errno on failure
  */
-static int __wlan_hdd_cfg80211_ap_policy(struct wlan_objmgr_vdev *vdev,
+static int __wlan_hdd_cfg80211_ap_policy(struct hdd_adapter *adapter,
 					 struct nlattr **tb)
 {
 	QDF_STATUS status;
@@ -15559,7 +15735,7 @@ static int __wlan_hdd_cfg80211_ap_policy(struct wlan_objmgr_vdev *vdev,
 	uint8_t ap_config =
 		QCA_WLAN_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING;
 
-	vdev_id = wlan_vdev_get_id(vdev);
+	vdev_id = wlan_vdev_get_id(adapter->deflink->vdev);
 	device_mode = hdd_get_device_mode(vdev_id);
 	if (device_mode != QDF_SAP_MODE) {
 		hdd_err_rl("command not allowed in %d mode, vdev_id: %d",
@@ -15589,12 +15765,12 @@ static int __wlan_hdd_cfg80211_ap_policy(struct wlan_objmgr_vdev *vdev,
 		hdd_err("Failed to set profile %d", profile);
 		return -EINVAL;
 	}
-	status = wlan_hdd_config_dp_direct_link_profile(vdev, ap_cfg_policy);
+	status = wlan_hdd_config_dp_direct_link_profile(adapter, ap_cfg_policy);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("failed to set DP ap config");
 		return -EINVAL;
 	}
-	status = ucfg_mlme_set_ap_policy(vdev, ap_cfg_policy);
+	status = ucfg_mlme_set_ap_policy(adapter->deflink->vdev, ap_cfg_policy);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("failed to set MLME ap config");
 		return -EINVAL;
@@ -15657,7 +15833,7 @@ static int __wlan_hdd_cfg80211_concurrent_session_policy(
 		__wlan_hdd_cfg80211_dual_sta_policy(adapter->hdd_ctx, tb);
 
 	if (tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG])
-		__wlan_hdd_cfg80211_ap_policy(adapter->deflink->vdev, tb);
+		__wlan_hdd_cfg80211_ap_policy(adapter, tb);
 
 	return 0;
 }
@@ -21454,8 +21630,9 @@ hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter)
 		if (!link_adapter)
 			continue;
 
-		ucfg_dp_update_inf_mac(hdd_ctx->psoc, &link_adapter->mac_addr,
-				       &link_addr[i]);
+		ucfg_dp_update_intf_mac(hdd_ctx->psoc, &link_adapter->mac_addr,
+					&link_addr[i],
+					link_adapter->deflink->vdev);
 		qdf_copy_macaddr(&link_adapter->mac_addr, &link_addr[i]);
 	}
 	qdf_copy_macaddr(&adapter->link_info[i].link_addr, &link_addr[i]);
@@ -21654,7 +21831,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 
 	/* restart the adapter if it was up before the change iface request */
 	if (iff_up) {
-		errno = hdd_start_adapter(adapter);
+		errno = hdd_start_adapter(adapter, true);
 		if (errno) {
 			hdd_err("Failed to start adapter");
 			errno = -EINVAL;
@@ -21840,7 +22017,7 @@ wlan_hdd_set_vlan_id(struct hdd_sta_info_obj *sta_info_list,
 	if (!sta_info) {
 		hdd_err("Failed to find right station MAC: "
 			  QDF_MAC_ADDR_FMT,
-			  QDF_MAC_ADDR_REF(uint8_t *)mac);
+			  QDF_MAC_ADDR_REF(mac));
 		return;
 	}
 
@@ -22220,53 +22397,38 @@ static int wlan_hdd_add_key_sta(struct wlan_objmgr_pdev *pdev,
 
 #ifdef WLAN_FEATURE_11BE_MLO
 static void
-wlan_hdd_mlo_link_free_keys(struct hdd_adapter *adapter,
+wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc *psoc,
+			    struct hdd_adapter *adapter,
 			    struct wlan_objmgr_vdev *vdev,
 			    bool pairwise)
 {
+	struct qdf_mac_addr *link_addr;
+	uint8_t link_id;
+
 	if (adapter->device_mode != QDF_STA_MODE)
 		return;
 
 	if (pairwise &&
 	    wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
 	    mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
-					      wlan_vdev_get_id(vdev)))
-		wlan_crypto_free_vdev_key(vdev);
-}
-static bool
-wlan_hdd_mlo_set_keys_saved(struct hdd_adapter *adapter,
-			    struct wlan_objmgr_vdev *vdev,
-			    struct qdf_mac_addr *mac_address)
-{
-	if (!adapter)
-		return false;
+					      wlan_vdev_get_id(vdev))) {
+		link_addr =
+		(struct qdf_mac_addr *)wlan_vdev_mlme_get_linkaddr(vdev);
 
-	if (!vdev)
-		return false;
-
-	if ((adapter->device_mode == QDF_STA_MODE) &&
-	    ((!wlan_cm_is_vdev_connected(vdev)) ||
-	     (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
-	      mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
-						wlan_vdev_get_id(vdev))))) {
-		hdd_debug("MLO:Save keys for vdev %d", wlan_vdev_get_id(vdev));
-		mlo_set_keys_saved(vdev, mac_address, true);
-		return true;
+		if (!link_addr) {
+			crypto_err("link_addr NULL");
+			return;
+		}
+		link_id = wlan_vdev_get_link_id(vdev);
+		wlan_crypto_free_key_by_link_id(psoc, link_addr, link_id);
 	}
-
-	return false;
 }
+
 #else
-static bool
-wlan_hdd_mlo_set_keys_saved(struct hdd_adapter *adapter,
-			    struct wlan_objmgr_vdev *vdev,
-			    struct qdf_mac_addr *mac_address)
-{
-	return false;
-}
 
 static void
-wlan_hdd_mlo_link_free_keys(struct hdd_adapter *adapter,
+wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc *psoc,
+			    struct hdd_adapter *adapter,
 			    struct wlan_objmgr_vdev *vdev,
 			    bool pairwise)
 {
@@ -22367,6 +22529,7 @@ wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
 	ol_txrx_soc_handle soc_txrx_handle;
 	uint16_t *vlan_map = sap_ctx->vlan_map;
 	uint8_t found = 0;
+	bool keyindex_valid;
 	int i = 0;
 
 	psoc = wlan_vdev_get_psoc(vdev);
@@ -22375,7 +22538,7 @@ wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
 		return -EINVAL;
 	}
 
-	for (i = 0; i < (2 * MAX_VLAN); i += 2) {
+	for (i = 0; i < (MAX_VLAN * 2); i += 2) {
 		if (!vlan_map[i] || !vlan_map[i + 1]) {
 			found = 1;
 			break;
@@ -22388,7 +22551,9 @@ wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
 		}
 	}
 
-	if (found) {
+	keyindex_valid = (i + key_index - 1) < (2 * MAX_VLAN) ? true : false;
+
+	if (found && keyindex_valid) {
 		soc_txrx_handle = wlan_psoc_get_dp_handle(psoc);
 		vlan_map[i + key_index - 1] = params->vlan_id;
 		wlan_hdd_set_vlan_groupkey(soc_txrx_handle,
@@ -22413,6 +22578,75 @@ wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
 }
 #endif
 
+#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+static void wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev *vdev,
+					       struct hdd_context *hdd_ctx,
+					       u8 key_index, bool pairwise,
+					       struct key_params *params)
+{
+	struct mlo_link_info *mlo_link_info;
+	uint8_t link_info_iter = 0;
+
+	mlo_link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[0];
+	for (link_info_iter = 0; link_info_iter < WLAN_MAX_ML_BSS_LINKS;
+	     link_info_iter++, mlo_link_info++) {
+		if (qdf_is_macaddr_zero(&mlo_link_info->ap_link_addr) ||
+		    mlo_link_info->link_id == 0xFF)
+			continue;
+			hdd_debug(" Add pairwise key link id  %d ",
+				  mlo_link_info->link_id);
+			wlan_cfg80211_store_link_key(
+				hdd_ctx->psoc, key_index,
+				(pairwise ? WLAN_CRYPTO_KEY_TYPE_UNICAST :
+				WLAN_CRYPTO_KEY_TYPE_GROUP),
+				(uint8_t *)mlo_link_info->ap_link_addr.bytes,
+				params, &mlo_link_info->link_addr,
+				mlo_link_info->link_id);
+	}
+}
+
+static bool
+wlan_hdd_mlo_defer_set_keys(struct hdd_adapter *adapter,
+			    struct wlan_objmgr_vdev *vdev,
+			    struct qdf_mac_addr *mac_address)
+{
+	if (!adapter)
+		return false;
+
+	if (!vdev)
+		return false;
+
+	if ((adapter->device_mode == QDF_STA_MODE) &&
+	    ((!wlan_cm_is_vdev_connected(vdev)) ||
+	    (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
+	     mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
+					       wlan_vdev_get_id(vdev))))) {
+		hdd_debug("MLO:Defer set keys for vdev %d", wlan_vdev_get_id(vdev));
+		return true;
+	}
+
+	return false;
+}
+
+#else
+
+static void wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev *vdev,
+					       struct hdd_context *hdd_ctx,
+					       u8 key_index, bool pairwise,
+					       struct key_params *params)
+{
+}
+
+static bool
+wlan_hdd_mlo_defer_set_keys(struct hdd_adapter *adapter,
+			    struct wlan_objmgr_vdev *vdev,
+			    struct qdf_mac_addr *mac_address)
+{
+	return false;
+}
+
+#endif
+
 static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
 				 struct wlan_objmgr_vdev *vdev, u8 key_index,
 				 bool pairwise, const u8 *mac_addr,
@@ -22424,7 +22658,7 @@ static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
 	struct hdd_context *hdd_ctx;
 	struct qdf_mac_addr mac_address;
 	int32_t cipher_cap, ucast_cipher = 0;
-	int errno;
+	int errno = 0;
 	enum wlan_crypto_cipher_type cipher;
 	bool ft_mode = false;
 	uint8_t keyidx;
@@ -22491,15 +22725,22 @@ static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
 	}
 
 done:
-	wlan_hdd_mlo_link_free_keys(adapter, vdev, pairwise);
+	wlan_hdd_mlo_link_free_keys(hdd_ctx->psoc, adapter, vdev, pairwise);
+	if (pairwise && adapter->device_mode == QDF_STA_MODE &&
+	    wlan_vdev_mlme_is_mlo_vdev(vdev)) {
+		wlan_hdd_mlo_link_add_pairwise_key(vdev, hdd_ctx, key_index,
+						   pairwise, params);
 
-	errno = wlan_cfg80211_store_key(vdev, key_index,
+	} else {
+		errno = wlan_cfg80211_store_key(
+					vdev, key_index,
 					(pairwise ?
 					WLAN_CRYPTO_KEY_TYPE_UNICAST :
 					WLAN_CRYPTO_KEY_TYPE_GROUP),
 					mac_address.bytes, params);
+	}
 
-	if (wlan_hdd_mlo_set_keys_saved(adapter, vdev, &mac_address))
+	if (wlan_hdd_mlo_defer_set_keys(adapter, vdev, &mac_address))
 		return 0;
 
 	cipher_cap = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_CIPHER_CAP);
@@ -22773,6 +23014,32 @@ add_key:
 	return errno;
 }
 
+static int wlan_add_key_standby_link(struct hdd_adapter *adapter,
+				     struct wlan_objmgr_vdev *vdev,
+				     int link_id, u8 key_index,
+				     bool pairwise, struct key_params *params)
+{
+	int errno = 0;
+	struct hdd_context *hdd_ctx;
+	struct mlo_link_info *mlo_link_info;
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+	mlo_link_info = mlo_mgr_get_ap_link_by_link_id(vdev, link_id);
+	if (!mlo_link_info)
+		return QDF_STATUS_E_FAILURE;
+
+	errno = wlan_cfg80211_store_link_key(
+			hdd_ctx->psoc, key_index,
+			(pairwise ? WLAN_CRYPTO_KEY_TYPE_UNICAST :
+			WLAN_CRYPTO_KEY_TYPE_GROUP),
+			(uint8_t *)mlo_link_info->ap_link_addr.bytes,
+			params,
+			&mlo_link_info->link_addr,
+			link_id);
+	return errno;
+}
+
 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
 				     struct wlan_objmgr_vdev *vdev,
 				     u8 key_index, bool pairwise,
@@ -22844,7 +23111,9 @@ static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
 	link_vdev = wlan_key_get_link_vdev(adapter, WLAN_MLO_MGR_ID, link_id);
 	if (!link_vdev) {
 		hdd_err("couldn't get vdev for link_id :%d", link_id);
-		return -EINVAL;
+		errno = wlan_add_key_standby_link(adapter, vdev, link_id,
+						  key_index, pairwise, params);
+		return errno;
 	}
 
 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);

+ 10 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -286,6 +286,7 @@ typedef enum {
 #define WIFI_TDLS_SUPPORT			BIT(0)
 #define WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT	BIT(1)
 #define WIFI_TDLS_OFFCHANNEL_SUPPORT		BIT(2)
+#define WIFI_TDLS_WIDER_BW_SUPPORT		BIT(3)
 
 #define CFG_NON_AGG_RETRY_MAX                  (64)
 #define CFG_AGG_RETRY_MAX                      (64)
@@ -1122,6 +1123,15 @@ QDF_STATUS hdd_mlo_dev_t2lm_notify_link_update(struct wlan_objmgr_vdev *vdev,
 }
 #endif
 
+/** hdd_set_vdev_phy_mode() - Set vdev phy mode
+ * @adapter: adapter pointer
+ * @vendor_phy_mode: vendor phy mode
+ *
+ * Return: 0 for success
+ */
+int hdd_set_vdev_phy_mode(struct hdd_adapter *adapter,
+			  enum qca_wlan_vendor_phy_mode vendor_phy_mode);
+
 #if defined(WLAN_FEATURE_11BE_MLO) && \
 	defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT)
 /**

+ 4 - 4
core/hdd/src/wlan_hdd_cfr.c

@@ -136,8 +136,8 @@ wlan_cfg80211_cfr_set_group_config(struct wlan_objmgr_vdev *vdev,
 		nla_memcpy(&params.ta_mask[0],
 			   tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK],
 			   QDF_MAC_ADDR_SIZE);
-		hdd_debug("ta_mask " QDF_FULL_MAC_FMT,
-			  QDF_FULL_MAC_REF(&params.ta_mask[0]));
+		hdd_debug("ta_mask " QDF_MAC_ADDR_FMT,
+			  QDF_MAC_ADDR_REF(&params.ta_mask[0]));
 	}
 
 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA]) {
@@ -152,8 +152,8 @@ wlan_cfg80211_cfr_set_group_config(struct wlan_objmgr_vdev *vdev,
 		nla_memcpy(&params.ra_mask[0],
 			   tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK],
 			   QDF_MAC_ADDR_SIZE);
-		hdd_debug("ra_mask " QDF_FULL_MAC_FMT,
-			  QDF_FULL_MAC_REF(&params.ra_mask[0]));
+		hdd_debug("ra_mask " QDF_MAC_ADDR_FMT,
+			  QDF_MAC_ADDR_REF(&params.ra_mask[0]));
 	}
 
 	if (!qdf_is_macaddr_zero((struct qdf_mac_addr *)&params.ta) ||

+ 63 - 2
core/hdd/src/wlan_hdd_cm_api.h

@@ -255,13 +255,13 @@ __hdd_cm_disconnect_handler_pre_user_update(struct wlan_hdd_link_info *link_info
 /**
  * __hdd_cm_disconnect_handler_post_user_update() - Handle disconnect indication
  * after updating to user space
- * @adapter: Pointer to adapter
+ * @link_info: Link info pointer in HDD adapter
  * @vdev: vdev ptr
  *
  * Return: None
  */
 void
-__hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter,
+__hdd_cm_disconnect_handler_post_user_update(struct wlan_hdd_link_info *link_info,
 					     struct wlan_objmgr_vdev *vdev);
 
 /**
@@ -379,4 +379,65 @@ QDF_STATUS
 hdd_cm_get_scan_ie_params(struct wlan_objmgr_vdev *vdev,
 			  struct element_info *scan_ie,
 			  enum dot11_mode_filter *dot11mode_filter);
+
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * hdd_cm_save_connected_links_info() - Update connection info to station
+ * context.
+ * @self_mac: Self MAC address.
+ * @bssid: BSSID of link.
+ * @link_id: IEEE link id.
+ *
+ * It searches for link info pointer matching with @self_mac and updates
+ * the BSSID and link ID fields in station context's connection info.
+ * This will help to retrieve the link information using IEEE link ID or
+ * BSSID thereafter.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS hdd_cm_save_connected_links_info(struct qdf_mac_addr *self_mac,
+					    struct qdf_mac_addr *bssid,
+					    int32_t link_id);
+
+/**
+ * hdd_cm_set_ieee_link_id() - Set IEEE link ID in station context conn info.
+ * @link_info: Link info pointer in HDD adapter
+ * @link_id: IEEE link ID
+ *
+ * Sets IEEE link ID in connection info of @link_info's station context.
+ *
+ * Return: void
+ */
+void
+hdd_cm_set_ieee_link_id(struct wlan_hdd_link_info *link_info, uint8_t link_id);
+
+/**
+ * hdd_cm_clear_ieee_link_id() - Clear IEEE link ID in station context
+ * conn info.
+ * @link_info: Link info pointer in HDD adapter
+ *
+ * Clear IEEE link ID in connection info of @link_info's station context.
+ *
+ * Return: void
+ */
+void hdd_cm_clear_ieee_link_id(struct wlan_hdd_link_info *link_info);
+#else
+static inline void
+hdd_cm_set_ieee_link_id(struct wlan_hdd_link_info *link_info, uint8_t link_id)
+{
+}
+
+static inline void
+hdd_cm_clear_ieee_link_id(struct wlan_hdd_link_info *link_info)
+{
+}
+
+static inline
+QDF_STATUS hdd_cm_save_connected_links_info(struct qdf_mac_addr *self_mac,
+					    struct qdf_mac_addr *bssid,
+					    int32_t link_id)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* WLAN_FEATURE_11BE_MLO */
 #endif /* __WLAN_HDD_CM_API_H */

+ 79 - 3
core/hdd/src/wlan_hdd_cm_connect.c

@@ -185,7 +185,7 @@ void hdd_cm_set_peer_authenticate(struct wlan_hdd_link_info *link_info,
 		  QDF_MAC_ADDR_REF(bssid->bytes),
 		  is_auth_required ? "CONNECTED" : "AUTHENTICATED");
 
-	hdd_change_peer_state(link_info->adapter, bssid->bytes,
+	hdd_change_peer_state(link_info, bssid->bytes,
 			      is_auth_required ?
 			      OL_TXRX_PEER_STATE_CONN :
 			      OL_TXRX_PEER_STATE_AUTH);
@@ -199,9 +199,22 @@ void hdd_cm_update_rssi_snr_by_bssid(struct wlan_hdd_link_info *link_info)
 	struct hdd_station_ctx *sta_ctx;
 	int8_t snr = 0;
 	struct hdd_adapter *adapter = link_info->adapter;
+	mac_handle_t mac_handle;
+
+	if (!adapter) {
+		hdd_err_rl("null hdd_adapter pointer");
+		return;
+	}
+
+	mac_handle = hdd_adapter_get_mac_handle(adapter);
+
+	if (!mac_handle) {
+		hdd_err_rl("null mac_handle pointer");
+		return;
+	}
 
 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
-	hdd_get_rssi_snr_by_bssid(hdd_adapter_get_mac_handle(adapter),
+	hdd_get_rssi_snr_by_bssid(mac_handle,
 				  sta_ctx->conn_info.bssid.bytes,
 				  &link_info->rssi, &snr);
 
@@ -314,6 +327,53 @@ void hdd_cm_save_connect_status(struct wlan_hdd_link_info *link_info,
 	hdd_sta_ctx->cache_conn_info.assoc_status_code = reason_code;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+QDF_STATUS hdd_cm_save_connected_links_info(struct qdf_mac_addr *self_mac,
+					    struct qdf_mac_addr *bssid,
+					    int32_t link_id)
+{
+	struct hdd_context *hdd_ctx;
+	struct wlan_hdd_link_info *link_info;
+	struct hdd_station_ctx *sta_ctx;
+
+	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	if (!hdd_ctx) {
+		hdd_err("HDD context NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	link_info = hdd_get_link_info_by_link_addr(hdd_ctx, self_mac);
+	if (!link_info) {
+		hdd_err("No link info with MAC: " QDF_MAC_ADDR_FMT,
+			QDF_MAC_ADDR_REF(self_mac->bytes));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
+	hdd_cm_set_ieee_link_id(link_info, link_id);
+	qdf_copy_macaddr(&sta_ctx->conn_info.bssid, bssid);
+	return QDF_STATUS_SUCCESS;
+}
+
+void
+hdd_cm_set_ieee_link_id(struct wlan_hdd_link_info *link_info, uint8_t link_id)
+{
+	struct hdd_station_ctx *sta_ctx =
+				WLAN_HDD_GET_STATION_CTX_PTR(link_info);
+
+	sta_ctx->conn_info.ieee_link_id = link_id;
+}
+
+void
+hdd_cm_clear_ieee_link_id(struct wlan_hdd_link_info *link_info)
+{
+	struct hdd_station_ctx *sta_ctx =
+				WLAN_HDD_GET_STATION_CTX_PTR(link_info);
+
+	sta_ctx->conn_info.ieee_link_id = WLAN_INVALID_LINK_ID;
+}
+#endif
+
 #ifdef FEATURE_WLAN_WAPI
 static bool hdd_cm_is_wapi_sta(enum csr_akm_type auth_type)
 {
@@ -518,12 +578,19 @@ hdd_get_sap_adapter_of_dfs(struct hdd_context *hdd_ctx)
 			    hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS)
 				continue;
 
+			wlan_objmgr_vdev_get_ref(link_info->vdev,
+						 WLAN_HDD_ID_OBJ_MGR);
 			chan = wlan_vdev_get_active_channel(link_info->vdev);
 			if (!chan) {
 				hdd_debug("Can not get active channel");
+				wlan_objmgr_vdev_release_ref(link_info->vdev,
+							   WLAN_HDD_ID_OBJ_MGR);
 				continue;
 			}
 
+			wlan_objmgr_vdev_release_ref(link_info->vdev,
+						     WLAN_HDD_ID_OBJ_MGR);
+
 			if (!wlan_reg_is_5ghz_ch_freq(chan->ch_freq))
 				continue;
 
@@ -868,6 +935,8 @@ hdd_cm_connect_failure_pre_user_update(struct wlan_objmgr_vdev *vdev,
 	struct hdd_station_ctx *hdd_sta_ctx;
 	uint32_t time_buffer_size;
 	struct wlan_hdd_link_info *link_info;
+	bool is_link_switch =
+			wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev);
 
 	if (!hdd_ctx) {
 		hdd_err("hdd_ctx is NULL");
@@ -886,7 +955,14 @@ hdd_cm_connect_failure_pre_user_update(struct wlan_objmgr_vdev *vdev,
 	qdf_mem_zero(hdd_sta_ctx->conn_info.connect_time, time_buffer_size);
 	hdd_init_scan_reject_params(hdd_ctx);
 	hdd_cm_save_connect_status(link_info, rsp->status_code);
-	hdd_conn_remove_connect_info(hdd_sta_ctx);
+	if (!is_link_switch) {
+		/* For link switch connection failure, do not clear existing
+		 * connection info in OSIF.
+		 */
+		hdd_conn_remove_connect_info(hdd_sta_ctx);
+		hdd_adapter_reset_station_ctx(adapter);
+	}
+
 	ucfg_dp_remove_conn_info(vdev);
 	hdd_cm_update_rssi_snr_by_bssid(link_info);
 	hdd_cm_rec_connect_info(rsp);

+ 23 - 14
core/hdd/src/wlan_hdd_cm_disconnect.c

@@ -165,36 +165,39 @@ __hdd_cm_disconnect_handler_pre_user_update(struct wlan_hdd_link_info *link_info
 	hdd_place_marker(adapter, "DISCONNECTED", NULL);
 }
 
-void __hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter,
-						  struct wlan_objmgr_vdev *vdev)
+void
+__hdd_cm_disconnect_handler_post_user_update(struct wlan_hdd_link_info *link_info,
+					     struct wlan_objmgr_vdev *vdev)
 {
+	struct hdd_adapter *adapter = link_info->adapter;
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	struct hdd_station_ctx *sta_ctx;
 	mac_handle_t mac_handle;
 	struct hdd_adapter *link_adapter;
 	struct hdd_station_ctx *link_sta_ctx;
+	bool is_link_switch =
+			wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev);
 
 	mac_handle = hdd_ctx->mac_handle;
-	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
+	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
 
 	/* update P2P connection status */
 	ucfg_p2p_status_disconnect(vdev);
-	hdd_cfr_disconnect(adapter->deflink->vdev);
+	hdd_cfr_disconnect(vdev);
 
 	hdd_wmm_adapter_clear(adapter);
 	ucfg_cm_ft_reset(vdev);
-	ucfg_cm_reset_key(hdd_ctx->pdev, adapter->deflink->vdev_id);
+	ucfg_cm_reset_key(hdd_ctx->pdev, link_info->vdev_id);
 	hdd_clear_roam_profile_ie(adapter);
 
 	if (adapter->device_mode == QDF_STA_MODE)
 		wlan_crypto_reset_vdev_params(vdev);
 
 	hdd_remove_beacon_filter(adapter);
-	if (sme_is_beacon_report_started(mac_handle,
-					 adapter->deflink->vdev_id)) {
+	if (sme_is_beacon_report_started(mac_handle, link_info->vdev_id)) {
 		hdd_debug("Sending beacon pause indication to userspace");
 		hdd_beacon_recv_pause_indication((hdd_handle_t)hdd_ctx,
-						 adapter->deflink->vdev_id,
+						 link_info->vdev_id,
 						 SCAN_EVENT_TYPE_MAX, true);
 	}
 
@@ -208,13 +211,20 @@ void __hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter,
 			hdd_conn_remove_connect_info(link_sta_ctx);
 		}
 	}
-	/* Clear saved connection information in HDD */
-	hdd_conn_remove_connect_info(sta_ctx);
+
+	if (!is_link_switch) {
+		/* Clear saved connection information in HDD */
+		hdd_conn_remove_connect_info(sta_ctx);
+		/* Reset the IEEE link ID to invalid when disconnect is not
+		 * due to link switch.
+		 */
+		hdd_adapter_reset_station_ctx(adapter);
+	}
 
 	ucfg_dp_remove_conn_info(vdev);
 
 	/* Setting the RTS profile to original value */
-	if (sme_cli_set_command(adapter->deflink->vdev_id,
+	if (sme_cli_set_command(link_info->vdev_id,
 				wmi_vdev_param_enable_rtscts,
 				cfg_get(hdd_ctx->psoc,
 					CFG_ENABLE_FW_RTS_PROFILE),
@@ -226,8 +236,7 @@ void __hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter,
 
 	if ((QDF_STA_MODE == adapter->device_mode) ||
 	    (QDF_P2P_CLIENT_MODE == adapter->device_mode)) {
-		sme_ps_disable_auto_ps_timer(mac_handle,
-					     adapter->deflink->vdev_id);
+		sme_ps_disable_auto_ps_timer(mac_handle, link_info->vdev_id);
 		adapter->send_mode_change = true;
 	}
 	wlan_hdd_clear_link_layer_stats(adapter);
@@ -568,7 +577,7 @@ hdd_cm_disconnect_complete_post_user_update(struct wlan_objmgr_vdev *vdev,
 	 */
 	hdd_cm_restore_ch_width(vdev, adapter);
 	hdd_cm_set_default_wlm_mode(adapter);
-	__hdd_cm_disconnect_handler_post_user_update(adapter, vdev);
+	__hdd_cm_disconnect_handler_post_user_update(link_info, vdev);
 	wlan_twt_concurrency_update(hdd_ctx);
 	hdd_cm_reset_udp_qos_upgrade_config(adapter);
 

+ 11 - 6
core/hdd/src/wlan_hdd_debugfs_llstat.c

@@ -78,12 +78,16 @@ void hdd_debugfs_process_iface_stats(struct wlan_hdd_link_info *link_info,
 	buffer += len;
 	ll_stats.len += len;
 	len = scnprintf(buffer, DEBUGFS_LLSTATS_BUF_SIZE - ll_stats.len,
-			"\nmode: %u, MAC_ADDR: %pM, state: %u, roaming: %u, capabilities: %u, SSID: %s, BSSID_MAC: %pM, ap_country_str: %s, country_str: %s",
-			iface_info->mode, &iface_info->macAddr.bytes[0],
+			"\nmode: %u, MAC_ADDR: " QDF_MAC_ADDR_FMT ", state: %u,"
+			" roaming: %u, capabilities: %u, SSID: %s,"
+			" BSSID_MAC: " QDF_MAC_ADDR_FMT
+			", ap_country_str: %s, country_str: %s",
+			iface_info->mode,
+			QDF_MAC_ADDR_REF(&iface_info->macAddr.bytes[0]),
 			iface_info->state, iface_info->roaming,
 			iface_info->capabilities, iface_info->ssid,
-			&iface_info->bssid.bytes[0], iface_info->apCountryStr,
-			iface_info->countryStr);
+			QDF_MAC_ADDR_REF(&iface_info->bssid.bytes[0]),
+			iface_info->apCountryStr, iface_info->countryStr);
 
 	link_stats = &iface_stat->link_stats;
 	average_tsf_offset =  link_stats->avg_bcn_spread_offset_high;
@@ -201,9 +205,10 @@ void hdd_debugfs_process_peer_stats(struct hdd_adapter *adapter, void *data)
 		ll_stats.len += len;
 		len = scnprintf(buffer,
 				DEBUGFS_LLSTATS_BUF_SIZE - ll_stats.len,
-				"\nType: %d, peer_mac: %pM, capabilities: %u\nnum_rates: %d",
+				"\nType: %d, peer_mac: " QDF_MAC_ADDR_FMT
+				", capabilities: %u\nnum_rates: %d",
 				wmi_to_sir_peer_type(peer_info->type),
-				&peer_info->peer_macaddr.bytes[0],
+				QDF_MAC_ADDR_REF(&peer_info->peer_macaddr.bytes[0]),
 				peer_info->capabilities, peer_info->num_rate);
 
 		num_rate = peer_info->num_rate;

+ 2 - 2
core/hdd/src/wlan_hdd_debugfs_offload.c

@@ -100,8 +100,8 @@ wlan_hdd_mc_addr_list_info_debugfs(struct hdd_context *hdd_ctx,
 		}
 
 		ret = scnprintf(buf + length, buf_avail_len - length,
-				QDF_FULL_MAC_FMT "\n",
-				QDF_FULL_MAC_REF(mc_addr_list.mc_addr[i].bytes));
+				QDF_MAC_ADDR_FMT "\n",
+				QDF_MAC_ADDR_REF(mc_addr_list.mc_addr[i].bytes));
 		if (ret <= 0)
 			return length;
 		length += ret;

+ 8 - 8
core/hdd/src/wlan_hdd_debugfs_roam.c

@@ -473,16 +473,16 @@ wlan_hdd_update_roam_stats(struct hdd_context *hdd_ctx,
 			ret = scnprintf(buf + length,
 					buf_avail_len - length,
 					"\nSTA roamed from "
-					QDF_FULL_MAC_FMT " to "
-					QDF_FULL_MAC_FMT "\n",
-					QDF_FULL_MAC_REF(scan->old_bssid),
-					QDF_FULL_MAC_REF(scan->new_bssid));
+					QDF_MAC_ADDR_FMT " to "
+					QDF_MAC_ADDR_FMT "\n",
+					QDF_MAC_ADDR_REF(scan->old_bssid),
+					QDF_MAC_ADDR_REF(scan->new_bssid));
 		} else {
 			ret = scnprintf(buf + length,
 					buf_avail_len - length,
-					"\nSTA is connected to " QDF_FULL_MAC_FMT
+					"\nSTA is connected to " QDF_MAC_ADDR_FMT
 					" before and after scan, not roamed\n",
-					QDF_FULL_MAC_REF(scan->old_bssid));
+					QDF_MAC_ADDR_REF(scan->old_bssid));
 		}
 		if (ret <= 0)
 			goto free_mem;
@@ -523,8 +523,8 @@ wlan_hdd_update_roam_stats(struct hdd_context *hdd_ctx,
 
 			ret = scnprintf(buf + length,
 					buf_avail_len - length,
-					QDF_FULL_MAC_FMT " %4u  %3u   %3u\n",
-					QDF_FULL_MAC_REF(bssid),
+					QDF_MAC_ADDR_FMT " %4u  %3u   %3u\n",
+					QDF_MAC_ADDR_REF(bssid),
 					scan->cand[rci].freq,
 					scan->cand[rci].score,
 					scan->cand[rci].rssi);

+ 17 - 9
core/hdd/src/wlan_hdd_hostapd.c

@@ -132,6 +132,8 @@
 #define HDD_80211_MODE_AC 1
 /* Defines the BIT position of 11ax support mode field of stainfo */
 #define HDD_80211_MODE_AX 2
+/* Defines the BIT position of 11be support mode field of stainfo */
+#define HDD_80211_MODE_BE 4
 
 #define HDD_MAX_CUSTOM_START_EVENT_SIZE 64
 
@@ -497,7 +499,7 @@ static int __hdd_hostapd_open(struct net_device *dev)
 		return ret;
 	}
 
-	ret = hdd_start_adapter(adapter);
+	ret = hdd_start_adapter(adapter, true);
 	if (ret) {
 		hdd_err("Error Initializing the AP mode: %d", ret);
 		return ret;
@@ -806,7 +808,8 @@ static int __hdd_hostapd_set_mac_address(struct net_device *dev, void *addr)
 
 	/* Currently for SL-ML-SAP use same MAC for both MLD and link */
 	hdd_update_dynamic_mac(hdd_ctx, &adapter->mac_addr, &mac_addr);
-	ucfg_dp_update_inf_mac(hdd_ctx->psoc, &adapter->mac_addr, &mac_addr);
+	ucfg_dp_update_intf_mac(hdd_ctx->psoc, &adapter->mac_addr, &mac_addr,
+				adapter->deflink->vdev);
 	memcpy(&adapter->mac_addr, psta_mac_addr->sa_data, ETH_ALEN);
 	qdf_net_update_net_device_dev_addr(dev, psta_mac_addr->sa_data,
 					   ETH_ALEN);
@@ -1517,6 +1520,8 @@ static void hdd_fill_station_info(struct hdd_adapter *adapter,
 					event->ht_caps.present))
 		is_dot11_mode_abgn = false;
 
+	stainfo->support_mode |=
+				(event->eht_caps_present << HDD_80211_MODE_BE);
 	stainfo->support_mode |= is_dot11_mode_abgn << HDD_80211_MODE_ABGN;
 	/* Initialize DHCP info */
 	stainfo->dhcp_phase = DHCP_PHASE_ACK;
@@ -2873,8 +2878,8 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 			return QDF_STATUS_E_NOMEM;
 
 		snprintf(unknownSTAEvent, IW_CUSTOM_MAX,
-			 "JOIN_UNKNOWN_STA-"QDF_FULL_MAC_FMT,
-			 QDF_FULL_MAC_REF(sap_event->sapevt.sapUnknownSTAJoin.macaddr.bytes));
+			 "JOIN_UNKNOWN_STA-"QDF_MAC_ADDR_FMT,
+			 QDF_MAC_ADDR_REF(sap_event->sapevt.sapUnknownSTAJoin.macaddr.bytes));
 		we_event = IWEVCUSTOM;  /* Discovered a new node (AP mode). */
 		wrqu.data.pointer = unknownSTAEvent;
 		wrqu.data.length = strlen(unknownSTAEvent);
@@ -2888,10 +2893,10 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 			return QDF_STATUS_E_NOMEM;
 
 		snprintf(maxAssocExceededEvent, IW_CUSTOM_MAX,
-			 "Peer "QDF_FULL_MAC_FMT" denied"
+			 "Peer "QDF_MAC_ADDR_FMT" denied"
 			 " assoc due to Maximum Mobile Hotspot connections reached. Please disconnect"
 			 " one or more devices to enable the new device connection",
-			 QDF_FULL_MAC_REF(sap_event->sapevt.sapMaxAssocExceeded.macaddr.bytes));
+			 QDF_MAC_ADDR_REF(sap_event->sapevt.sapMaxAssocExceeded.macaddr.bytes));
 		we_event = IWEVCUSTOM;  /* Discovered a new node (AP mode). */
 		wrqu.data.pointer = maxAssocExceededEvent;
 		wrqu.data.length = strlen(maxAssocExceededEvent);
@@ -4240,7 +4245,9 @@ hdd_indicate_peers_deleted(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
 	hdd_sap_indicate_disconnect_for_sta(link_info->adapter);
 }
 
-QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter, bool reinit)
+QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter,
+			    bool reinit,
+			    bool rtnl_held)
 {
 	struct hdd_hostapd_state *phostapdBuf;
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
@@ -4373,7 +4380,7 @@ QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter, bool reinit)
 	return status;
 
 error_release_softap_tx_rx:
-	hdd_unregister_wext(adapter->dev);
+	hdd_wext_unregister(adapter->dev, rtnl_held);
 error_deinit_sap_session:
 	hdd_hostapd_deinit_sap_session(adapter->deflink);
 error_release_vdev:
@@ -6143,7 +6150,8 @@ static QDF_STATUS wlan_hdd_mlo_update(struct wlan_hdd_link_info *link_info)
 
 	is_ml_ap = wlan_vdev_mlme_is_mlo_ap(link_info->vdev);
 	if (!policy_mgr_is_mlo_sap_concurrency_allowed(hdd_ctx->psoc,
-						       is_ml_ap)) {
+						       is_ml_ap,
+						       wlan_vdev_get_id(link_info->vdev))) {
 		hdd_err("MLO SAP concurrency check fails");
 		return QDF_STATUS_E_INVAL;
 	}

+ 4 - 1
core/hdd/src/wlan_hdd_hostapd.h

@@ -242,12 +242,15 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
  * hdd_init_ap_mode() - to init the AP adaptor
  * @adapter: SAP/GO adapter
  * @reinit: true if re-init, otherwise initial init
+ * @rtnl_held: true if rtnl lock is taken, otherwise false
  *
  * This API can be called to open the SAP session as well as
  * to create and store the vdev object. It also initializes necessary
  * SAP adapter related params.
  */
-QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter, bool reinit);
+QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter,
+			    bool reinit,
+			    bool rtnl_held);
 
 /**
  * hdd_deinit_ap_mode() - to deinit the AP adaptor

+ 4 - 4
core/hdd/src/wlan_hdd_hostapd_wext.c

@@ -2298,9 +2298,9 @@ static int hdd_softap_get_sta_info(struct hdd_adapter *adapter,
 		}
 
 		written += scnprintf(buf + written, size - written,
-				     QDF_FULL_MAC_FMT
+				     QDF_MAC_ADDR_FMT
 				     " ecsa=%d\n",
-				     QDF_FULL_MAC_REF(sta->sta_mac.bytes),
+				     QDF_MAC_ADDR_REF(sta->sta_mac.bytes),
 				     sta->ecsa_capable);
 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta, true,
 				     STA_INFO_SOFTAP_GET_STA_INFO);
@@ -2683,8 +2683,8 @@ __iw_get_peer_rssi(struct net_device *dev, struct iw_request_info *info,
 		wrqu->data.length +=
 			scnprintf(extra + wrqu->data.length,
 				  IW_PRIV_SIZE_MASK - wrqu->data.length,
-				  "["QDF_FULL_MAC_FMT"] [%d]\n",
-				  QDF_FULL_MAC_REF(rssi_info->peer_stats[i].peer_macaddr),
+				  "["QDF_MAC_ADDR_FMT"] [%d]\n",
+				  QDF_MAC_ADDR_REF(rssi_info->peer_stats[i].peer_macaddr),
 				  rssi_info->peer_stats[i].peer_rssi);
 
 	wrqu->data.length++;

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.