ソースを参照

qcacld-3.0: Move pre cac hdd code to new file

Move pre cac code related to hdd into a new file
wlan_hdd_pre_cac.c

Change-Id: Ia6b2e92a1bea03d7efe12a7dad27e345dc5ef53d
CRs-Fixed: 3174488
Dundi Raviteja 3 年 前
コミット
d3bb29db4c

+ 8 - 0
Kbuild

@@ -1667,6 +1667,14 @@ endif
 
 $(call add-wlan-objs,ftm_time_sync,$(FTM_TIME_SYNC_OBJS))
 
+########## WLAN PRE_CAC ##########
+
+ifeq ($(CONFIG_FEATURE_WLAN_PRE_CAC), y)
+WLAN_PRE_CAC_OBJS := $(HDD_SRC_DIR)/wlan_hdd_pre_cac.o
+endif
+
+$(call add-wlan-objs,wlan_pre_cac,$(WLAN_PRE_CAC_OBJS))
+
 ########## CLD TARGET_IF #######
 CLD_TARGET_IF_DIR := components/target_if
 

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

@@ -3757,36 +3757,6 @@ static inline int wlan_hdd_get_cpu(void)
 }
 #endif
 
-#ifdef PRE_CAC_SUPPORT
-/**
- * wlan_hdd_sap_pre_cac_failure() - Process the pre cac failure
- * @data: AP adapter
- *
- * Deletes the pre cac adapter
- *
- * Return: None
- */
-void wlan_hdd_sap_pre_cac_failure(void *data);
-/**
- * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
- * @hdd_ctx: HDD context
- *
- * Cleans up the pre cac interface, if it exists
- *
- * Return: None
- */
-void hdd_clean_up_pre_cac_interface(struct hdd_context *hdd_ctx);
-#else
-static inline void wlan_hdd_sap_pre_cac_failure(void *data)
-{
-}
-
-static inline void
-hdd_clean_up_pre_cac_interface(struct hdd_context *hdd_ctx)
-{
-}
-#endif /* PRE_CAC_SUPPORT */
-
 void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
 	enum netif_action_type action, enum netif_reason_type reason);
 

+ 122 - 0
core/hdd/inc/wlan_hdd_pre_cac.h

@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _WLAN_HDD_PRE_CAC_H_
+#define _WLAN_HDD_PRE_CAC_H_
+
+#ifdef PRE_CAC_SUPPORT
+
+/* default pre cac channel bandwidth */
+#define DEFAULT_PRE_CAC_BANDWIDTH CH_WIDTH_80MHZ
+
+/**
+ * wlan_hdd_sap_pre_cac_success() - Process the pre cac success
+ * @data: AP adapter
+ *
+ * Return: None
+ */
+void wlan_hdd_sap_pre_cac_success(void *data);
+/**
+ * wlan_hdd_sap_pre_cac_failure() - Process the pre cac failure
+ * @data: AP adapter
+ *
+ * Deletes the pre cac adapter
+ *
+ * Return: None
+ */
+void wlan_hdd_sap_pre_cac_failure(void *data);
+
+/**
+ * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
+ * @hdd_ctx: HDD context
+ *
+ * Cleans up the pre cac interface, if it exists
+ *
+ * Return: None
+ */
+void hdd_clean_up_pre_cac_interface(struct hdd_context *hdd_ctx);
+
+/**
+ * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
+ * @hdd_ctx: the HDD context to operate against
+ * @chan_freq: channel freq option provided by userspace
+ *
+ * Sets the driver to the required hardware mode and start an adapter for
+ * pre CAC which will mimic an AP.
+ *
+ * Return: Zero on success, non-zero value on error
+ */
+int wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx, uint32_t chan_freq);
+
+/**
+ * hdd_send_conditional_chan_switch_status() - Send conditional channel switch
+ * status
+ * @hdd_ctx: HDD context
+ * @wdev: Wireless device structure
+ * @status: Status of conditional channel switch
+ * (0: Success, Non-zero: Failure)
+ *
+ * Sends the status of conditional channel switch to user space. This is named
+ * conditional channel switch because the SAP will move to the provided channel
+ * after some condition (pre-cac) is met.
+ *
+ * Return: None
+ */
+void hdd_send_conditional_chan_switch_status(struct hdd_context *hdd_ctx,
+					     struct wireless_dev *wdev,
+					     bool status);
+
+/**
+ * hdd_close_pre_cac_adapter() - Close pre CAC adapter
+ * @hdd_ctx: the HDD context to operate against
+ *
+ * Return: None
+ */
+void hdd_close_pre_cac_adapter(struct hdd_context *hdd_ctx);
+#else
+static inline void wlan_hdd_sap_pre_cac_success(void *data)
+{
+}
+
+static inline void wlan_hdd_sap_pre_cac_failure(void *data)
+{
+}
+
+static inline void
+hdd_clean_up_pre_cac_interface(struct hdd_context *hdd_ctx)
+{
+}
+
+static inline int
+wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx, uint32_t chan_freq)
+{
+	return 0;
+}
+
+static inline void
+hdd_send_conditional_chan_switch_status(struct hdd_context *hdd_ctx,
+					struct wireless_dev *wdev,
+					bool status)
+{
+}
+
+static inline void
+hdd_close_pre_cac_adapter(struct hdd_context *hdd_ctx)
+{
+}
+#endif /* PRE_CAC_SUPPORT */
+#endif /* _WLAN_HDD_PRE_CAC_H_ */

+ 0 - 19
core/hdd/src/wlan_hdd_cfg80211.h

@@ -552,25 +552,6 @@ void hdd_send_roam_scan_ch_list_event(struct hdd_context *hdd_ctx,
 
 int wlan_hdd_cfg80211_update_apies(struct hdd_adapter *adapter);
 
-#ifdef PRE_CAC_SUPPORT
-/**
- * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
- * @hdd_ctx: the HDD context to operate against
- * @chan_freq: channel freq option provided by userspace
- *
- * Sets the driver to the required hardware mode and start an adapter for
- * pre CAC which will mimic an AP.
- *
- * Return: Zero on success, non-zero value on error
- */
-int wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx, uint32_t chan_freq);
-#else
-static inline int
-wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx, uint32_t chan_freq)
-{
-	return 0;
-}
-#endif
 int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter);
 
 int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,

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

@@ -109,6 +109,7 @@
 #include "wlan_hdd_son.h"
 #include "wlan_hdd_mcc_quota.h"
 #include "wlan_hdd_wds.h"
+#include "wlan_hdd_pre_cac.h"
 
 #define ACS_SCAN_EXPIRY_TIMEOUT_S 4
 
@@ -1079,194 +1080,6 @@ static QDF_STATUS hdd_send_radar_event(struct hdd_context *hdd_context,
 	return QDF_STATUS_SUCCESS;
 }
 
