Merge "qca-wifi: Add srng history for monitor mode"
diff --git a/dp/src/dp_rate_stats.c b/dp/src/dp_rate_stats.c
index a0615e2..1bd4e84 100644
--- a/dp/src/dp_rate_stats.c
+++ b/dp/src/dp_rate_stats.c
@@ -309,7 +309,7 @@
 		stats_ctx = (struct wlan_peer_rate_stats_ctx *)
 				ppdu_user->cookie;
 
-		if (qdf_unlikely(!ppdu_user->tx_ratekbps ||
+		if (qdf_unlikely(!ppdu_user->tx_ratekbps || !ppdu_user->rix ||
 				 ppdu_user->rix > DP_RATE_TABLE_SIZE)) {
 			continue;
 		}
@@ -321,11 +321,6 @@
 			continue;
 		}
 
-		if (qdf_unlikely(!ppdu_user->tx_ratekbps || !ppdu_user->rix ||
-				 ppdu_user->rix > DP_RATE_TABLE_SIZE)) {
-			continue;
-		}
-
 		tx_stats = &stats_ctx->tx;
 		RATE_STATS_LOCK_ACQUIRE(&tx_stats->lock);
 
diff --git a/dp/wifi3.0/dp_full_mon.c b/dp/wifi3.0/dp_full_mon.c
index 8821c01..94f059d 100644
--- a/dp/wifi3.0/dp_full_mon.c
+++ b/dp/wifi3.0/dp_full_mon.c
@@ -73,6 +73,7 @@
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			  "%s %d : HAL Monitor Status Ring Init Failed -- %pK",
 			  __func__, __LINE__, mon_status_srng);
+		QDF_ASSERT(0);
 		return status;
 	}
 
@@ -84,6 +85,7 @@
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			  "%s %d : HAL SRNG access Failed -- %pK",
 			  __func__, __LINE__, mon_status_srng);
+		QDF_ASSERT(0);
 		return status;
 	}
 
