Przeglądaj źródła

qcacld-3.0: Avoid processing back to back ACS req within 500ms

Currently as part of LL_LT_SAP optimization, driver receives
do_acs command from below two path

1. LL_LT_SAP library to get the channel early and
2. Hostapd during SAP turn on

In the first request if driver finds the clean channel as part
of partial scan req then it directly sends that channel to
requested module. So in the second request, driver will exclude
the recently scanned channel from scan list. But there may be
possible that it may receive another clean channel during scan
which leads to two different back to back ACS frequency.

To avoid this, store the current acs frequency and if driver
receives the second acs req within 500ms then send the stored
acs result to requested module.

Change-Id: I9b083a64e996f6ada32ff5210a304aa66aa6ec3a
CRs-Fixed: 3498271
Jyoti Kumari 1 rok temu
rodzic
commit
1aa66f5a46

+ 99 - 14
core/hdd/src/wlan_hdd_cfg80211.c

@@ -2261,7 +2261,6 @@ static void hdd_update_acs_channel_list(struct sap_config *sap_config,
 	sap_config->acs_cfg.ch_list_count = temp_count;
 }
 
-
 /**
  * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
  * @adapter: pointer to SAP adapter struct
@@ -2319,7 +2318,7 @@ int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
 
 		if (status > 0) {
 			/*notify hostapd about channel override */
-			wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
+			wlan_hdd_cfg80211_acs_ch_select_evt(adapter, true);
 			wlansap_dcs_set_wlan_interference_mitigation_on_band(sap_ctx,
 									     sap_config);
 			return 0;
@@ -3357,7 +3356,7 @@ wlan_hdd_handle_single_ch_in_acs_list(struct hdd_context *hdd_ctx,
 	sap_config->ch_params.mhz_freq_seg1 =
 		sap_config->acs_cfg.vht_seg1_center_ch_freq;
 	/*notify hostapd about channel override */
-	wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
+	wlan_hdd_cfg80211_acs_ch_select_evt(adapter, true);
 	wlansap_dcs_set_wlan_interference_mitigation_on_band(
 		WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
 		sap_config);
@@ -3639,6 +3638,88 @@ static void hdd_remove_passive_dfs_acs_channel_for_ll_sap(
 	}
 }
 
+/* Stored ACS Frequency timeout in msec */
+#define STORED_ACS_FREQ_TIMEOUT 500
+static bool
+wlan_hdd_is_prev_acs_freq_present_in_acs_config(struct sap_config *sap_cfg)
+{
+	uint32_t i = 0;
+	bool prev_acs_freq_found = false;
+
+	if (!qdf_system_time_before(
+		qdf_get_time_of_the_day_ms(),
+		sap_cfg->last_acs_complete_time + STORED_ACS_FREQ_TIMEOUT))
+		return prev_acs_freq_found;
+
+	for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
+		if (sap_cfg->acs_cfg.freq_list[i] == sap_cfg->last_acs_freq) {
+			prev_acs_freq_found = true;
+			break;
+		}
+	}
+
+	return prev_acs_freq_found;
+}
+
+static bool
+wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(struct hdd_adapter *adapter)
+{
+	struct hdd_context *hdd_ctx;
+	struct sap_config *sap_config;
+	int status;
+	bool prev_acs_freq_valid = false;
+	struct sap_context *sap_ctx;
+
+	if (!adapter) {
+		hdd_err("adapter is NULL");
+		return prev_acs_freq_valid;
+	}
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	status = wlan_hdd_validate_context(hdd_ctx);
+	if (0 != status) {
+		hdd_err("Invalid HDD context");
+		return prev_acs_freq_valid;
+	}
+
+	sap_config = &adapter->deflink->session.ap.sap_config;
+	if (!sap_config) {
+		hdd_err("SAP config is NULL");
+		return prev_acs_freq_valid;
+	}
+
+	if (!sap_config->last_acs_freq || !sap_config->last_acs_complete_time)
+		return prev_acs_freq_valid;
+
+	if (!policy_mgr_is_vdev_lt_ll_sap(
+				hdd_ctx->psoc,
+				adapter->deflink->vdev_id))
+		return prev_acs_freq_valid;
+
+	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink);
+	if (wlan_hdd_is_prev_acs_freq_present_in_acs_config(sap_config)) {
+		wlansap_update_ll_lt_sap_acs_result(sap_ctx,
+						    sap_config->last_acs_freq);
+
+		hdd_debug("vdev %d, return prev ACS freq %d stored at %lu, current time %lu",
+			  adapter->deflink->vdev_id, sap_config->last_acs_freq,
+			  sap_config->last_acs_complete_time,
+			  qdf_get_time_of_the_day_ms());
+
+		/* Notify to hostapd without storing the last acs frequency.
+		 * Reason for not storing the last acs frequency is to avoid
+		 * storing the same freq again and again
+		 */
+		wlan_hdd_cfg80211_acs_ch_select_evt(adapter, false);
+		wlansap_dcs_set_wlan_interference_mitigation_on_band(sap_ctx,
+								    sap_config);
+
+		prev_acs_freq_valid = true;
+	}
+
+	return prev_acs_freq_valid;
+}
+
 /**
  * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
  * @wiphy:  Linux wiphy struct pointer
@@ -4046,6 +4127,11 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 
 	sap_dump_acs_channel(&sap_config->acs_cfg);
 
+	if (wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(adapter)) {
+		ret = 0;
+		goto out;
+	}
+
 	qdf_status = ucfg_mlme_get_vendor_acs_support(hdd_ctx->psoc,
 						      &is_vendor_acs_support);
 	if (QDF_IS_STATUS_ERROR(qdf_status))
@@ -4226,16 +4312,8 @@ static uint16_t wlan_hdd_acs_get_puncture_bitmap(struct sap_acs_cfg *acs_cfg)
 }
 #endif /* WLAN_FEATURE_11BE */
 