-#ifdef PRE_CAC_SUPPORT
-/**
- * hdd_send_conditional_chan_switch_status() - Send conditional channel switch
- * status
- * @hdd_ctx: HDD context
- * @wdev: Wireless device structure
- * @status: Status of conditional channel switch
- * (0: Success, Non-zero: Failure)
- *
- * Sends the status of conditional channel switch to user space. This is named
- * conditional channel switch because the SAP will move to the provided channel
- * after some condition (pre-cac) is met.
- *
- * Return: None
- */
-static void hdd_send_conditional_chan_switch_status(struct hdd_context *hdd_ctx,
-						struct wireless_dev *wdev,
-						bool status)
-{
-	struct sk_buff *event;
-
-	hdd_enter_dev(wdev->netdev);
-
-	if (!hdd_ctx) {
-		hdd_err("Invalid HDD context pointer");
-		return;
-	}
-
-	event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
-		  wdev, sizeof(uint32_t) + NLMSG_HDRLEN,
-		  QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX,
-		  GFP_KERNEL);
-	if (!event) {
-		hdd_err("cfg80211_vendor_event_alloc failed");
-		return;
-	}
-
-	if (nla_put_u32(event,
-			QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS,
-			status)) {
-		hdd_err("nla put failed");
-		kfree_skb(event);
-		return;
-	}
-
-	cfg80211_vendor_event(event, GFP_KERNEL);
-}
-
-/**
- * wlan_hdd_set_pre_cac_complete_status() - Set pre cac complete status
- * @ap_adapter: AP adapter
- * @status: Status which can be true or false
- *
- * Sets the status of pre cac i.e., whether it is complete or not
- *
- * Return: Zero on success, non-zero on failure
- */
-static int wlan_hdd_set_pre_cac_complete_status(struct hdd_adapter *ap_adapter,
-		bool status)
-{
-	QDF_STATUS ret;
-
-	ret = wlan_sap_set_pre_cac_complete_status(
-			WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), status);
-	if (QDF_IS_STATUS_ERROR(ret))
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- * __wlan_hdd_sap_pre_cac_failure() - Process the pre cac failure
- * @adapter: AP adapter
- *
- * Deletes the pre cac adapter
- *
- * Return: None
- */
-static void __wlan_hdd_sap_pre_cac_failure(struct hdd_adapter *adapter)
-{
-	struct hdd_context *hdd_ctx;
-
-	hdd_enter();
-
-	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	if (wlan_hdd_validate_context(hdd_ctx))
-		return;
-
-	hdd_stop_adapter(hdd_ctx, adapter);
-
-	hdd_exit();
-}
-
-/**
- * wlan_hdd_sap_pre_cac_failure() - Process the pre cac failure
- * @data: AP adapter
- *
- * Deletes the pre cac adapter
- *
- * Return: None
- */
-void wlan_hdd_sap_pre_cac_failure(void *data)
-{
-	struct hdd_adapter *adapter = data;
-	struct osif_vdev_sync *vdev_sync;
-	int errno;
-
-	errno = osif_vdev_sync_trans_start_wait(adapter->dev, &vdev_sync);
-	if (errno)
-		return;
-
-
-	__wlan_hdd_sap_pre_cac_failure(data);
-
-	osif_vdev_sync_trans_stop(vdev_sync);
-}
-
-/**
- * __wlan_hdd_sap_pre_cac_success() - Process the pre cac result
- * @adapter: AP adapter
- *
- * Deletes the pre cac adapter and moves the existing SAP to the pre cac
- * channel
- *
- * Return: None
- */
-static void __wlan_hdd_sap_pre_cac_success(struct hdd_adapter *adapter)
-{
-	struct hdd_adapter *ap_adapter;
-	int i;
-	struct hdd_context *hdd_ctx;
-	enum phy_ch_width pre_cac_ch_width;
-
-	hdd_enter();
-
-	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	if (!hdd_ctx) {
-		hdd_err("HDD context is null");
-		return;
-	}
-
-	pre_cac_ch_width = wlansap_get_chan_width(
-				WLAN_HDD_GET_SAP_CTX_PTR(adapter));
-
-	hdd_stop_adapter(hdd_ctx, adapter);
-
-	/* Prepare to switch AP from 2.4GHz channel to the pre CAC channel */
-	ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
-	if (!ap_adapter) {
-		hdd_err("failed to get SAP adapter, no restart on pre CAC channel");
-		return;
-	}
-
-	/*
-	 * Setting of the pre cac complete status will ensure that on channel
-	 * switch to the pre CAC DFS channel, there is no CAC again.
-	 */
-	wlan_hdd_set_pre_cac_complete_status(ap_adapter, true);
-
-	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->vdev_id,
-				    CSA_REASON_PRE_CAC_SUCCESS);
-	i = hdd_softap_set_channel_change(ap_adapter->dev,
-					  ap_adapter->pre_cac_freq,
-					  pre_cac_ch_width, false);
-	if (0 != i) {
-		hdd_err("failed to change channel");
-		wlan_hdd_set_pre_cac_complete_status(ap_adapter, false);
-	}
-
-	hdd_exit();
-}
-
-static void wlan_hdd_sap_pre_cac_success(void *data)
-{
-	struct hdd_adapter *adapter = data;
-	struct osif_vdev_sync *vdev_sync;
-	int errno;
-
-	errno = osif_vdev_sync_trans_start_wait(adapter->dev, &vdev_sync);
-	if (errno)
-		return;
-
-	__wlan_hdd_sap_pre_cac_success(adapter);
-
-	osif_vdev_sync_trans_stop(vdev_sync);
-}
-#endif
-
 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
 /**
  * hdd_handle_acs_scan_event() - handle acs scan event for SAP

+ 1 - 61
core/hdd/src/wlan_hdd_main.c

@@ -164,7 +164,7 @@
 #include "wlan_policy_mgr_ucfg.h"
 #include "qdf_func_tracker.h"
 #include "pld_common.h"
-
+#include "wlan_hdd_pre_cac.h"
 
 #ifdef CNSS_GENL
 #ifdef CONFIG_CNSS_OUT_OF_TREE
@@ -8099,39 +8099,6 @@ static inline void hdd_dump_func_call_map(void)
 }
 #endif
 
-#ifdef PRE_CAC_SUPPORT
-static void hdd_close_pre_cac_adapter(struct hdd_context *hdd_ctx)
-{
-	struct hdd_adapter *pre_cac_adapter;
-	struct osif_vdev_sync *vdev_sync;
-	int errno;
-
-	pre_cac_adapter = hdd_get_adapter_by_iface_name(hdd_ctx,
-							SAP_PRE_CAC_IFNAME);
-	if (!pre_cac_adapter)
-		return;
-
-	errno = osif_vdev_sync_trans_start_wait(pre_cac_adapter->dev,
-						&vdev_sync);
-	if (errno)
-		return;
-
-	osif_vdev_sync_unregister(pre_cac_adapter->dev);
-	osif_vdev_sync_wait_for_ops(vdev_sync);
-
-	wlan_hdd_release_intf_addr(hdd_ctx, pre_cac_adapter->mac_addr.bytes);
-	hdd_close_adapter(hdd_ctx, pre_cac_adapter, true);
-
-	osif_vdev_sync_trans_stop(vdev_sync);
-	osif_vdev_sync_destroy(vdev_sync);
-}
-#else
-static inline void
-hdd_close_pre_cac_adapter(struct hdd_context *hdd_ctx)
-{
-}
-#endif
-
 QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
 				struct hdd_adapter *adapter)
 {
@@ -19168,33 +19135,6 @@ void hdd_set_conparam(int32_t con_param)
 	curr_con_mode = con_param;
 }
 
-#ifdef PRE_CAC_SUPPORT
-void hdd_clean_up_pre_cac_interface(struct hdd_context *hdd_ctx)
-{
-	uint8_t vdev_id;
-	QDF_STATUS status;
-	struct hdd_adapter *precac_adapter;
-
-	status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->mac_handle, &vdev_id);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_err("failed to get pre cac vdev id");
-		return;
-	}
-
-	precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
-	if (!precac_adapter) {
-		hdd_err("invalid pre cac adapter");
-		return;
-	}
-
-	qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
-			wlan_hdd_sap_pre_cac_failure,
-			(void *)precac_adapter);
-	qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
-
-}
-#endif
-
 /**
  * hdd_svc_fw_crashed_ind() - API to send FW CRASHED IND to Userspace
  *

+ 1 - 0
core/hdd/src/wlan_hdd_p2p.c

@@ -54,6 +54,7 @@
 #include "nan_ucfg_api.h"
 #include "wlan_pkt_capture_ucfg_api.h"
 #include "wlan_hdd_object_manager.h"
+#include "wlan_hdd_pre_cac.h"
 
 /* Ms to Time Unit Micro Sec */
 #define MS_TO_TU_MUS(x)   ((x) * 1024)

