qcacld-3.0: Add support for STA+NAN+NDI+NDI

Add support for four port concurrency for
STA+NAN discovery + NDI + NDI.

Change-Id: I7d6d3f482a61bef7f3d0a31eee3fdfe5e5e9d879
CRs-Fixed: 2633982
diff --git a/Kbuild b/Kbuild
index 12409ea..7230409 100644
--- a/Kbuild
+++ b/Kbuild
@@ -3162,6 +3162,7 @@
 cppflags-$(CONFIG_SLUB_DEBUG_ON) += -DHAL_CONFIG_SLUB_DEBUG_ON
 
 ccflags-$(CONFIG_FOURTH_CONNECTION) += -DFEATURE_FOURTH_CONNECTION
+ccflags-$(CONFIG_FOURTH_CONNECTION_AUTO) += -DFOURTH_CONNECTION_AUTO
 ccflags-$(CONFIG_WMI_SEND_RECV_QMI) += -DWLAN_FEATURE_WMI_SEND_RECV_QMI
 
 cppflags-$(CONFIG_WDI3_STATS_UPDATE) += -DWDI3_STATS_UPDATE
diff --git a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h
index ff246f6..0deb382 100644
--- a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h
+++ b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h
@@ -803,6 +803,14 @@
  * SCC, SAP on 5 G
  * @PM_SAP_NDI_SCC_5_NAN_DISC_24_DBS: SAP & NDI/NDP connection on 5 Ghz,
  * NAN_DISC on 24 Ghz
+ * @PM_NAN_DISC_STA_24_NDI_5_DBS: STA and NAN Disc on 2.4Ghz and NDI on 5ghz DBS
+ * @PM_NAN_DISC_NDI_24_STA_5_DBS: NDI and NAN Disc on 2.4Ghz and STA on 5ghz DBS
+ * @PM_STA_NDI_5_NAN_DISC_24_DBS: STA, NDI on 5ghz and NAN Disc on 2.4Ghz DBS
+ * @PM_STA_NDI_NAN_DISC_24_SMM: STA, NDI, NAN Disc all on 2.4ghz SMM
+ * @PM_NAN_DISC_NDI_24_NDI_5_DBS: NDI and NAN Disc on 2.4Ghz and second NDI in
+ * 5ghz DBS
+ * @PM_NDI_NDI_5_NAN_DISC_24_DBS: Both NDI on 5ghz and NAN Disc on 2.4Ghz DBS
+ * @PM_NDI_NDI_NAN_DISC_24_SMM: Both NDI, NAN Disc on 2.4ghz SMM
  */
 enum policy_mgr_three_connection_mode {
 	PM_STA_SAP_SCC_24_SAP_5_DBS,
@@ -812,6 +820,13 @@
 	PM_NAN_DISC_SAP_SCC_24_NDI_5_DBS,
 	PM_NAN_DISC_NDI_SCC_24_SAP_5_DBS,
 	PM_SAP_NDI_SCC_5_NAN_DISC_24_DBS,
+	PM_NAN_DISC_STA_24_NDI_5_DBS,
+	PM_NAN_DISC_NDI_24_STA_5_DBS,
+	PM_STA_NDI_5_NAN_DISC_24_DBS,
+	PM_STA_NDI_NAN_DISC_24_SMM,
+	PM_NAN_DISC_NDI_24_NDI_5_DBS,
+	PM_NDI_NDI_5_NAN_DISC_24_DBS,
+	PM_NDI_NDI_NAN_DISC_24_SMM,
 
 	PM_MAX_THREE_CONNECTION_MODE
 };
diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c
index dfd57ab..6f702a2 100644
--- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c
+++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c
@@ -2114,38 +2114,48 @@
 {
 	uint32_t i;
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	uint8_t sap_cnt, go_cnt;
 
 	/* new STA may just have ssid, no channel until bssid assigned */
 	if (ch_freq == 0 && mode == PM_STA_MODE)
 		return true;
 
-	pm_ctx = policy_mgr_get_context(psoc);
-	if (!pm_ctx) {
-		policy_mgr_err("context is NULL");
+	sap_cnt = policy_mgr_mode_specific_connection_count(psoc,
+							    PM_SAP_MODE, NULL);
+
+	go_cnt = policy_mgr_mode_specific_connection_count(psoc,
+							   PM_P2P_GO_MODE, NULL);
+	if (sap_cnt || go_cnt) {
+		pm_ctx = policy_mgr_get_context(psoc);
+		if (!pm_ctx) {
+			policy_mgr_err("context is NULL");
+			return false;
+		}
+
+		if (policy_mgr_get_mcc_to_scc_switch_mode(psoc) !=
+		    QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION) {
+			policy_mgr_err("couldn't start 4th port for bad force scc cfg");
+			return false;
+		}
+		if (pm_ctx->cfg.dual_mac_feature ||
+		    !pm_ctx->cfg.sta_sap_scc_on_dfs_chnl  ||
+		    !pm_ctx->cfg.sta_sap_scc_on_lte_coex_chnl) {
+			policy_mgr_err(
+				"Couldn't start 4th port for bad cfg of dual mac, dfs scc, lte coex scc");
+			return false;
+		}
+
+		for (i = 0; i < pcl.pcl_len; i++)
+			if (ch_freq == pcl.pcl_list[i])
+				return true;
+
+		policy_mgr_err("4th port failed on ch freq %d with mode %d",
+			       ch_freq, mode);
+
 		return false;
 	}
 
-	if (policy_mgr_get_mcc_to_scc_switch_mode(psoc) !=
-	    QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION) {
-		policy_mgr_err("couldn't start 4th port for bad force scc cfg");
-		return false;
-	}
-	if (pm_ctx->cfg.dual_mac_feature ||
-	    !pm_ctx->cfg.sta_sap_scc_on_dfs_chnl  ||
-	    !pm_ctx->cfg.sta_sap_scc_on_lte_coex_chnl) {
-		policy_mgr_err(
-			"Couldn't start 4th port for bad cfg of dual mac, dfs scc, lte coex scc");
-		return false;
-	}
-
-	for (i = 0; i < pcl.pcl_len; i++)
-		if (ch_freq == pcl.pcl_list[i])
-			return true;
-
-	policy_mgr_err("4th port failed on ch freq %d with mode %d",
-		       ch_freq, mode);
-
-	return false;
+	return true;
 }
 #else
 static inline bool policy_mgr_is_concurrency_allowed_4_port(
diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c
index 98cfb14..6d2c304 100644
--- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c
+++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c
@@ -682,9 +682,19 @@
 	/* Will be enhanced for other types of 4 port conc (NaN etc.)
 	 * in future.
 	 */
+	if (!policy_mgr_is_hw_dbs_capable(psoc)) {
+		policy_mgr_err("Can't find index for 4th port pcl table for non dbs capable");
+		return PM_MAX_PCL_TYPE;
+	}
+
+	/* SAP and P2P Go have same result in 4th port pcl table */
+	if (mode == PM_SAP_MODE || mode == PM_P2P_GO_MODE) {
+		mode = PM_SAP_MODE;
+	}
+
 	if (mode != PM_STA_MODE && mode != PM_SAP_MODE &&
-	    mode != PM_P2P_GO_MODE) {
-		policy_mgr_err("Can't start 4th port if not STA, SAP");
+	    mode != PM_NDI_MODE) {
+		policy_mgr_err("Can't start 4th port if not STA, SAP, NDI");
 		return PM_MAX_PCL_TYPE;
 	}
 
@@ -696,14 +706,9 @@
 	}
 	policy_mgr_debug("Index for 4th port pcl table: %d", fourth_index);
 
-	if (policy_mgr_is_hw_dbs_capable(psoc) == true) {
-		pcl = fourth_connection_pcl_dbs_table
-			[fourth_index][mode][pref];
-		return pcl;
-	}
-	policy_mgr_err("Can't find index for 4th port pcl table for non dbs capable");
+	pcl = fourth_connection_pcl_dbs_table[fourth_index][mode][pref];
 
-	return PM_MAX_PCL_TYPE;
+	return pcl;
 }
 #else
 static inline enum policy_mgr_pcl_type policy_mgr_get_pcl_4_port(
@@ -1932,6 +1937,52 @@
 		} else {
 			index = PM_MAX_THREE_CONNECTION_MODE;
 		}
