Pārlūkot izejas kodu

qcacld-3.0: Implement vendor command to avoid freq in SAP

qcacld-2.0 to qcacld-3.0 propagation

Add support for vendor command which ask the driver
to restart the SAP if SAP is on unsafe channel.
QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY is used to send
driver to restart SAP device if SAP is on any unsafe channels.
Upon receiving this command, driver will restart the SAP device
if SAP is operating on any of one the unsafe channels.

Change-Id: I187a6e0c9f3eaa96c740e50c332a7aba5796dc74
CRs-Fixed: 998048
Agrawal Ashish 8 gadi atpakaļ
vecāks
revīzija
467dde4b12

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

@@ -1860,4 +1860,7 @@ static inline void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
 void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context);
 
 enum  sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode);
+
+void hdd_ch_avoid_cb(void *hdd_context, void *indi_param);
+void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctx);
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

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

@@ -76,7 +76,7 @@
 #include "wlan_logging_sock_svc.h"
 #include "sap_api.h"
 #include "csr_api.h"
-
+#include "pld_common.h"
 
 
 #ifdef FEATURE_WLAN_EXTSCAN
@@ -7042,6 +7042,93 @@ static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
 	return ret;
 }
 
+#ifdef FEATURE_WLAN_CH_AVOID
+/**
+ * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
+ * is on unsafe channel.
+ * @wiphy:    wiphy structure pointer
+ * @wdev:     Wireless device structure pointer
+ * @data:     Pointer to the data received
+ * @data_len: Length of @data
+ *
+ * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
+ * on any of unsafe channels.
+ * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
+ * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
+ *
+ * Return: 0 on success; errno on failure
+ */
+static int
+__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
+		struct wireless_dev *wdev,
+		const void *data, int data_len)
+{
+	hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+	int ret;
+	uint16_t unsafe_channel_count;
+	int unsafe_channel_index;
+	qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
+
+	ENTER_DEV(wdev->netdev);
+
+	if (!qdf_ctx) {
+		cds_err("qdf_ctx is NULL");
+		return -EINVAL;
+	}
+
+	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EINVAL;
+	}
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (0 != ret)
+		return ret;
+	pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
+			&(hdd_ctx->unsafe_channel_count),
+			sizeof(hdd_ctx->unsafe_channel_list));
+
+	unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
+			(uint16_t)NUM_CHANNELS);
+	for (unsafe_channel_index = 0;
+			unsafe_channel_index < unsafe_channel_count;
+			unsafe_channel_index++) {
+		hdd_info("Channel %d is not safe",
+			hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
+	}
+	hdd_unsafe_channel_restart_sap(hdd_ctx);
+	return 0;
+}
+
+/**
+ * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
+ * is on unsafe channel.
+ * @wiphy:    wiphy structure pointer
+ * @wdev:     Wireless device structure pointer
+ * @data:     Pointer to the data received
+ * @data_len: Length of @data
+ *
+ * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
+ * on any of unsafe channels.
+ * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
+ * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
+ *
+ * Return: 0 on success; errno on failure
+ */
+static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
+		struct wireless_dev *wdev,
+		const void *data, int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}
+
+#endif
 /**
  * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
  * SAP is on unsafe channel.
@@ -8084,6 +8171,16 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
 			WIPHY_VENDOR_CMD_NEED_RUNNING,
 		.doit = wlan_hdd_cfg80211_sta_roam_policy
 	},
+#ifdef FEATURE_WLAN_CH_AVOID
+	{
+		.info.vendor_id = QCA_NL80211_VENDOR_ID,
+		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			WIPHY_VENDOR_CMD_NEED_NETDEV |
+			WIPHY_VENDOR_CMD_NEED_RUNNING,
+		.doit = wlan_hdd_cfg80211_avoid_freq
+	},
+#endif
 	{
 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,

+ 73 - 64
core/hdd/src/wlan_hdd_main.c

@@ -5711,7 +5711,78 @@ void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
 
 	cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
 }
+/**
+ * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
+ * @hdd_ctx: hdd context pointer
+ *
+ * hdd_unsafe_channel_restart_sap check all unsafe channel list
+ * and if ACS is enabled, driver will ask userspace to restart the
+ * sap. User space on LTE coex indication restart driver.
+ *
+ * Return - none
+ */
+void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
+{
+	QDF_STATUS status;
+	hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
+	hdd_adapter_t *adapter_temp;
+	uint32_t i;
+	bool found = false;
+	uint8_t restart_chan;
+
+	status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
+	while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
+		adapter_temp = adapter_node->pAdapter;
+
+		if (!adapter_temp) {
+			hdd_err("adapter is NULL, moving to next one");
+			goto next_adapater;
+		}
+
+		if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
+		   (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
+			hdd_info("skip device mode:%d acs:%d",
+				adapter_temp->device_mode,
+				adapter_temp->sessionCtx.ap.sapConfig.
+				acs_cfg.acs_mode);
+			goto next_adapater;
+		}
+
+		found = false;
+		for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
+			if (cds_chan_to_freq(
+				adapter_temp->sessionCtx.ap.operatingChannel) ==
+				hdd_ctxt->unsafe_channel_list[i]) {
+				found = true;
+				hdd_info("operating ch:%d is unsafe",
+				  adapter_temp->sessionCtx.ap.operatingChannel);
+				break;
+			}
+		}
+
+		if (!found) {
+			hdd_info("ch:%d is safe. no need to change channel",
+				adapter_temp->sessionCtx.ap.operatingChannel);
+			goto next_adapater;
+		}
 