+ 755 - 0
core/hdd/src/wlan_hdd_pre_cac.c

@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "osif_vdev_sync.h"
+#include "wlan_hdd_hostapd.h"
+#include "wlan_hdd_pre_cac.h"
+
+void hdd_send_conditional_chan_switch_status(struct hdd_context *hdd_ctx,
+					     struct wireless_dev *wdev,
+					     bool status)
+{
+	struct sk_buff *event;
+
+	hdd_enter_dev(wdev->netdev);
+
+	if (!hdd_ctx) {
+		hdd_err("Invalid HDD context pointer");
+		return;
+	}
+
+	event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
+		  wdev, sizeof(uint32_t) + NLMSG_HDRLEN,
+		  QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX,
+		  GFP_KERNEL);
+	if (!event) {
+		hdd_err("cfg80211_vendor_event_alloc failed");
+		return;
+	}
+
+	if (nla_put_u32(event,
+			QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS,
+			status)) {
+		hdd_err("nla put failed");
+		kfree_skb(event);
+		return;
+	}
+
+	cfg80211_vendor_event(event, GFP_KERNEL);
+}
+
+/**
+ * wlan_hdd_set_pre_cac_complete_status() - Set pre cac complete status
+ * @ap_adapter: AP adapter
+ * @status: Status which can be true or false
+ *
+ * Sets the status of pre cac i.e., whether it is complete or not
+ *
+ * Return: Zero on success, non-zero on failure
+ */
+static int wlan_hdd_set_pre_cac_complete_status(struct hdd_adapter *ap_adapter,
+						bool status)
+{
+	QDF_STATUS ret;
+
+	ret = wlan_sap_set_pre_cac_complete_status(
+			WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), status);
+	if (QDF_IS_STATUS_ERROR(ret))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * __wlan_hdd_sap_pre_cac_failure() - Process the pre cac failure
+ * @adapter: AP adapter
+ *
+ * Deletes the pre cac adapter
+ *
+ * Return: None
+ */
+static void __wlan_hdd_sap_pre_cac_failure(struct hdd_adapter *adapter)
+{
+	struct hdd_context *hdd_ctx;
+
+	hdd_enter();
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	if (wlan_hdd_validate_context(hdd_ctx))
+		return;
+
+	hdd_stop_adapter(hdd_ctx, adapter);
+
+	hdd_exit();
+}
+
+/**
+ * wlan_hdd_sap_pre_cac_failure() - Process the pre cac failure
+ * @data: AP adapter
+ *
+ * Deletes the pre cac adapter
+ *
+ * Return: None
+ */
+void wlan_hdd_sap_pre_cac_failure(void *data)
+{
+	struct hdd_adapter *adapter = data;
+	struct osif_vdev_sync *vdev_sync;
+	int errno;
+
+	errno = osif_vdev_sync_trans_start_wait(adapter->dev, &vdev_sync);
+	if (errno)
+		return;
+
+	__wlan_hdd_sap_pre_cac_failure(data);
+
+	osif_vdev_sync_trans_stop(vdev_sync);
+}
+
+/**
+ * __wlan_hdd_sap_pre_cac_success() - Process the pre cac result
+ * @adapter: AP adapter
+ *
+ * Stops the pre cac adapter and moves the existing SAP to the pre cac
+ * channel
+ *
+ * Return: None
+ */
+static void __wlan_hdd_sap_pre_cac_success(struct hdd_adapter *adapter)
+{
+	struct hdd_adapter *ap_adapter;
+	int i;
+	struct hdd_context *hdd_ctx;
+	enum phy_ch_width pre_cac_ch_width;
+
+	hdd_enter();
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	if (!hdd_ctx) {
+		hdd_err("HDD context is null");
+		return;
+	}
+
+	pre_cac_ch_width = wlansap_get_chan_width(
+				WLAN_HDD_GET_SAP_CTX_PTR(adapter));
+
+	hdd_stop_adapter(hdd_ctx, adapter);
+
+	/* Prepare to switch AP from 2.4GHz channel to the pre CAC channel */
+	ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
+	if (!ap_adapter) {
+		hdd_err("failed to get SAP adapter, no restart on pre CAC channel");
+		return;
+	}
+
+	/*
+	 * Setting of the pre cac complete status will ensure that on channel
+	 * switch to the pre CAC DFS channel, there is no CAC again.
+	 */
+	wlan_hdd_set_pre_cac_complete_status(ap_adapter, true);
+
+	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->vdev_id,
+				    CSA_REASON_PRE_CAC_SUCCESS);
+	i = hdd_softap_set_channel_change(ap_adapter->dev,
+					  ap_adapter->pre_cac_freq,
+					  pre_cac_ch_width, false);
+	if (i) {
+		hdd_err("failed to change channel");
+		wlan_hdd_set_pre_cac_complete_status(ap_adapter, false);
+	}
+
+	hdd_exit();
+}
+
+void wlan_hdd_sap_pre_cac_success(void *data)
+{
+	struct hdd_adapter *adapter = data;
+	struct osif_vdev_sync *vdev_sync;
+	int errno;
+
+	errno = osif_vdev_sync_trans_start_wait(adapter->dev, &vdev_sync);
+	if (errno)
+		return;
+
+	__wlan_hdd_sap_pre_cac_success(adapter);
+
+	osif_vdev_sync_trans_stop(vdev_sync);
+}
+
+void hdd_close_pre_cac_adapter(struct hdd_context *hdd_ctx)
+{
+	struct hdd_adapter *pre_cac_adapter;
+	struct osif_vdev_sync *vdev_sync;
+	int errno;
+
+	pre_cac_adapter = hdd_get_adapter_by_iface_name(hdd_ctx,
+							SAP_PRE_CAC_IFNAME);
+	if (!pre_cac_adapter)
+		return;
+
+	errno = osif_vdev_sync_trans_start_wait(pre_cac_adapter->dev,
+						&vdev_sync);
+	if (errno)
+		return;
+
+	osif_vdev_sync_unregister(pre_cac_adapter->dev);
+	osif_vdev_sync_wait_for_ops(vdev_sync);
+
+	wlan_hdd_release_intf_addr(hdd_ctx, pre_cac_adapter->mac_addr.bytes);
+	hdd_close_adapter(hdd_ctx, pre_cac_adapter, true);
+
+	osif_vdev_sync_trans_stop(vdev_sync);
+	osif_vdev_sync_destroy(vdev_sync);
+}
+
+void hdd_clean_up_pre_cac_interface(struct hdd_context *hdd_ctx)
+{
+	uint8_t vdev_id;
+	QDF_STATUS status;
+	struct hdd_adapter *precac_adapter;
+
+	status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->mac_handle, &vdev_id);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("failed to get pre cac vdev id");
+		return;
+	}
+
+	precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+	if (!precac_adapter) {
+		hdd_err("invalid pre cac adapter");
+		return;
+	}
+
+	qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
+			wlan_hdd_sap_pre_cac_failure,
+			(void *)precac_adapter);
+	qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
+}
+
+/**
+ * wlan_hdd_set_pre_cac_status() - Set the pre cac status
+ * @pre_cac_adapter: AP adapter used for pre cac
+ * @status: Status (true or false)
+ *
+ * Sets the status of pre cac i.e., whether the pre cac is active or not
+ *
+ * Return: Zero on success, non-zero on failure
+ */
+static int wlan_hdd_set_pre_cac_status(struct hdd_adapter *pre_cac_adapter,
+				       bool status)
+{
+	QDF_STATUS ret;
+
+	ret = wlan_sap_set_pre_cac_status(
+		WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status);
+	if (QDF_IS_STATUS_ERROR(ret))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * wlan_hdd_set_chan_freq_before_pre_cac() - Save the channel before pre cac
+ * @ap_adapter: AP adapter
+ * @freq_before_pre_cac: Channel
+ *
+ * Saves the channel frequency which the AP was beaconing on before moving to
+ * the pre cac channel. If radar is detected on the pre cac channel, this saved
+ * channel will be used for AP operations.
+ *
+ * Return: Zero on success, non-zero on failure
+ */
+static int
+wlan_hdd_set_chan_freq_before_pre_cac(struct hdd_adapter *ap_adapter,
+				      qdf_freq_t freq_before_pre_cac)
+{
+	QDF_STATUS ret;
+	struct sap_context *sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter);
+
+	ret = wlan_sap_set_chan_freq_before_pre_cac(sap_ctx,
+						    freq_before_pre_cac);
+	if (QDF_IS_STATUS_ERROR(ret))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
+ * @hdd_ctx: HDD context
+ * @ap_adapter: AP adapter
+ * @chan_freq: Channel frequency requested by userspace
+ * @pre_cac_chan_freq: Pointer to the pre CAC channel frequency storage
+ *
+ * Validates the channel provided by userspace. If user provided channel 0,
+ * a valid outdoor channel must be selected from the regulatory channel.
+ *
+ * Return: Zero on success and non zero value on error
+ */
+static int wlan_hdd_validate_and_get_pre_cac_ch(struct hdd_context *hdd_ctx,
+						struct hdd_adapter *ap_adapter,
+						uint32_t chan_freq,
+						uint32_t *pre_cac_chan_freq)
+{
+	uint32_t i;
+	QDF_STATUS status;
+	uint32_t weight_len = 0;
+	uint32_t len = CFG_VALID_CHANNEL_LIST_LEN;
+	uint32_t freq_list[NUM_CHANNELS] = {0};
+	uint8_t pcl_weights[NUM_CHANNELS] = {0};
+	mac_handle_t mac_handle;
+
+	if (!chan_freq) {
+		/* Channel is not obtained from PCL because PCL may not have
+		 * the entire channel list. For example: if SAP is up on
+		 * channel 6 and PCL is queried for the next SAP interface,
+		 * if SCC is preferred, the PCL will contain only the channel
+		 * 6. But, we are in need of a DFS channel. So, going with the
+		 * first channel from the valid channel list.
+		 */
+		status = policy_mgr_get_valid_chans(hdd_ctx->psoc,
+						    freq_list, &len);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			hdd_err("Failed to get channel list");
+			return -EINVAL;
+		}
+		policy_mgr_update_with_safe_channel_list(hdd_ctx->psoc,
+							 freq_list, &len,
+							 pcl_weights,
+							 weight_len);
+		for (i = 0; i < len; i++) {
+			if (wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
+						     freq_list[i])) {
+				*pre_cac_chan_freq = freq_list[i];
+				break;
+			}
+		}
+		if (*pre_cac_chan_freq == 0) {
+			hdd_err("unable to find outdoor channel");
+			return -EINVAL;
+		}
+	} else {
+		/* Only when driver selects a channel, check is done for
+		 * unnsafe and NOL channels. When user provides a fixed channel
+		 * the user is expected to take care of this.
+		 */
+		mac_handle = hdd_ctx->mac_handle;
+		if (!sme_is_channel_valid(mac_handle, chan_freq) ||
+		    !wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, chan_freq)) {
+			hdd_err("Invalid channel for pre cac:%d", chan_freq);
+			return -EINVAL;
+		}
+		*pre_cac_chan_freq = chan_freq;
+	}
+	hdd_debug("selected pre cac channel:%d", *pre_cac_chan_freq);
+	return 0;
+}
+
+static int wlan_set_def_pre_cac_chan(struct hdd_context *hdd_ctx,
+				     uint32_t pre_cac_ch_freq,
+				     struct cfg80211_chan_def *chandef,
+				     enum nl80211_channel_type *chantype,
+				     enum phy_ch_width *ch_width)
+{
+	enum nl80211_channel_type channel_type;
+	struct ieee80211_channel *ieee_chan;
+	struct ch_params ch_params = {0};
+
+	ieee_chan = ieee80211_get_channel(hdd_ctx->wiphy,
+					  pre_cac_ch_freq);
+	if (!ieee_chan) {
+		hdd_err("channel converion failed %d", pre_cac_ch_freq);
+		return -EINVAL;
+	}
+	ch_params.ch_width = *ch_width;
+	wlan_reg_set_channel_params_for_freq(hdd_ctx->pdev,
+					     pre_cac_ch_freq, 0,
+					     &ch_params);
+	switch (ch_params.sec_ch_offset) {
+	case HIGH_PRIMARY_CH:
+		channel_type = NL80211_CHAN_HT40MINUS;
+		break;
+	case LOW_PRIMARY_CH:
+		channel_type = NL80211_CHAN_HT40PLUS;
+		break;
+	default:
+		channel_type = NL80211_CHAN_HT20;
+		break;
+	}
+	cfg80211_chandef_create(chandef, ieee_chan, channel_type);
+	switch (ch_params.ch_width) {
+	case CH_WIDTH_80MHZ:
+		chandef->width = NL80211_CHAN_WIDTH_80;
+		break;
+	case CH_WIDTH_80P80MHZ:
+		chandef->width = NL80211_CHAN_WIDTH_80P80;
+		if (ch_params.mhz_freq_seg1)
+			chandef->center_freq2 = ch_params.mhz_freq_seg1;
+		break;
+	case CH_WIDTH_160MHZ:
+		chandef->width = NL80211_CHAN_WIDTH_160;
+		break;
+	default:
+		break;
+	}
+	if (ch_params.ch_width == CH_WIDTH_80MHZ ||
+	    ch_params.ch_width == CH_WIDTH_80P80MHZ ||
+	    ch_params.ch_width == CH_WIDTH_160MHZ) {
+		if (ch_params.mhz_freq_seg0)
+			chandef->center_freq1 = ch_params.mhz_freq_seg0;
+	}
+	*chantype = channel_type;
+	*ch_width = ch_params.ch_width;
+	hdd_debug("pre cac ch def: chan:%d width:%d freq1:%d freq2:%d",
+		  chandef->chan->center_freq, chandef->width,
+		  chandef->center_freq1, chandef->center_freq2);
+
+	return 0;
+}
+
+/**
+ * __wlan_hdd_request_pre_cac() - Start pre CAC in the driver
+ * @hdd_ctx: the HDD context to operate against
+ * @chan_freq: Channel frequency option provided by userspace
+ * @out_adapter: out parameter for the newly created pre-cac adapter
+ *
+ * Sets the driver to the required hardware mode and start an adapter for
+ * pre CAC which will mimic an AP.
+ *
+ * Return: Zero on success, non-zero value on error
+ */
+static int __wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx,
+				      uint32_t chan_freq,
+				      struct hdd_adapter **out_adapter)
+{
+	uint8_t *mac_addr = NULL;
+	uint32_t pre_cac_chan_freq = 0;
+	int ret;
+	struct hdd_adapter *ap_adapter, *pre_cac_adapter;
+	struct hdd_ap_ctx *hdd_ap_ctx;
+	QDF_STATUS status;
+	struct wiphy *wiphy;
+	struct net_device *dev;
+	struct cfg80211_chan_def chandef;
+	enum nl80211_channel_type channel_type;
+	mac_handle_t mac_handle;
+	bool val;
+	enum phy_ch_width cac_ch_width;
+	struct hdd_adapter_create_param params = {0};
+	qdf_freq_t freq;
+
+	if (!policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc)) {
+		hdd_debug("Pre CAC is not supported on non-dbs platforms");
+		return -EINVAL;
+	}
+
+	pre_cac_adapter = hdd_get_adapter_by_iface_name(hdd_ctx,
+							SAP_PRE_CAC_IFNAME);
+	if (pre_cac_adapter) {
+		/* Flush existing pre_cac work */
+		if (hdd_ctx->sap_pre_cac_work.fn)
+			cds_flush_work(&hdd_ctx->sap_pre_cac_work);
+	} else {
+		if (policy_mgr_get_connection_count(hdd_ctx->psoc) > 1) {
+			hdd_err("pre cac not allowed in concurrency");
+			return -EINVAL;
+		}
+	}
+
+	ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
+	if (!ap_adapter) {
+		hdd_err("unable to get SAP adapter");
+		return -EINVAL;
+	}
+
+	if (qdf_atomic_read(&ap_adapter->ch_switch_in_progress)) {
+		hdd_err("pre cac not allowed during CSA");
+		return -EINVAL;
+	}
+
+	mac_handle = hdd_ctx->mac_handle;
+	val = wlan_sap_is_pre_cac_active(mac_handle);
+	if (val) {
+		hdd_err("pre cac is already in progress");
+		return -EINVAL;
+	}
+
+	hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
+	if (!hdd_ap_ctx) {
+		hdd_err("SAP context is NULL");
+		return -EINVAL;
+	}
+
+	if (wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
+				     hdd_ap_ctx->operating_chan_freq)) {
+		hdd_err("SAP is already on DFS channel:%d",
+			hdd_ap_ctx->operating_chan_freq);
+		return -EINVAL;
+	}
+
+	if (!WLAN_REG_IS_24GHZ_CH_FREQ(hdd_ap_ctx->operating_chan_freq)) {
+		hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
+			hdd_ap_ctx->operating_chan_freq);
+		return -EINVAL;
+	}
+
+	hdd_debug("channel: %d", chan_freq);
+
+	ret = wlan_hdd_validate_and_get_pre_cac_ch(
+		hdd_ctx, ap_adapter, chan_freq, &pre_cac_chan_freq);
+	if (ret != 0) {
+		hdd_err("can't validate pre-cac channel");
+		goto release_intf_addr_and_return_failure;
+	}
+
+	hdd_debug("starting pre cac SAP  adapter");
+
+	if (!pre_cac_adapter) {
+		mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_SAP_MODE);
+		if (!mac_addr) {
+			hdd_err("can't add virtual intf: Not getting valid mac addr");
+			return -EINVAL;
+		}
+
+		/**
+		 * Starting a SAP adapter:
+		 * Instead of opening an adapter, we could just do a SME open
+		 * session for AP type. But, start BSS would still need an
+		 * adapter. So, this option is not taken.
+		 *
+		 * hdd open adapter is going to register this precac interface
+		 * with user space. This interface though exposed to user space
+		 * will be in DOWN state. Consideration was done to avoid this
+		 * registration to the user space. But, as part of SAP
+		 * operations multiple events are sent to user space. Some of
+		 * these events received from unregistered interface was
+		 * causing crashes. So, retaining the registration.
+		 *
+		 * So, this interface would remain registered and will remain
+		 * in DOWN state for the CAC duration. We will add notes in the
+		 * feature announcement to not use this temporary interface for
+		 * any activity from user space.
+		 */
+		params.is_add_virtual_iface = 1;
+		pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE,
+						   SAP_PRE_CAC_IFNAME, mac_addr,
+						   NET_NAME_UNKNOWN, true,
+						   &params);
+
+		if (!pre_cac_adapter) {
+			hdd_err("error opening the pre cac adapter");
+			goto release_intf_addr_and_return_failure;
+		}
+	}
+
+	sap_clear_global_dfs_param(mac_handle,
+				   WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter));
+
+	/*
+	 * This interface is internally created by the driver. So, no interface
+	 * up comes for this interface from user space and hence starting
+	 * the adapter internally.
+	 */
+	if (hdd_start_adapter(pre_cac_adapter)) {
+		hdd_err("error starting the pre cac adapter");
+		goto close_pre_cac_adapter;
+	}
+
+	hdd_debug("preparing for start ap/bss on the pre cac adapter");
+
+	wiphy = hdd_ctx->wiphy;
+	dev = pre_cac_adapter->dev;
+
+	/* Since this is only a dummy interface lets us use the IEs from the
+	 * other active SAP interface. In regular scenarios, these IEs would
+	 * come from the user space entity
+	 */
+	pre_cac_adapter->session.ap.beacon = qdf_mem_malloc(
+			sizeof(*ap_adapter->session.ap.beacon));
+	if (!pre_cac_adapter->session.ap.beacon)
+		goto stop_close_pre_cac_adapter;
+
+	qdf_mem_copy(pre_cac_adapter->session.ap.beacon,
+		     ap_adapter->session.ap.beacon,
+		     sizeof(*pre_cac_adapter->session.ap.beacon));
+	pre_cac_adapter->session.ap.sap_config.ch_width_orig =
+			ap_adapter->session.ap.sap_config.ch_width_orig;
+	pre_cac_adapter->session.ap.sap_config.authType =
+			ap_adapter->session.ap.sap_config.authType;
+
+	/* The orginal premise is that on moving from 2.4GHz to 5GHz, the SAP
+	 * will continue to operate on the same bandwidth as that of the 2.4GHz
+	 * operations. Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
+	 * Now some customer request to start AP on higher BW such as 80Mhz.
+	 * Hence use max possible supported BW based on phymode configurated
+	 * on SAP.
+	 */
+	cac_ch_width = wlansap_get_max_bw_by_phymode(
+			WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter));
+	if (cac_ch_width > DEFAULT_PRE_CAC_BANDWIDTH)
+		cac_ch_width = DEFAULT_PRE_CAC_BANDWIDTH;
+
+	qdf_mem_zero(&chandef, sizeof(struct cfg80211_chan_def));
+	if (wlan_set_def_pre_cac_chan(hdd_ctx, pre_cac_chan_freq,
+				      &chandef, &channel_type,
+				      &cac_ch_width)) {
+		hdd_err("error set pre_cac channel %d", pre_cac_chan_freq);
+		goto close_pre_cac_adapter;
+	}
+	pre_cac_adapter->session.ap.sap_config.ch_width_orig =
+					hdd_map_nl_chan_width(chandef.width);
+
+	hdd_debug("existing ap phymode:%d pre cac ch_width:%d freq:%d",
+		  ap_adapter->session.ap.sap_config.SapHw_mode,
+		  cac_ch_width, pre_cac_chan_freq);
+	/*
+	 * Doing update after opening and starting pre-cac adapter will make
+	 * sure that driver won't do hardware mode change if there are any
+	 * initial hick-ups or issues in pre-cac adapter's configuration.
+	 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
+	 * connection update should result in DBS mode
+	 */
+	status = policy_mgr_update_and_wait_for_connection_update(
+			hdd_ctx->psoc, ap_adapter->vdev_id, pre_cac_chan_freq,
+			POLICY_MGR_UPDATE_REASON_PRE_CAC);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("error in moving to DBS mode");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
+	if (ret != 0) {
+		hdd_err("failed to set channel");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
+					     PRE_CAC_SSID,
+					     qdf_str_len(PRE_CAC_SSID),
+					     NL80211_HIDDEN_SSID_NOT_IN_USE,
+					     false);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("start bss failed");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	/*
+	 * The pre cac status is set here. But, it would not be reset explicitly
+	 * anywhere, since after the pre cac success/failure, the pre cac
+	 * adapter itself would be removed.
+	 */
+	ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true);
+	if (ret != 0) {
+		hdd_err("failed to set pre cac status");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	freq = hdd_ap_ctx->operating_chan_freq;
+	ret = wlan_hdd_set_chan_freq_before_pre_cac(ap_adapter,
+						    freq);
+	if (ret != 0) {
+		hdd_err("failed to set channel before pre cac");
+		goto stop_close_pre_cac_adapter;
+	}
+
+	ap_adapter->pre_cac_freq = pre_cac_chan_freq;
+	pre_cac_adapter->is_pre_cac_adapter = true;
+
+	*out_adapter = pre_cac_adapter;
+
+	return 0;
+
+stop_close_pre_cac_adapter:
+	hdd_stop_adapter(hdd_ctx, pre_cac_adapter);
+	qdf_mem_free(pre_cac_adapter->session.ap.beacon);
+	pre_cac_adapter->session.ap.beacon = NULL;
+close_pre_cac_adapter:
+	hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
+release_intf_addr_and_return_failure:
+	/*
+	 * Release the interface address as the adapter
+	 * failed to start, if you don't release then next
+	 * adapter which is trying to come wouldn't get valid
+	 * mac address. Remember we have limited pool of mac addresses
+	 */
+	if (mac_addr)
+		wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
+	return -EINVAL;
+}
+
+static int
+wlan_hdd_start_pre_cac_trans(struct hdd_context *hdd_ctx,
+			     struct osif_vdev_sync **out_vdev_sync,
+			     bool *is_vdev_sync_created)
+{
+	struct hdd_adapter *adapter, *next_adapter = NULL;
+	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_START_PRE_CAC_TRANS;
+	int errno;
+
+	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
+					   dbgid) {
+		if (!qdf_str_cmp(adapter->dev->name, SAP_PRE_CAC_IFNAME)) {
+			errno = osif_vdev_sync_trans_start(adapter->dev,
+							   out_vdev_sync);
+
+			hdd_adapter_dev_put_debug(adapter, dbgid);
+			if (next_adapter)
+				hdd_adapter_dev_put_debug(next_adapter,
+							  dbgid);
+			return errno;
+		}
+		hdd_adapter_dev_put_debug(adapter, dbgid);
+	}
+
+	errno = osif_vdev_sync_create_and_trans(hdd_ctx->parent_dev,
+						out_vdev_sync);
+	if (errno)
+		return errno;
+
+	*is_vdev_sync_created = true;
+	return 0;
+}
+
+int wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx, uint32_t chan_freq)
+{
+	struct hdd_adapter *adapter;
+	struct osif_vdev_sync *vdev_sync;
+	int errno;
+	bool is_vdev_sync_created = false;
+
+	errno = wlan_hdd_start_pre_cac_trans(hdd_ctx, &vdev_sync,
+					     &is_vdev_sync_created);
+	if (errno)
+		return errno;
+
+	errno = __wlan_hdd_request_pre_cac(hdd_ctx, chan_freq, &adapter);
+	if (errno)
+		goto destroy_sync;
+
+	if (is_vdev_sync_created)
+		osif_vdev_sync_register(adapter->dev, vdev_sync);
+	osif_vdev_sync_trans_stop(vdev_sync);
+
+	return 0;
+
+destroy_sync:
+	osif_vdev_sync_trans_stop(vdev_sync);
+	if (is_vdev_sync_created)
+		osif_vdev_sync_destroy(vdev_sync);
+
+	return errno;
+}

