Преглед на файлове

qcacld-3.0: Wait for ACS rather than iface change fail

Currently the driver checks for the ACS in progress
in change iface and returns fail if the ACS is in
progress. The return status is not checked by the
kernel and it assumes that the interface change is
successfull, which may lead to out of sync between
driver and kernel.

Fix is to wait for ACS completion if the iface change
or interface down is triggered in between ACS.

Change-Id: Iaabd42fc959a533041b18b181e1b63493f17e0a5
CRs-Fixed: 2541325
gaurank kathpalia преди 5 години
родител
ревизия
7aed85ed22
променени са 4 файла, в които са добавени 16 реда и са изтрити 8 реда
  1. 4 1
      core/hdd/inc/wlan_hdd_main.h
  2. 1 5
      core/hdd/src/wlan_hdd_cfg80211.c
  3. 3 0
      core/hdd/src/wlan_hdd_hostapd.c
  4. 8 2
      core/hdd/src/wlan_hdd_main.c

+ 4 - 1
core/hdd/inc/wlan_hdd_main.h

@@ -197,6 +197,8 @@ static inline bool in_compat_syscall(void) { return is_compat_task(); }
 #define NUM_CPUS 1
 #endif
 
+#define ACS_COMPLETE_TIMEOUT 3000
+
 #define HDD_PSOC_IDLE_SHUTDOWN_SUSPEND_DELAY (1000)
 /**
  * enum hdd_adapter_flags - event bitmap flags registered net device
@@ -1043,7 +1045,7 @@ struct hdd_context;
  * @mic_work: mic work information
  * @gpio_tsf_sync_work: work to sync send TSF CAP WMI command
  * @cache_sta_count: number of currently cached stations
- *
+ * @acs_complete_event: acs complete event
  */
 struct hdd_adapter {
 	/* Magic cookie for adapter sanity verification.  Note that this
@@ -1168,6 +1170,7 @@ struct hdd_adapter {
 	} session;
 
 	qdf_atomic_t ch_switch_in_progress;
+	qdf_event_t acs_complete_event;
 
 #ifdef WLAN_FEATURE_TSF
 	/* tsf value received from firmware */

+ 1 - 5
core/hdd/src/wlan_hdd_cfg80211.c

@@ -2760,6 +2760,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 		return -EINVAL;
 	} else {
 		qdf_atomic_set(&adapter->session.ap.acs_in_progress, 1);
+		qdf_event_reset(&adapter->acs_complete_event);
 	}
 
 	ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
@@ -15561,11 +15562,6 @@ static int hdd_change_adapter_mode(struct hdd_adapter *adapter,
 
 	hdd_enter();
 
-	if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
-		hdd_warn("Can't change interface: ACS in progress");
-		return -EBUSY;
-	}
-
 	hdd_stop_adapter(hdd_ctx, adapter);
 	hdd_deinit_adapter(hdd_ctx, adapter, true);
 	adapter->device_mode = new_mode;

+ 3 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -2600,6 +2600,8 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 			sap_event->sapevt.sap_ch_selected.ch_width;
 		wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
 		qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
+		qdf_event_set(&adapter->acs_complete_event);
+
 		return QDF_STATUS_SUCCESS;
 	case eSAP_ECSA_CHANGE_CHAN_IND:
 		hdd_debug("Channel change indication from peer for channel %d",
@@ -3459,6 +3461,7 @@ void hdd_deinit_ap_mode(struct hdd_context *hdd_ctx,
 		clear_bit(WMM_INIT_DONE, &adapter->event_flags);
 	}
 	qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
+
 	hdd_softap_deinit_tx_rx(adapter);
 	/*
 	 * if we are being called during driver unload,

+ 8 - 2
core/hdd/src/wlan_hdd_main.c

@@ -5622,6 +5622,7 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
 	INIT_WORK(&adapter->scan_block_work, wlan_hdd_cfg80211_scan_block_cb);
 	qdf_list_create(&adapter->blocked_scan_request_q, WLAN_MAX_SCAN_COUNT);
 	qdf_mutex_create(&adapter->blocked_scan_request_q_lock);
+	qdf_event_create(&adapter->acs_complete_event);
 
 	if (QDF_STATUS_SUCCESS == status) {
 		/* Add it to the hdd's session list. */
@@ -5679,7 +5680,7 @@ static void __hdd_close_adapter(struct hdd_context *hdd_ctx,
 	qdf_list_destroy(&adapter->blocked_scan_request_q);
 	qdf_mutex_destroy(&adapter->blocked_scan_request_q_lock);
 	policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
-
+	qdf_event_destroy(&adapter->acs_complete_event);
 	hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
 
 	if (hdd_ctx->current_intf_count != 0)
@@ -5970,7 +5971,12 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
 
 	case QDF_P2P_GO_MODE:
 		cds_flush_work(&adapter->sap_stop_bss_work);
-		qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
+		if (qdf_atomic_read(&adapter->session.ap.acs_in_progress)) {
+			hdd_info("ACS in progress, wait for complete");
+			qdf_wait_for_event_completion(
+				&adapter->acs_complete_event,
+				ACS_COMPLETE_TIMEOUT);
+		}
 		wlan_hdd_undo_acs(adapter);
 
 		if (adapter->device_mode == QDF_P2P_GO_MODE)