+		restart_chan =
+			hdd_get_safe_channel_from_pcl_and_acs_range(
+					adapter_temp);
+		if (!restart_chan) {
+			hdd_alert("fail to restart SAP");
+		} else {
+			hdd_info("sending coex indication");
+			wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
+					WLAN_SVC_LTE_COEX_IND, NULL, 0);
+			hdd_restart_sap(adapter_temp, restart_chan);
+		}
+
+next_adapater:
+		status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
+		adapter_node = next;
+	}
+}
 /**
  * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
  * @adapter:	HDD adapter pointer
@@ -5723,7 +5794,7 @@ void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
  *
  * Return: None
  */
-static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
+void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
 {
 	hdd_context_t *hdd_ctxt;
 	tSirChAvoidIndType *ch_avoid_indi;
@@ -5735,11 +5806,6 @@ static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
 	v_CONTEXT_t cds_context;
 	tHddAvoidFreqList hdd_avoid_freq_list;
 	uint32_t i;
-	QDF_STATUS status;
-	hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
-	hdd_adapter_t *adapter_temp;
-	uint8_t restart_chan;
-	bool found = false;
 
 	/* Basic sanity */
 	if (!hdd_context || !indi_param) {
@@ -5866,64 +5932,7 @@ static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
 		hdd_info("no unsafe channels - not restarting SAP");
 		return;
 	}
-
-	/* No channel change is done for fixed channel SAP.
-	 * Loop through all ACS SAP interfaces and change the channels for
-	 * the ones operating on unsafe channels.
-	 */
-	status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
-	while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
-		adapter_temp = adapter_node->pAdapter;
-
-		if (!adapter_temp) {
-			hdd_err("adapter is NULL, moving to next one");
-			goto next_adapater;
-		}
-
-		if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
-		   (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
-			hdd_info("skip device mode:%d acs:%d",
-				adapter_temp->device_mode,
-				adapter_temp->sessionCtx.ap.sapConfig.
-				acs_cfg.acs_mode);
-			goto next_adapater;
-		}
-
-		found = false;
-		for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
-			if (cds_chan_to_freq(
-				adapter_temp->sessionCtx.ap.operatingChannel) ==
-				hdd_ctxt->unsafe_channel_list[i]) {
-				found = true;
-				hdd_info("operating ch:%d is unsafe",
-				  adapter_temp->sessionCtx.ap.operatingChannel);
-				break;
-			}
-		}
-
-		if (!found) {
-			hdd_info("ch:%d is safe. no need to change channel",
-				adapter_temp->sessionCtx.ap.operatingChannel);
-			goto next_adapater;
-		}
-
-		restart_chan =
-			hdd_get_safe_channel_from_pcl_and_acs_range(
-					adapter_temp);
-		if (!restart_chan) {
-			hdd_alert("fail to restart SAP");
-		} else {
-			hdd_info("sending coex indication");
-			wlan_hdd_send_svc_nlink_msg
-				(hdd_ctxt->radio_index,
-				WLAN_SVC_LTE_COEX_IND, NULL, 0);
-			hdd_restart_sap(adapter_temp, restart_chan);
-		}
-
-next_adapater:
-		status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
-		adapter_node = next;
-	}
+	hdd_unsafe_channel_restart_sap(hdd_ctxt);
 	return;
 }