+ 1 - 516
core/hdd/src/wlan_hdd_sap_cond_chan_switch.c

@@ -33,522 +33,7 @@
 #include <qdf_str.h>
 #include <wlan_hdd_includes.h>
 #include <wlan_hdd_sap_cond_chan_switch.h>
-
-#ifdef PRE_CAC_SUPPORT
-/* default pre cac channel bandwidth */
-#define DEFAULT_PRE_CAC_BANDWIDTH CH_WIDTH_80MHZ
-
-/**
- * wlan_hdd_set_pre_cac_status() - Set the pre cac status
- * @pre_cac_adapter: AP adapter used for pre cac
- * @status: Status (true or false)
- *
- * Sets the status of pre cac i.e., whether the pre cac is active or not
- *
- * Return: Zero on success, non-zero on failure
- */
-static int wlan_hdd_set_pre_cac_status(struct hdd_adapter *pre_cac_adapter,
-				       bool status)
-{
-	QDF_STATUS ret;
-
-	ret = wlan_sap_set_pre_cac_status(
-		WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status);
-	if (QDF_IS_STATUS_ERROR(ret))
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- * wlan_hdd_set_chan_freq_before_pre_cac() - Save the channel before pre cac
- * @ap_adapter: AP adapter
- * @freq_before_pre_cac: Channel
- *
- * Saves the channel frequency which the AP was beaconing on before moving to
- * the pre cac channel. If radar is detected on the pre cac channel, this saved
- * channel will be used for AP operations.
- *
- * Return: Zero on success, non-zero on failure
- */
-static int
-wlan_hdd_set_chan_freq_before_pre_cac(struct hdd_adapter *ap_adapter,
-				      qdf_freq_t freq_before_pre_cac)
-{
-	QDF_STATUS ret;
-	struct sap_context *sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter);
-
-	ret = wlan_sap_set_chan_freq_before_pre_cac(sap_ctx,
-						    freq_before_pre_cac);
-	if (QDF_IS_STATUS_ERROR(ret))
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
- * @hdd_ctx: HDD context
- * @ap_adapter: AP adapter
- * @chan_freq: Channel frequency requested by userspace
- * @pre_cac_chan_freq: Pointer to the pre CAC channel frequency storage
- *
- * Validates the channel provided by userspace. If user provided channel 0,
- * a valid outdoor channel must be selected from the regulatory channel.
- *
- * Return: Zero on success and non zero value on error
- */
-static int wlan_hdd_validate_and_get_pre_cac_ch(struct hdd_context *hdd_ctx,
-						struct hdd_adapter *ap_adapter,
-						uint32_t chan_freq,
-						uint32_t *pre_cac_chan_freq)
-{
-	uint32_t i;
-	QDF_STATUS status;
-	uint32_t weight_len = 0;
-	uint32_t len = CFG_VALID_CHANNEL_LIST_LEN;
-	uint32_t freq_list[NUM_CHANNELS] = {0};
-	uint8_t pcl_weights[NUM_CHANNELS] = {0};
-	mac_handle_t mac_handle;
-
-	if (!chan_freq) {
-		/* Channel is not obtained from PCL because PCL may not have
-		 * the entire channel list. For example: if SAP is up on
-		 * channel 6 and PCL is queried for the next SAP interface,
-		 * if SCC is preferred, the PCL will contain only the channel
-		 * 6. But, we are in need of a DFS channel. So, going with the
-		 * first channel from the valid channel list.
-		 */
-		status = policy_mgr_get_valid_chans(hdd_ctx->psoc,
-						    freq_list, &len);
-		if (QDF_IS_STATUS_ERROR(status)) {
-			hdd_err("Failed to get channel list");
-			return -EINVAL;
-		}
-		policy_mgr_update_with_safe_channel_list(hdd_ctx->psoc,
-							 freq_list, &len,
-							 pcl_weights,
-							 weight_len);
-		for (i = 0; i < len; i++) {
-			if (wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
-						     freq_list[i])) {
-				*pre_cac_chan_freq = freq_list[i];
-				break;
-			}
-		}
-		if (*pre_cac_chan_freq == 0) {
-			hdd_err("unable to find outdoor channel");
-			return -EINVAL;
-		}
-	} else {
-		/* Only when driver selects a channel, check is done for
-		 * unnsafe and NOL channels. When user provides a fixed channel
-		 * the user is expected to take care of this.
-		 */
-		mac_handle = hdd_ctx->mac_handle;
-		if (!sme_is_channel_valid(mac_handle, chan_freq) ||
-		    !wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, chan_freq)) {
-			hdd_err("Invalid channel for pre cac:%d", chan_freq);
-			return -EINVAL;
-		}
-		*pre_cac_chan_freq = chan_freq;
-	}
-	hdd_debug("selected pre cac channel:%d", *pre_cac_chan_freq);
-	return 0;
-}
-
-static int wlan_set_def_pre_cac_chan(struct hdd_context *hdd_ctx,
-				     uint32_t pre_cac_ch_freq,
-				     struct cfg80211_chan_def *chandef,
-				     enum nl80211_channel_type *chantype,
-				     enum phy_ch_width *ch_width)
-{
-	enum nl80211_channel_type channel_type;
-	struct ieee80211_channel *ieee_chan;
-	struct ch_params ch_params = {0};
-
-	ieee_chan = ieee80211_get_channel(hdd_ctx->wiphy,
-					  pre_cac_ch_freq);
-	if (!ieee_chan) {
-		hdd_err("channel converion failed %d", pre_cac_ch_freq);
-		return -EINVAL;
-	}
-	ch_params.ch_width = *ch_width;
-	wlan_reg_set_channel_params_for_freq(hdd_ctx->pdev,
-					     pre_cac_ch_freq, 0,
-					     &ch_params);
-	switch (ch_params.sec_ch_offset) {
-	case HIGH_PRIMARY_CH:
-		channel_type = NL80211_CHAN_HT40MINUS;
-		break;
-	case LOW_PRIMARY_CH:
-		channel_type = NL80211_CHAN_HT40PLUS;
-		break;
-	default:
-		channel_type = NL80211_CHAN_HT20;
-		break;
-	}
-	cfg80211_chandef_create(chandef, ieee_chan, channel_type);
-	switch (ch_params.ch_width) {
-	case CH_WIDTH_80MHZ:
-		chandef->width = NL80211_CHAN_WIDTH_80;
-		break;
-	case CH_WIDTH_80P80MHZ:
-		chandef->width = NL80211_CHAN_WIDTH_80P80;
-		if (ch_params.mhz_freq_seg1)
-			chandef->center_freq2 = ch_params.mhz_freq_seg1;
-		break;
-	case CH_WIDTH_160MHZ:
-		chandef->width = NL80211_CHAN_WIDTH_160;
-		break;
-	default:
-		break;
-	}
-	if (ch_params.ch_width == CH_WIDTH_80MHZ ||
-	    ch_params.ch_width == CH_WIDTH_80P80MHZ ||
-	    ch_params.ch_width == CH_WIDTH_160MHZ) {
-		if (ch_params.mhz_freq_seg0)
-			chandef->center_freq1 = ch_params.mhz_freq_seg0;
-	}
-	*chantype = channel_type;
-	*ch_width = ch_params.ch_width;
-	hdd_debug("pre cac ch def: chan:%d width:%d freq1:%d freq2:%d",
-		  chandef->chan->center_freq, chandef->width,
-		  chandef->center_freq1, chandef->center_freq2);
-
-	return 0;
-}
-
-/**
- * __wlan_hdd_request_pre_cac() - Start pre CAC in the driver
- * @hdd_ctx: the HDD context to operate against
- * @chan_freq: Channel frequency option provided by userspace
- * @out_adapter: out parameter for the newly created pre-cac adapter
- *
- * Sets the driver to the required hardware mode and start an adapter for
- * pre CAC which will mimic an AP.
- *
- * Return: Zero on success, non-zero value on error
- */
-static int __wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx,
-				      uint32_t chan_freq,
-				      struct hdd_adapter **out_adapter)
-{
-	uint8_t *mac_addr = NULL;
-	uint32_t pre_cac_chan_freq = 0;
-	int ret;
-	struct hdd_adapter *ap_adapter, *pre_cac_adapter;
-	struct hdd_ap_ctx *hdd_ap_ctx;
-	QDF_STATUS status;
-	struct wiphy *wiphy;
-	struct net_device *dev;
-	struct cfg80211_chan_def chandef;
-	enum nl80211_channel_type channel_type;
-	mac_handle_t mac_handle;
-	bool val;
-	enum phy_ch_width cac_ch_width;
-	struct hdd_adapter_create_param params = {0};
-
-	if (!policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc)) {
-		hdd_debug("Pre CAC is not supported on non-dbs platforms");
-		return -EINVAL;
-	}
-
-	pre_cac_adapter = hdd_get_adapter_by_iface_name(hdd_ctx,
-							SAP_PRE_CAC_IFNAME);
-	if (pre_cac_adapter) {
-		/* Flush existing pre_cac work */
-		if (hdd_ctx->sap_pre_cac_work.fn)
-			cds_flush_work(&hdd_ctx->sap_pre_cac_work);
-	} else {
-		if (policy_mgr_get_connection_count(hdd_ctx->psoc) > 1) {
-			hdd_err("pre cac not allowed in concurrency");
-			return -EINVAL;
-		}
-	}
-
-	ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
-	if (!ap_adapter) {
-		hdd_err("unable to get SAP adapter");
-		return -EINVAL;
-	}
-
-	if (qdf_atomic_read(&ap_adapter->ch_switch_in_progress)) {
-		hdd_err("pre cac not allowed during CSA");
-		return -EINVAL;
-	}
-
-	mac_handle = hdd_ctx->mac_handle;
-	val = wlan_sap_is_pre_cac_active(mac_handle);
-	if (val) {
-		hdd_err("pre cac is already in progress");
-		return -EINVAL;
-	}
-
-	hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
-	if (!hdd_ap_ctx) {
-		hdd_err("SAP context is NULL");
-		return -EINVAL;
-	}
-
-	if (wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
-				     hdd_ap_ctx->operating_chan_freq)) {
-		hdd_err("SAP is already on DFS channel:%d",
-			hdd_ap_ctx->operating_chan_freq);
-		return -EINVAL;
-	}
-
-	if (!WLAN_REG_IS_24GHZ_CH_FREQ(hdd_ap_ctx->operating_chan_freq)) {
-		hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
-			hdd_ap_ctx->operating_chan_freq);
-		return -EINVAL;
-	}
-
-	hdd_debug("channel: %d", chan_freq);
-
-	ret = wlan_hdd_validate_and_get_pre_cac_ch(
-		hdd_ctx, ap_adapter, chan_freq, &pre_cac_chan_freq);
-	if (ret != 0) {
-		hdd_err("can't validate pre-cac channel");
-		goto release_intf_addr_and_return_failure;
-	}
-
-	hdd_debug("starting pre cac SAP  adapter");
-
-	if (!pre_cac_adapter) {
-		mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_SAP_MODE);
-		if (!mac_addr) {
-			hdd_err("can't add virtual intf: Not getting valid mac addr");
-			return -EINVAL;
-		}
-
-		/**
-		 * Starting a SAP adapter:
-		 * Instead of opening an adapter, we could just do a SME open
-		 * session for AP type. But, start BSS would still need an
-		 * adapter. So, this option is not taken.
-		 *
-		 * hdd open adapter is going to register this precac interface
-		 * with user space. This interface though exposed to user space
-		 * will be in DOWN state. Consideration was done to avoid this
-		 * registration to the user space. But, as part of SAP
-		 * operations multiple events are sent to user space. Some of
-		 * these events received from unregistered interface was
-		 * causing crashes. So, retaining the registration.
-		 *
-		 * So, this interface would remain registered and will remain
-		 * in DOWN state for the CAC duration. We will add notes in the
-		 * feature announcement to not use this temporary interface for
-		 * any activity from user space.
-		 */
-		params.is_add_virtual_iface = 1;
-		pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE,
-						   SAP_PRE_CAC_IFNAME, mac_addr,
-						   NET_NAME_UNKNOWN, true,
-						   &params);
-
-		if (!pre_cac_adapter) {
-			hdd_err("error opening the pre cac adapter");
-			goto release_intf_addr_and_return_failure;
-		}
-	}
-
-	sap_clear_global_dfs_param(mac_handle,
-				   WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter));
-
-	/*
-	 * This interface is internally created by the driver. So, no interface
-	 * up comes for this interface from user space and hence starting
-	 * the adapter internally.
-	 */
-	if (hdd_start_adapter(pre_cac_adapter)) {
-		hdd_err("error starting the pre cac adapter");
-		goto close_pre_cac_adapter;
-	}
-
-	hdd_debug("preparing for start ap/bss on the pre cac adapter");
-
-	wiphy = hdd_ctx->wiphy;
-	dev = pre_cac_adapter->dev;
-
-	/* Since this is only a dummy interface lets us use the IEs from the
-	 * other active SAP interface. In regular scenarios, these IEs would
-	 * come from the user space entity
-	 */
-	pre_cac_adapter->session.ap.beacon = qdf_mem_malloc(
-			sizeof(*ap_adapter->session.ap.beacon));
-	if (!pre_cac_adapter->session.ap.beacon)
-		goto stop_close_pre_cac_adapter;
-
-	qdf_mem_copy(pre_cac_adapter->session.ap.beacon,
-		     ap_adapter->session.ap.beacon,
-		     sizeof(*pre_cac_adapter->session.ap.beacon));
-	pre_cac_adapter->session.ap.sap_config.ch_width_orig =
-			ap_adapter->session.ap.sap_config.ch_width_orig;
-	pre_cac_adapter->session.ap.sap_config.authType =
-			ap_adapter->session.ap.sap_config.authType;
-
-	/* The orginal premise is that on moving from 2.4GHz to 5GHz, the SAP
-	 * will continue to operate on the same bandwidth as that of the 2.4GHz
-	 * operations. Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
-	 * Now some customer request to start AP on higher BW such as 80Mhz.
-	 * Hence use max possible supported BW based on phymode configurated
-	 * on SAP.
-	 */
-	cac_ch_width = wlansap_get_max_bw_by_phymode(
-			WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter));
-	if (cac_ch_width > DEFAULT_PRE_CAC_BANDWIDTH)
-		cac_ch_width = DEFAULT_PRE_CAC_BANDWIDTH;
-
-	qdf_mem_zero(&chandef, sizeof(struct cfg80211_chan_def));
-	if (wlan_set_def_pre_cac_chan(hdd_ctx, pre_cac_chan_freq,
-				      &chandef, &channel_type,
-				      &cac_ch_width)) {
-		hdd_err("error set pre_cac channel %d", pre_cac_chan_freq);
-		goto close_pre_cac_adapter;
-	}
-	pre_cac_adapter->session.ap.sap_config.ch_width_orig =
-					hdd_map_nl_chan_width(chandef.width);
-
-	hdd_debug("existing ap phymode:%d pre cac ch_width:%d freq:%d",
-		  ap_adapter->session.ap.sap_config.SapHw_mode,
-		  cac_ch_width, pre_cac_chan_freq);
-	/*
-	 * Doing update after opening and starting pre-cac adapter will make
-	 * sure that driver won't do hardware mode change if there are any
-	 * initial hick-ups or issues in pre-cac adapter's configuration.
-	 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
-	 * connection update should result in DBS mode
-	 */
-	status = policy_mgr_update_and_wait_for_connection_update(
-			hdd_ctx->psoc, ap_adapter->vdev_id, pre_cac_chan_freq,
-			POLICY_MGR_UPDATE_REASON_PRE_CAC);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_err("error in moving to DBS mode");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
-	if (ret != 0) {
-		hdd_err("failed to set channel");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
-			PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
-			NL80211_HIDDEN_SSID_NOT_IN_USE, false);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_err("start bss failed");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	/*
-	 * The pre cac status is set here. But, it would not be reset explicitly
-	 * anywhere, since after the pre cac success/failure, the pre cac
-	 * adapter itself would be removed.
-	 */
-	ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true);
-	if (ret != 0) {
-		hdd_err("failed to set pre cac status");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	ret = wlan_hdd_set_chan_freq_before_pre_cac(ap_adapter,
-						    hdd_ap_ctx->operating_chan_freq);
-	if (ret != 0) {
-		hdd_err("failed to set channel before pre cac");
-		goto stop_close_pre_cac_adapter;
-	}
-
-	ap_adapter->pre_cac_freq = pre_cac_chan_freq;
-	pre_cac_adapter->is_pre_cac_adapter = true;
-
-	*out_adapter = pre_cac_adapter;
-
-	return 0;
-
-stop_close_pre_cac_adapter:
-	hdd_stop_adapter(hdd_ctx, pre_cac_adapter);
-	qdf_mem_free(pre_cac_adapter->session.ap.beacon);
-	pre_cac_adapter->session.ap.beacon = NULL;
-close_pre_cac_adapter:
-	hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
-release_intf_addr_and_return_failure:
-	/*
-	 * Release the interface address as the adapter
-	 * failed to start, if you don't release then next
-	 * adapter which is trying to come wouldn't get valid
-	 * mac address. Remember we have limited pool of mac addresses
-	 */
-	if (mac_addr)
-		wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
-	return -EINVAL;
-}
-
-static int
-wlan_hdd_start_pre_cac_trans(struct hdd_context *hdd_ctx,
-			     struct osif_vdev_sync **out_vdev_sync,
-			     bool *is_vdev_sync_created)
-{
-	struct hdd_adapter *adapter, *next_adapter = NULL;
-	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_START_PRE_CAC_TRANS;
-	int errno;
-
-	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
-					   dbgid) {
-		if (!qdf_str_cmp(adapter->dev->name, SAP_PRE_CAC_IFNAME)) {
-			errno = osif_vdev_sync_trans_start(adapter->dev,
-							   out_vdev_sync);
-
-			hdd_adapter_dev_put_debug(adapter, dbgid);
-			if (next_adapter)
-				hdd_adapter_dev_put_debug(next_adapter,
-							  dbgid);
-			return errno;
-
-		}
-		hdd_adapter_dev_put_debug(adapter, dbgid);
-	}
-
-	errno = osif_vdev_sync_create_and_trans(hdd_ctx->parent_dev,
-						out_vdev_sync);
-	if (errno)
-		return errno;
-
-	*is_vdev_sync_created = true;
-	return 0;
-}
-
-int wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx, uint32_t chan_freq)
-{
-	struct hdd_adapter *adapter;
-	struct osif_vdev_sync *vdev_sync;
-	int errno;
-	bool is_vdev_sync_created = false;
-
-	errno = wlan_hdd_start_pre_cac_trans(hdd_ctx, &vdev_sync,
-					     &is_vdev_sync_created);
-	if (errno)
-		return errno;
-
-	errno = __wlan_hdd_request_pre_cac(hdd_ctx, chan_freq, &adapter);
-	if (errno)
-		goto destroy_sync;
-
-	if (is_vdev_sync_created)
-		osif_vdev_sync_register(adapter->dev, vdev_sync);
-	osif_vdev_sync_trans_stop(vdev_sync);
-
-	return 0;
-
-destroy_sync:
-	osif_vdev_sync_trans_stop(vdev_sync);
-	if (is_vdev_sync_created)
-		osif_vdev_sync_destroy(vdev_sync);
-
-	return errno;
-}
-#endif
+#include "wlan_hdd_pre_cac.h"
 
 const struct nla_policy conditional_chan_switch_policy[
 		QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1] = {