+	} else if (count_nan_disc == 1 && count_ndi == 1 && count_sta == 1) {
+		/* Policy mgr only considers NAN Disc ch in 2.4GHz */
+		if (WLAN_REG_IS_24GHZ_CH_FREQ(
+			pm_conc_connection_list[list_sta[0]].freq) &&
+		    WLAN_REG_IS_5GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq)) {
+			index = PM_NAN_DISC_STA_24_NDI_5_DBS;
+		} else if (WLAN_REG_IS_5GHZ_CH_FREQ(
+			pm_conc_connection_list[list_sta[0]].freq) &&
+			   WLAN_REG_IS_24GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq)) {
+			index = PM_NAN_DISC_NDI_24_STA_5_DBS;
+		} else if (WLAN_REG_IS_5GHZ_CH_FREQ(
+			pm_conc_connection_list[list_sta[0]].freq) &&
+			  WLAN_REG_IS_5GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq)) {
+			index = PM_STA_NDI_5_NAN_DISC_24_DBS;
+		} else if (WLAN_REG_IS_24GHZ_CH_FREQ(
+			pm_conc_connection_list[list_sta[0]].freq) &&
+			  WLAN_REG_IS_24GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq)) {
+			index = PM_STA_NDI_NAN_DISC_24_SMM;
+		}
+	} else if (count_nan_disc == 1 && count_ndi == 2) {
+		/* Policy mgr only considers NAN Disc ch in 2.4GHz */
+		if (WLAN_REG_IS_24GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq) &&
+		    WLAN_REG_IS_5GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[1]].freq)) {
+			index = PM_NAN_DISC_NDI_24_NDI_5_DBS;
+		} else if (WLAN_REG_IS_5GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq) &&
+			   WLAN_REG_IS_24GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq)) {
+			index = PM_NAN_DISC_NDI_24_NDI_5_DBS;
+		} else if (WLAN_REG_IS_5GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq) &&
+			  WLAN_REG_IS_5GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq)) {
+			index = PM_NDI_NDI_5_NAN_DISC_24_DBS;
+		} else if (WLAN_REG_IS_24GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq) &&
+			  WLAN_REG_IS_24GHZ_CH_FREQ(
+			pm_conc_connection_list[list_ndi[0]].freq)) {
+			index = PM_NDI_NDI_NAN_DISC_24_SMM;
+		}
 	}
 
 	policy_mgr_debug(
diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_tables_2x2_dbs_i.h b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_tables_2x2_dbs_i.h
index 45d8453..dc4da92 100644
--- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_tables_2x2_dbs_i.h
+++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_tables_2x2_dbs_i.h
@@ -1943,8 +1943,9 @@
 /**
  * fourth_connection_pcl_dbs_table - table which provides PCL for
  * the 4th connection, when we have 3 connections already in
- * the system (with DBS supported by HW)
+ * the system (with DBS supported by HW), this table is for auto products.
  */
+#ifdef FOURTH_CONNECTION_AUTO
 const enum policy_mgr_pcl_type
 fourth_connection_pcl_dbs_table
 	[PM_MAX_THREE_CONNECTION_MODE][PM_MAX_NUM_OF_MODE]
@@ -1964,6 +1965,35 @@
 	[PM_SAP_NDI_SCC_5_NAN_DISC_24_DBS] = {
 	[PM_SAP_MODE] = { PM_24G, PM_24G, PM_24G } }
 };