diff --git a/dp/wifi3.0/dp_tx_capture.c b/dp/wifi3.0/dp_tx_capture.c
index a879293..b36ffc2 100644
--- a/dp/wifi3.0/dp_tx_capture.c
+++ b/dp/wifi3.0/dp_tx_capture.c
@@ -3643,7 +3643,8 @@
 			dp_tx_cap_peer_unref_del(peer);
 		if (!(type == IEEE80211_FC0_TYPE_MGT &&
 		    (subtype == MGMT_SUBTYPE_PROBE_RESP >> 4 ||
-		     subtype == MGMT_SUBTYPE_DISASSOC >> 4))) {
+		     subtype == MGMT_SUBTYPE_DISASSOC >> 4 ||
+		     subtype == MGMT_SUBTYPE_DEAUTH >> 4))) {
 			if (!dp_peer_or_pdev_tx_cap_enabled(pdev, NULL,
 							    ppdu_desc->user[0]
 							    .mac_addr)) {
@@ -3831,7 +3832,8 @@
 
 			if (type == IEEE80211_FC0_TYPE_MGT &&
 			    (subtype == MGMT_SUBTYPE_PROBE_RESP >> 4 ||
-			     subtype == MGMT_SUBTYPE_DISASSOC >> 4)) {
+			     subtype == MGMT_SUBTYPE_DISASSOC >> 4 ||
+			     subtype == MGMT_SUBTYPE_DEAUTH >> 4)) {
 				if (!dp_peer_or_pdev_tx_cap_enabled(pdev,
 								    NULL,
 								    wh->i_addr1
diff --git a/qca_multi_link/inc/qca_multi_link.h b/qca_multi_link/inc/qca_multi_link.h
index b997b32..f9bf565 100644
--- a/qca_multi_link/inc/qca_multi_link.h
+++ b/qca_multi_link/inc/qca_multi_link.h
@@ -23,6 +23,7 @@
 #include <qdf_util.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/version.h>
 #include <linux/wireless.h>
 #include <net/cfg80211.h>
 #include <br_private.h>
diff --git a/qca_multi_link/src/qca_multi_link_tbl.c b/qca_multi_link/src/qca_multi_link_tbl.c
index 7d7d98e..634e5a3 100644
--- a/qca_multi_link/src/qca_multi_link_tbl.c
+++ b/qca_multi_link/src/qca_multi_link_tbl.c
@@ -45,11 +45,22 @@
 	 */
 	rcu_read_lock();
 	for (i = 0; i < BR_HASH_SIZE ; i++) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 24)
 		hlist_for_each_entry_rcu(search_fdb, &p->br->hash[i], hlist) {
+#else
+		hlist_for_each_entry_rcu(search_fdb, &p->br->fdb_list,
+					 fdb_node) {
+#endif
 			ndev = search_fdb->dst ? search_fdb->dst->dev : NULL;
 			wdev = ndev ? ndev->ieee80211_ptr : NULL;
 			if (!wdev && ndev) {
-				memcpy(qfdb->qal_mac_addr, search_fdb->addr.addr, 6);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 24)
+				memcpy(qfdb->qal_mac_addr,
+				       search_fdb->addr.addr, 6);
+#else
+				memcpy(qfdb->qal_mac_addr,
+				       search_fdb->key.addr.addr, 6);
+#endif
 				qfdb->qal_fdb_dev = ndev;
 				qfdb->qal_fdb_is_local =  search_fdb->is_local;
 				num_of_entries++;
@@ -89,7 +100,12 @@
 
 	rcu_read_lock();
 	for (i = 0; i < BR_HASH_SIZE; i++) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 24)
 		hlist_for_each_entry_rcu(search_fdb, &p->br->hash[i], hlist) {
+#else
+		hlist_for_each_entry_rcu(search_fdb, &p->br->fdb_list,
+					 fdb_node) {
+#endif
 			if (!search_fdb->is_local)
 				continue;
 
@@ -112,8 +128,14 @@
 
 QDF_STATUS qca_multi_link_tbl_delete_entry(struct net_device *net_dev, uint8_t *addr)
 {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 24)
 	int status;
+#endif
 	struct net_bridge_fdb_entry *fdb_entry = NULL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 24)
+	struct net_bridge_port *fdb_port = NULL;
+	struct net_bridge *br = NULL;
+#endif
 
 	fdb_entry = br_fdb_has_entry(net_dev, addr, 0);
 	if (!fdb_entry) {
@@ -124,10 +146,25 @@
 		return QDF_STATUS_SUCCESS;
 	}
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 24)
+	fdb_port = br_port_get_rcu(net_dev);
+	if (!fdb_port) {
+		qdf_err("fdb port is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	br = fdb_port->br;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 24)
 	status = br_fdb_delete_by_netdev(net_dev, addr, 0);
 	if (status < 0) {
 		return QDF_STATUS_E_FAILURE;
 	}
+#else
+	/* Use 5.4-specific API */
+	qdf_info("Needs alternative implementation");
+#endif
 	return QDF_STATUS_SUCCESS;
 }
 
diff --git a/tools/linux/cfg80211_ven_cmd.h b/tools/linux/cfg80211_ven_cmd.h
index fbd1e43..4a95784 100644
--- a/tools/linux/cfg80211_ven_cmd.h
+++ b/tools/linux/cfg80211_ven_cmd.h
@@ -762,6 +762,11 @@
 	IEEE80211_PARAM_OCE_IP_SUBNET_ID           = 697, /* IP subnet identifier value to be advertised as OCE attribute in Beacon and  Probe response frame */
 	IEEE80211_PARAM_OCE_ADD_ESS_RPT            = 698, /* Add ESS Report */
 	IEEE80211_PARAM_RSNX_OVERRIDE              = 700,
+#if QCA_AIRTIME_FAIRNESS && WLAN_ATF_STATS
+	IEEE80211_PARAM_ATF_ENABLE_STATS           = 701,
+	IEEE80211_PARAM_ATF_STATS_TIMEOUT          = 702,
+	IEEE80211_PARAM_ATF_GET_STATS              = 703,
+#endif
 };
 
 enum {
@@ -1190,6 +1195,8 @@
 	OL_ATH_PARAM_NXT_RDR_FREQ = 444,
 	/* set the flag for a radio with no backhaul */
 	OL_ATH_PARAM_NO_BACKHAUL_RADIO = 445,
+	/* MAX_PHY feature flag per PDEV */
+	OL_ATH_PARAM_RPT_MAX_PHY = 446,
 
 };
 
@@ -1677,6 +1684,13 @@
 	{"get_commitatf",       IEEE80211_PARAM_ATF_OPT, GET_PARAM, 0},
 	{"perunit",             IEEE80211_PARAM_ATF_PER_UNIT, SET_PARAM, 1},
 	{"get_perunit",         IEEE80211_PARAM_ATF_PER_UNIT, GET_PARAM, 0},
+#if WLAN_ATF_STATS
+	{"enable_atf_stats",    IEEE80211_PARAM_ATF_ENABLE_STATS, SET_PARAM, 1},
+	{"g_enable_atf_stats",  IEEE80211_PARAM_ATF_ENABLE_STATS, GET_PARAM, 0},
+	{"atf_stats_timeout",   IEEE80211_PARAM_ATF_STATS_TIMEOUT, SET_PARAM, 1},
+	{"g_atf_stats_timeout", IEEE80211_PARAM_ATF_STATS_TIMEOUT, GET_PARAM, 0},
+	{"get_atf_stats",       IEEE80211_PARAM_ATF_GET_STATS, GET_PARAM, 0},
+#endif
 #endif
 	{"get_minpower",        IEEE80211_PARAM_TX_MIN_POWER, GET_PARAM, 0},
 	{"get_maxpower",        IEEE80211_PARAM_TX_MAX_POWER, GET_PARAM, 0},
@@ -2010,7 +2024,7 @@
 	{"whc_mixedbh_bh_type", IEEE80211_PARAM_WHC_BACKHAUL_TYPE, SET_PARAM, 1},
 	{"he_bsr_supp",         IEEE80211_PARAM_HE_BSR_SUPPORT, SET_PARAM, 1},
 	{"get_he_bsr_supp",     IEEE80211_PARAM_HE_BSR_SUPPORT, GET_PARAM, 0},
-	{"display_me_info",     IEEE80211_PARAM_DUMP_RA_TABLE, SET_PARAM, 1},
+	{"display_me_info",     IEEE80211_PARAM_DUMP_RA_TABLE, GET_PARAM, 0},
 	{"set_obss_ru_tolerance_time",  IEEE80211_PARAM_OBSS_NB_RU_TOLERANCE_TIME,
 		SET_PARAM, 1},
 	{"get_obss_ru_tolerance_time",  IEEE80211_PARAM_OBSS_NB_RU_TOLERANCE_TIME,
@@ -2207,12 +2221,10 @@
 		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_BCN_BURST, SET_PARAM, 1},
 	{"get_bcnburst",
 		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_BCN_BURST, GET_PARAM, 0},
-#if UMAC_SUPPORT_PERIODIC_PERFSTATS
 	{"dcs_enable",
-		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_PRDPERFSTAT_THRPUT_ENAB, SET_PARAM, 1},
+		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_DCS, SET_PARAM, 1},
 	{"get_dcs_enable",
-		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_PRDPERFSTAT_THRPUT_ENAB, GET_PARAM, 0},
-#endif
+		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_DCS, GET_PARAM, 0},
 	{"get_total_PER",
 		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_TOTAL_PER, GET_PARAM, 0},
 	{"setctsrate",
@@ -2743,8 +2755,6 @@
 		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_ICM_ACTIVE, SET_PARAM, 1},
 	{"get_icm_active",
 		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_ICM_ACTIVE, GET_PARAM, 0},
-	{"get_nominal_noisefloor",
-		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_NOMINAL_NOISEFLOOR, GET_PARAM, 0},
 	{"acs_rank_en",
 		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_ACS_RANK, SET_PARAM, 1},
 	{"g_acs_rank_en",
@@ -3007,6 +3017,10 @@
 		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_NXT_RDR_FREQ, SET_PARAM, 1},
 	{"getNxtRadarFreq",
 		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_NXT_RDR_FREQ, GET_PARAM, 0},
+	{"rpt_max_phy",
+		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_RPT_MAX_PHY, SET_PARAM, 1},
+	{"g_rpt_max_phy",
+		OL_ATH_PARAM_SHIFT | OL_ATH_PARAM_RPT_MAX_PHY, GET_PARAM, 0},
 	{"setCountryID",
 		OL_SPECIAL_PARAM_SHIFT | OL_SPECIAL_PARAM_COUNTRY_ID, SET_PARAM, 1},
 	{"getCountryID",
diff --git a/umac/dfs/core/src/misc/dfs_zero_cac.c b/umac/dfs/core/src/misc/dfs_zero_cac.c
index a96af57..41bc5e7 100644
--- a/umac/dfs/core/src/misc/dfs_zero_cac.c
+++ b/umac/dfs/core/src/misc/dfs_zero_cac.c
@@ -1953,23 +1953,104 @@
 }
 #endif
 
+#ifdef QCA_SUPPORT_AGILE_DFS
+#ifdef CONFIG_CHAN_FREQ_API
+/* Checks the Host side agile configurations. ie if agile channel
+ * is configured as 5730MHz and the agile channel width is 80P80/165MHz.
+ */
+#define IS_HOST_AGILE_CURCHAN_165MHZ(_x) \
+	((_x)->dfs_agile_precac_freq_mhz == \
+	 RESTRICTED_80P80_CHAN_CENTER_FREQ) && \
+	((_x)->dfs_precac_chwidth == CH_WIDTH_80P80MHZ)
+
+/* Checks if the FW Agile operation was on the restricited 80P80MHz,
+ * by comparing the center frequency 1 with 5690MHz, center frequency 2
+ * with 5775MHz and the channel width was 80P80/165MHz.
+ */
+#define IS_OCAC_EVENT_ON_165_MHZ_CHAN(_x, _y, _z) \
+	((_x) == RESTRICTED_80P80_LEFT_80_CENTER_FREQ) && \
+	((_y) == RESTRICTED_80P80_RIGHT_80_CENTER_FREQ) && \
+	((_z) == CH_WIDTH_80P80MHZ)
+
+/*
+ * dfs_is_ocac_complete_event_for_cur_agile_chan() - Check if the OCAC
+ * completion event from FW is received for the currently configured agile
+ * channel in host.
+ *
+ * @dfs: Pointer to dfs structure.
+ * @center_freq_mhz1: Center frequency of the band when the precac width is
+ * 20/40/80/160MHz and center frequency of the left 80MHz in case of restricted
+ * 80P80/165MHz.
+ * @center_freq_mhz2: Center frequency of the right 80MHz in case of restricted
+ * 80P80/165MHz. It is zero for other channel widths.
+ * @chwidth: Agile channel width for which the completion event is received.
+ *
+ * return: True if the channel on which OCAC completion event received is same
+ * as currently configured agile channel in host. False otherwise.
+ */
+static bool
+dfs_is_ocac_complete_event_for_cur_agile_chan(struct wlan_dfs *dfs,
+					      uint32_t center_freq_mhz1,
+					      uint32_t center_freq_mhz2,
+					      enum phy_ch_width chwidth)
+{
+    if (IS_HOST_AGILE_CURCHAN_165MHZ(dfs) &&
+	IS_OCAC_EVENT_ON_165_MHZ_CHAN(center_freq_mhz1,
+				      center_freq_mhz2,
+				      chwidth))
+	return true;
+    else if (dfs->dfs_agile_precac_freq_mhz == center_freq_mhz1)
+	return true;
+    else
+	return false;
+}
+
 /*
  * dfs_process_ocac_complete() - Process OCAC Complete eventid.
  * @pdev: Pointer to wlan_objmgr_pdev.
  * @ocac_status: OCAC Status.
- * @center_freq_mhz: Center frequency in MHZ.
+ * @center_freq_mhz1: Center frequency of the band when the precac width is
+ * 20/40/80/160MHz and center frequency of the left 80MHz in case of restricted
+ * 80P80/165MHz.
+ * @center_freq_mhz2: Center frequency of the right 80MHz in case of restricted
+ * 80P80/165MHz. It is zero for other channel widths.
+ * @chwidth: Agile channel width for which the completion event is received.
  */
-#ifdef QCA_SUPPORT_AGILE_DFS
-#ifdef CONFIG_CHAN_FREQ_API
 void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev,
 			       uint32_t ocac_status,
-			       uint32_t center_freq_mhz)
+			       uint32_t center_freq_mhz1,
+			       uint32_t center_freq_mhz2,
+			       enum phy_ch_width chwidth)
 {
 	struct wlan_dfs *dfs = NULL;
 	struct dfs_agile_cac_params adfs_param;
 
 	dfs = wlan_pdev_get_dfs_obj(pdev);
 
+	/* When the FW sends a delayed OCAC completion status, Host might
+	 * have changed the precac channel already before an OCAC
+	 * completion event is received. So the OCAC completion status
+	 * should be validated if it is on the currently configured agile
+	 * channel.
+	 */
+
+	/* Assume the previous agile channel was 64 (20Mhz) and current
+	 * agile channel is 100(20Mhz), if the event from the FW is for
+	 * previously configured agile channel 64(20Mhz) then Host ignores
+	 * the event.
+	 */
+	if (!dfs_is_ocac_complete_event_for_cur_agile_chan(dfs,
+							  center_freq_mhz1,
+							  center_freq_mhz2,
+							  chwidth)) {
+	    dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
+		    "OCAC completion event is received on a different channel %d %d that is not the current Agile channel %d",
+		    center_freq_mhz1,
+		    center_freq_mhz2,
+		    dfs->dfs_agile_precac_freq_mhz);
+	    return;
+	}
+
 	/* STOP TIMER irrespective of status */
 	utils_dfs_cancel_precac_timer(pdev);
 	if (ocac_status == OCAC_RESET) {
@@ -1981,13 +2062,15 @@
 			  "PreCAC timer abort, agile precac stopped");
 	} else if (ocac_status == OCAC_SUCCESS) {
 		dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
-			  "PreCAC timer Completed for agile freq: %d",
-			  center_freq_mhz);
+			  "PreCAC timer Completed for agile freq: %d %d",
+			  center_freq_mhz1,
+			  center_freq_mhz2);
 		/*
 		 * TRIGGER agile precac timer with 0sec timeout
 		 * with ocac_status 0 for old pdev
 		 */
