Browse Source

qcacld-3.0: Send channel switch request instead of doing SAP restart

Send channel switch request instead of performing SAP restart when
doing a MCC to SCC switch. This is controlled using the existing INI
item 'gWlanMccToSccSwitchMode'. The new value of '3' will perform
this channel change by sending (E)/CSA whereas the old value of '2'
can still be used to do a channel change by doing SAP restart

Change-Id: I79e7317219503de0a9957940f3cf7a4e91c7a521
CRs-Fixed: 986202
Chandrasekaran Manishekar 9 years ago
parent
commit
cde33d77d6

+ 4 - 0
core/cds/inc/cds_concurrency.h

@@ -681,4 +681,8 @@ QDF_STATUS cds_stop_start_opportunistic_timer(void);
 QDF_STATUS cds_handle_hw_mode_change_on_csa(uint16_t session_id,
 		uint8_t channel, uint8_t *bssid, void *dst, void *src,
 		uint32_t numbytes);
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+QDF_STATUS cds_register_sap_restart_channel_switch_cb(
+		void (*sap_restart_chan_switch_cb)(void *, uint32_t, uint32_t));
+#endif
 #endif /* __CDS_CONCURRENCY_H */

+ 3 - 1
core/cds/inc/cds_sched.h

@@ -288,7 +288,9 @@ typedef struct _cds_context_type {
 	qdf_event_t connection_update_done_evt;
 	qdf_mutex_t qdf_conc_list_lock;
 	qdf_mc_timer_t dbs_opportunistic_timer;
-
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+	void (*sap_restart_chan_switch_cb)(void *, uint32_t, uint32_t);
+#endif
 } cds_context_type, *p_cds_contextType;
 
 /*---------------------------------------------------------------------------

+ 46 - 1
core/cds/src/cds_concurrency.c

@@ -6604,6 +6604,13 @@ static void cds_check_sta_ap_concurrent_ch_intf(void *data)
 	tHalHandle *hal_handle;
 	hdd_ap_ctx_t *hdd_ap_ctx;
 	uint16_t intf_ch = 0;
+	p_cds_contextType cds_ctx;
+
+	cds_ctx = cds_get_global_context();
+	if (!cds_ctx) {
+		cds_err("Invalid CDS context");
+		return;
+	}
 
 	cds_info("cds_concurrent_open_sessions_running: %d",
 		cds_concurrent_open_sessions_running());
@@ -6642,7 +6649,18 @@ static void cds_check_sta_ap_concurrent_ch_intf(void *data)
 			hdd_ap_ctx->sapConfig.channel,
 			hdd_ap_ctx->sapConfig.sec_ch,
 			&hdd_ap_ctx->sapConfig.ch_params);
-	cds_restart_sap(ap_adapter);
+
+	if ((hdd_ctx->config->WlanMccToSccSwitchMode ==
+		QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION) &&
+		(cds_ctx->sap_restart_chan_switch_cb)) {
+		cds_info("SAP chan change without restart");
+		cds_ctx->sap_restart_chan_switch_cb(ap_adapter,
+				hdd_ap_ctx->sapConfig.channel,
+				hdd_ap_ctx->sapConfig.ch_params.ch_width);
+	} else {
+		cds_restart_sap(ap_adapter);
+	}
+
 }
 /**
  * cds_check_concurrent_intf_and_restart_sap() - Check concurrent change intf
@@ -7989,3 +8007,30 @@ QDF_STATUS cds_handle_hw_mode_change_on_csa(uint16_t session_id,
 	}
 	return status;
 }
+
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+/**
+ * cds_register_sap_restart_channel_switch_cb() - Register callback for SAP
+ * channel switch without restart
+ * @sap_restart_chan_switch_cb: Callback to perform channel switch
+ *
+ * Registers callback to perform channel switch without having to actually
+ * restart the beaconing entity
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS cds_register_sap_restart_channel_switch_cb(
+		void (*sap_restart_chan_switch_cb)(void *, uint32_t, uint32_t))
+{
+	p_cds_contextType cds_ctx;
+
+	cds_ctx = cds_get_global_context();
+	if (!cds_ctx) {
+		cds_err("Invalid CDS context");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	cds_ctx->sap_restart_chan_switch_cb = sap_restart_chan_switch_cb;
+	return QDF_STATUS_SUCCESS;
+}
+#endif

+ 1 - 1
core/hdd/inc/wlan_hdd_cfg.h

@@ -343,7 +343,7 @@ typedef enum {
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 #define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE          "gWlanMccToSccSwitchMode"
 #define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MIN      (QDF_MCC_TO_SCC_SWITCH_DISABLE)
-#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MAX      (QDF_MCC_TO_SCC_SWITCH_FORCE)
+#define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_MAX      (QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION)
 #define CFG_WLAN_MCC_TO_SCC_SWITCH_MODE_DEFAULT  (QDF_MCC_TO_SCC_SWITCH_DISABLE)
 #endif
 

+ 9 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -1631,6 +1631,15 @@ uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
 			uint8_t bw_offset);
 void hdd_update_config(hdd_context_t *hdd_ctx);
 
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void);
+#else
+static inline QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
+{
+	return CDF_STATUS_SUCCESS;
+}
+#endif
+
 #ifdef FEATURE_TSO
 /**
  * hdd_set_tso_flags() - enable TSO flags in the network device

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

@@ -2098,6 +2098,39 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
 	return ret;
 }
 
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+/**
+ * hdd_sap_restart_with_channel_switch() - SAP channel change with E/CSA
+ * @ap_adapter: HDD adapter
+ * @target_channel: Channel to which switch must happen
+ * @target_bw: Bandwidth of the target channel
+ *
+ * Invokes the necessary API to perform channel switch for the SAP or GO
+ *
+ * Return: None
+ */
+void hdd_sap_restart_with_channel_switch(hdd_adapter_t *ap_adapter,
+					uint32_t target_channel,
+					uint32_t target_bw)
+{
+	struct net_device *dev = ap_adapter->dev;
+	int ret;
+
+	ENTER();
+
+	if (!dev) {
+		hdd_err("Invalid dev pointer");
+		return;
+	}
+
+	ret = hdd_softap_set_channel_change(dev, target_channel, target_bw);
+	if (ret) {
+		hdd_err("channel switch failed");
+		return;
+	}
+}
+#endif
+
 int
 static __iw_softap_set_ini_cfg(struct net_device *dev,
 			       struct iw_request_info *info,

+ 6 - 0
core/hdd/src/wlan_hdd_hostapd.h

@@ -63,6 +63,12 @@ int hdd_softap_set_channel_change(struct net_device *dev,
 				  int target_channel,
 				  enum ch_width target_bw);
 
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+void hdd_sap_restart_with_channel_switch(hdd_adapter_t *adapter,
+				uint32_t target_channel,
+				uint32_t target_bw);
+#endif
+
 eCsrEncryptionType
 hdd_translate_rsn_to_csr_encryption_type(uint8_t cipher_suite[4]);
 

+ 28 - 0
core/hdd/src/wlan_hdd_main.c

@@ -5542,6 +5542,29 @@ static inline bool hdd_hold_rtnl_lock(void) { return false; }
 static inline void hdd_release_rtnl_lock(void) { }
 #endif
 
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+/**
+ * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
+ * switch without restart
+ *
+ * Registers callback function to change the operating channel of SAP by using
+ * channel switch announcements instead of restarting SAP.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
+{
+	QDF_STATUS status;
+
+	status = cds_register_sap_restart_channel_switch_cb(
+			(void *)hdd_sap_restart_with_channel_switch);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		hdd_err("restart cb registration failed");
+
+	return status;
+}
+#endif
+
 /**
  * hdd_wlan_startup() - HDD init function
  * @dev:	Pointer to the underlying device
@@ -5852,6 +5875,11 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 	sme_ext_scan_register_callback(hdd_ctx->hHal,
 				       wlan_hdd_cfg80211_extscan_callback);
 
+	status = hdd_register_for_sap_restart_with_channel_switch();
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		/* Error already logged */
+		goto err_unreg_netdev_notifier;
+
 	sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
 				hdd_rssi_threshold_breached);
 

+ 6 - 0
core/hdd/src/wlan_hdd_power.c

@@ -1594,6 +1594,12 @@ QDF_STATUS hdd_wlan_re_init(void *hif_sc)
 
 	sme_ext_scan_register_callback(pHddCtx->hHal,
 				wlan_hdd_cfg80211_extscan_callback);
+
+	qdf_status = hdd_register_for_sap_restart_with_channel_switch();
+	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
+		/* Error already logged */
+		goto err_cds_disable;
+
 	sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached);
 
 #ifdef WLAN_FEATURE_LPSS

+ 3 - 1
core/sme/src/csr/csr_util.c

@@ -765,7 +765,9 @@ uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal mac_ctx,
 		intf_ch, sap_ch, intf_ch);
 
 	if (intf_ch && sap_ch != intf_ch &&
-			cc_switch_mode != QDF_MCC_TO_SCC_SWITCH_FORCE) {
+	    cc_switch_mode != QDF_MCC_TO_SCC_SWITCH_FORCE &&
+	    cc_switch_mode !=
+	    QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION) {
 		sap_lfreq = sap_cfreq - sap_hbw;
 		sap_hfreq = sap_cfreq + sap_hbw;
 		intf_lfreq = intf_cfreq - intf_hbw;