+#else
+/**
+ * fourth_connection_pcl_dbs_table - table which provides PCL for
+ * the 4th connection, when we have 3 connections already in
+ * the system (with DBS supported by HW), this table is for mobile products
+ * If you want to support any 4 port other than the below in MCL add below as
+ * other concurrencies supported by auto may not be PORed for mobile products
+ * and vice-versa.
+ */
+const enum policy_mgr_pcl_type
+fourth_connection_pcl_dbs_table
+	[PM_MAX_THREE_CONNECTION_MODE][PM_MAX_NUM_OF_MODE]
+	[PM_MAX_CONC_PRIORITY_MODE] = {
+	[PM_NAN_DISC_STA_24_NDI_5_DBS] = {
+	[PM_NDI_MODE] = { PM_5G, PM_5G, PM_5G } },
+	[PM_NAN_DISC_NDI_24_STA_5_DBS] = {
+	[PM_NDI_MODE] = { PM_5G, PM_5G, PM_5G } },
+	[PM_STA_NDI_5_NAN_DISC_24_DBS] = {
+	[PM_NDI_MODE] = { PM_5G, PM_5G, PM_5G } },
+	[PM_STA_NDI_NAN_DISC_24_SMM] = {
+	[PM_NDI_MODE] = { PM_5G, PM_5G, PM_5G } },
+	[PM_NAN_DISC_NDI_24_NDI_5_DBS] = {
+	[PM_STA_MODE] = { PM_5G, PM_5G, PM_5G } },
+	[PM_NDI_NDI_5_NAN_DISC_24_DBS] = {
+	[PM_STA_MODE] = { PM_5G, PM_5G, PM_5G } },
+	[PM_NDI_NDI_NAN_DISC_24_SMM] = {
+	[PM_STA_MODE] = { PM_5G, PM_5G, PM_5G } }
+};
+#endif
 #endif
 
 /**
diff --git a/components/nan/core/inc/nan_public_structs.h b/components/nan/core/inc/nan_public_structs.h
index 40eedf6..15e612b 100644
--- a/components/nan/core/inc/nan_public_structs.h
+++ b/components/nan/core/inc/nan_public_structs.h
@@ -795,6 +795,8 @@
  * @nan_sap_supported: Target supports NAN Discovery with SAP concurrency
  * @ndi_sap_supported: Target supports NAN Datapth with SAP concurrency
  * @nan_vdev_allowed: Allow separate vdev creation for NAN discovery
+ * @sta_nan_ndi_ndi_allowed: 4 port concurrency of STA+NAN+NDI+NDI is supported
+ * by Fw or not.
  */
 struct nan_tgt_caps {
 	uint32_t nan_disable_supported:1;
@@ -803,6 +805,7 @@
 	uint32_t nan_sap_supported:1;
 	uint32_t ndi_sap_supported:1;
 	uint32_t nan_vdev_allowed:1;
+	uint32_t sta_nan_ndi_ndi_allowed:1;
 };
 
 #endif
diff --git a/components/nan/dispatcher/inc/nan_ucfg_api.h b/components/nan/dispatcher/inc/nan_ucfg_api.h
index 1b94239..93d039d 100644
--- a/components/nan/dispatcher/inc/nan_ucfg_api.h
+++ b/components/nan/dispatcher/inc/nan_ucfg_api.h
@@ -370,6 +370,15 @@
 bool ucfg_nan_is_vdev_creation_allowed(struct wlan_objmgr_psoc *psoc);
 
 /**
+ * ucfg_nan_is_sta_nan_ndi_4_port_allowed- Get support for 4 port (STA +
+ * NAN Disc + NDI + NDI)
+ * @psoc: pointer to psoc object
+ *
+ * Return: True if 4 port concurrency allowed or not.
+ */
+bool ucfg_nan_is_sta_nan_ndi_4_port_allowed(struct wlan_objmgr_psoc *psoc);
+
+/**
  * ucfg_nan_get_is_separate_nan_iface() - get is_separate_nan_iface value
  * @psoc: pointer to psoc object
  *
@@ -451,6 +460,12 @@
 }
 
 static inline
+bool ucfg_nan_is_sta_nan_ndi_4_port_allowed(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
+
+static inline
 bool ucfg_nan_get_is_separate_nan_iface(struct wlan_objmgr_psoc *psoc)
 {
 	return false;
diff --git a/components/nan/dispatcher/src/nan_ucfg_api.c b/components/nan/dispatcher/src/nan_ucfg_api.c
index 0a40958..33e7682 100644
--- a/components/nan/dispatcher/src/nan_ucfg_api.c
+++ b/components/nan/dispatcher/src/nan_ucfg_api.c
@@ -1076,7 +1076,13 @@
 		if (wlan_vdev_get_id(vdev) == vdev_id_list[id])
 			return true;
 
-	return false;
+	/* If the flow reaches here then it is 4th NDI with STA */
+	if (!ucfg_nan_is_sta_nan_ndi_4_port_allowed(psoc))
+		return false;
+
+	/* The final freq would be provided by FW, it is not known now */
+	return policy_mgr_allow_concurrency(psoc, PM_NDI_MODE, 0,
+					    HW_MODE_20_MHZ);
 }
 
 bool ucfg_nan_is_vdev_creation_allowed(struct wlan_objmgr_psoc *psoc)