-		adfs_param.precac_center_freq_1 = center_freq_mhz;
+		adfs_param.precac_center_freq_1 = center_freq_mhz1;
+		adfs_param.precac_center_freq_2 = center_freq_mhz2;
 		adfs_param.precac_chwidth = dfs->dfs_precac_chwidth;
 		dfs_start_agile_precac_timer(dfs,
 					     ocac_status,
@@ -4095,6 +4178,7 @@
 	struct dfs_soc_priv_obj *dfs_soc_obj;
 
 	dfs_soc_obj = dfs->dfs_soc_obj;
+	dfs_soc_obj->cur_precac_dfs_index = dfs->dfs_psoc_idx;
 	dfs = dfs_soc_obj->dfs_priv[dfs_soc_obj->cur_precac_dfs_index].dfs;
 #define EXTRA_TIME_IN_SEC 5
 	dfs_soc_obj->dfs_precac_timer_running = 1;
@@ -4867,7 +4951,9 @@
 	bool rcac_enabled = false;
 
 	dfsdomain = utils_get_dfsdomain(dfs->dfs_pdev_obj);
-	if ((dfsdomain == DFS_FCC_REGION || dfsdomain == DFS_MKK_REGION) &&
+	if ((dfsdomain == DFS_FCC_REGION ||
+	     dfsdomain == DFS_MKK_REGION ||
+	     dfsdomain == DFS_MKKN_REGION) &&
 	    dfs->dfs_agile_rcac_ucfg && dfs->dfs_fw_adfs_support_non_160)
 	    rcac_enabled = true;
 
@@ -5639,7 +5725,6 @@
 	struct dfs_agile_cac_params adfs_param;
 	uint8_t ocac_status = 0;
 	struct dfs_soc_priv_obj *dfs_soc_obj;
-	uint8_t cur_dfs_idx;
 
 	dfs_soc_obj = dfs->dfs_soc_obj;
 
@@ -5647,17 +5732,13 @@
 		 __func__, __LINE__,
 		dfs_soc_obj->precac_state_started);
 
-	if (!dfs_soc_obj->precac_state_started)
-		dfs_soc_obj->cur_precac_dfs_index = dfs->dfs_psoc_idx;
-
-	cur_dfs_idx = dfs_soc_obj->cur_precac_dfs_index;
-	dfs_soc_obj->dfs_priv[cur_dfs_idx].agile_precac_active = true;
+	dfs_soc_obj->dfs_priv[dfs->dfs_psoc_idx].agile_precac_active = true;
 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
-		 " setting true to cur_precac_dfs_index = %d, dfs: %pK",
-		 dfs_soc_obj->cur_precac_dfs_index,
-		 dfs->dfs_soc_obj->dfs_priv[cur_dfs_idx].dfs);
+		 "Agile preCAC set to active for dfs_index = %d, dfs: %pK",
+		 dfs->dfs_psoc_idx, dfs);
 