-/**
- * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
- * @adapter: Pointer to SAP adapter struct
- *
- * This is a callback function on ACS procedure is completed.
- * This function send the ACS selected channel information to hostapd
- *
- * Return: None
- */
-void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter)
+void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter,
+					 bool store_acs_freq)
 {
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	struct sap_config *sap_cfg;
@@ -4255,6 +4333,13 @@ void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter)
 	sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink))->sap_config;
 	len = hdd_get_acs_evt_data_len(sap_cfg);
 
+	if (store_acs_freq &&
+	    policy_mgr_is_vdev_lt_ll_sap(hdd_ctx->psoc,
+					 adapter->deflink->vdev_id)) {
+		sap_cfg->last_acs_freq = sap_cfg->acs_cfg.pri_ch_freq;
+		sap_cfg->last_acs_complete_time = qdf_get_time_of_the_day_ms();
+	}
+
 	vendor_event = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
 							&adapter->wdev, len, id,
 							GFP_KERNEL);
@@ -15866,7 +15951,7 @@ static int hdd_update_acs_channel(struct hdd_adapter *adapter, uint8_t reason,
 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
 		hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
 		/* Update Hostapd */
-		wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
+		wlan_hdd_cfg80211_acs_ch_select_evt(adapter, true);
 		break;
 
 	/* DFS detected on current channel */

+ 12 - 1
core/hdd/src/wlan_hdd_cfg80211.h

@@ -519,7 +519,18 @@ int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx,
 void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
 				struct rso_cmd_status *rso_status);
 
-void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter);
+/**
+ * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
+ * @adapter: Pointer to SAP adapter struct
+ * @store_acs_freq: Store current ACS frequecy flag
+ *
+ * This is a callback function on ACS procedure is completed.
+ * This function send the ACS selected channel information to hostapd
+ *
+ * Return: None
+ */
+void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter,
+					 bool store_acs_freq);
 
 #ifdef WLAN_CFR_ENABLE
 /*

+ 1 - 1
core/hdd/src/wlan_hdd_hostapd.c

@@ -2972,7 +2972,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 		    test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
 			hdd_dcs_chan_select_complete(adapter);
 		} else {
-			wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
+			wlan_hdd_cfg80211_acs_ch_select_evt(adapter, true);
 			wlansap_dcs_set_wlan_interference_mitigation_on_band(
 					WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
 					&ap_ctx->sap_config);

+ 14 - 0
core/sap/inc/sap_api.h

@@ -556,6 +556,8 @@ struct sap_config {
 	uint8_t link_id;
 	uint8_t num_link;
 #endif
+	qdf_freq_t last_acs_freq;
+	qdf_time_t last_acs_complete_time;
 };
 
 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
@@ -1902,6 +1904,18 @@ void wlansap_process_chan_info_event(struct sap_context *sap_ctx,
 }
 #endif
 
+/**
+ * wlansap_update_ll_lt_sap_acs_result() - Update acs result of LL_LT_SAP
+ * @sap_ctx: sap context
+ * @last_acs_freq: last acs frequency to be set
+ *
+ * This function is used to update stored acs channel frequency
+ *
+ * Return: None
+ */
+void wlansap_update_ll_lt_sap_acs_result(struct sap_context *sap_ctx,
+					 qdf_freq_t last_acs_freq);
+
 #ifdef __cplusplus
 }
 #endif

+ 21 - 0
core/sap/src/sap_module.c

@@ -4134,3 +4134,24 @@ void sap_acs_set_puncture_support(struct sap_context *sap_ctx,
 		ch_params->is_create_punc_bitmap = true;
 }
 #endif
+
+void wlansap_update_ll_lt_sap_acs_result(struct sap_context *sap_ctx,
+					 qdf_freq_t last_acs_freq)
+{
+	struct mac_context *mac;
+
+	mac = sap_get_mac_context();
+	if (!mac) {
+		sap_err("Invalid MAC context");
+		return;
+	}
+
+	if (!sap_ctx) {
+		sap_err("Invalid sap context");
+		return;
+	}
+
+	wlansap_set_acs_ch_freq(sap_ctx, last_acs_freq);
+	sap_ctx->acs_cfg->pri_ch_freq = last_acs_freq;
+	sap_ctx->acs_cfg->ht_sec_ch_freq = 0;
+}