@@ -1092,6 +1098,20 @@
 	return psoc_nan_obj->nan_caps.nan_vdev_allowed;
 }
 
+bool
+ucfg_nan_is_sta_nan_ndi_4_port_allowed(struct wlan_objmgr_psoc *psoc)
+{
+	struct nan_psoc_priv_obj *psoc_nan_obj;
+
+	psoc_nan_obj = nan_get_psoc_priv_obj(psoc);
+	if (!psoc_nan_obj) {
+		nan_err("psoc_nan_obj is null");
+		return false;
+	}
+
+	return psoc_nan_obj->nan_caps.sta_nan_ndi_ndi_allowed;
+}
+
 bool ucfg_nan_get_is_separate_nan_iface(struct wlan_objmgr_psoc *psoc)
 {
 	struct nan_psoc_priv_obj *nan_obj = nan_get_psoc_priv_obj(psoc);
diff --git a/configs/default_defconfig b/configs/default_defconfig
index 40f87c9..b945496 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -891,6 +891,7 @@
 CONFIG_CONVERGED_P2P_ENABLE := y
 CONFIG_WLAN_POLICY_MGR_ENABLE := y
 CONFIG_FEATURE_BLACKLIST_MGR := y
+CONFIG_FOURTH_CONNECTION := y
 CONFIG_SUPPORT_11AX := y
 CONFIG_HDD_INIT_WITH_RTNL_LOCK := y
 CONFIG_WLAN_CONV_SPECTRAL_ENABLE := y
diff --git a/configs/qca6390_defconfig b/configs/qca6390_defconfig
index a8ae193..15bbe73 100644
--- a/configs/qca6390_defconfig
+++ b/configs/qca6390_defconfig
@@ -784,6 +784,7 @@
 endif
 
 CONFIG_FOURTH_CONNECTION := y
+CONFIG_FOURTH_CONNECTION_AUTO := y
 CONFIG_SAP_DHCP_FW_IND := y
 
 #Enable FW Offload
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index c08f197..93a7587 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -20404,9 +20404,12 @@
 	}
 	/*
 	 * STA+NDI concurrency gets preference over NDI+NDI. Disable
-	 * first NDI in case an NDI+NDI concurrency exists.
+	 * first NDI in case an NDI+NDI concurrency exists if FW does
+	 * not support 4 port concurrency of two NDI + NAN with STA.
 	 */
-	ucfg_nan_check_and_disable_unsupported_ndi(hdd_ctx->psoc, false);
+	if (!ucfg_nan_is_sta_nan_ndi_4_port_allowed(hdd_ctx->psoc))
+		ucfg_nan_check_and_disable_unsupported_ndi(hdd_ctx->psoc,
+							   false);
 
 	/*
 	 * In STA + STA roaming scenario, connection to same ssid but different
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 2ad152a..6986fc7 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -5247,6 +5247,10 @@
 
 	if (wmi_service_enabled(wma_handle->wmi_handle, wmi_service_nan_vdev))
 		tgt_cfg->nan_caps.nan_vdev_allowed = 1;
+
+	if (wmi_service_enabled(wma_handle->wmi_handle,
+				wmi_service_sta_nan_ndi_four_port))
+		tgt_cfg->nan_caps.sta_nan_ndi_ndi_allowed = 1;
 }
 #else
 static void wma_update_nan_target_caps(tp_wma_handle wma_handle,