-	if (!dfs->dfs_soc_obj->precac_state_started) {
+	if (!dfs_soc_obj->precac_state_started) {
+		dfs_soc_obj->cur_precac_dfs_index = dfs->dfs_psoc_idx;
 		/*
 		 * Initiate first call to start preCAC here, for channel as 0,
 		 * and ocac_status as 0
diff --git a/wmi/src/wmi_unified_ap_tlv.c b/wmi/src/wmi_unified_ap_tlv.c
index 71ce2a5..426599d 100644
--- a/wmi/src/wmi_unified_ap_tlv.c
+++ b/wmi/src/wmi_unified_ap_tlv.c
@@ -1703,7 +1703,8 @@
 		WMITLV_TAG_STRUC_wmi_pdev_update_pkt_routing_cmd_fixed_param,
 		WMITLV_GET_STRUCT_TLVLEN(
 	wmi_pdev_update_pkt_routing_cmd_fixed_param));
-	cmd->pdev_id = param->pdev_id;
+	cmd->pdev_id = wmi_hdl->ops->convert_pdev_id_host_to_target(wmi_hdl,
+							param->pdev_id);
 	cmd->op_code = (A_UINT32) param->op_code;
 	cmd->routing_type_bitmap = param->routing_type_bitmap;
 	cmd->dest_ring = param->dest_ring;