Sfoglia il codice sorgente

qcacld-3.0: Disable indoor channel on sap start

There are scenario where indoor channel operations
(like  active / passive scan/connect/roam etc)
are not desired / permitted specially in sap case.
Hence add support of disabling indoor channel
on sap start and revert it on sap stop.

Change-Id: Id6e01534532e3076a3e662e6a4f71e8be924165a
CRs-fixed: 2121103
Mukul Sharma 7 anni fa
parent
commit
ecf8e09fd5

+ 29 - 0
core/hdd/inc/wlan_hdd_cfg.h

@@ -10208,6 +10208,33 @@ enum dot11p_mode {
 #define CFG_INDOOR_CHANNEL_SUPPORT_MAX      (1)
 #define CFG_INDOOR_CHANNEL_SUPPORT_DEFAULT  (0)
 
+/*
+ * <ini>
+ * g_mark_sap_indoor_as_disable - Enable/Disable Indoor channel
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to mark the Indoor channel as
+ * disable when SAP start and revert it on SAP stop,
+ * so SAP will not turn on indoor channel and
+ * sta will not scan/associate and roam on indoor
+ * channels.
+ *
+ * Related: If g_mark_sap_indoor_as_disable set, turn the
+ * indoor channels to disable and update Wiphy & fw.
+ *
+ * Supported Feature: SAP/STA
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+#define CFG_MARK_INDOOR_AS_DISABLE_NAME     "g_mark_sap_indoor_as_disable"
+#define CFG_MARK_INDOOR_AS_DISABLE_MIN      (0)
+#define CFG_MARK_INDOOR_AS_DISABLE_MAX      (1)
+#define CFG_MARK_INDOOR_AS_DISABLE_DEFAULT  (0)
+
 /*
  * Force softap to 11n, when gSapForce11NFor11AC is set to 1 from ini
  * despite of hostapd.conf request for 11ac
@@ -15130,6 +15157,8 @@ struct hdd_config {
 	uint32_t tgt_gtx_usr_cfg;
 	enum cfg_sub_20_channel_width enable_sub_20_channel_width;
 	bool indoor_channel_support;
+	/* control marking indoor channel passive to disable */
+	bool force_ssc_disable_indoor_channel;
 	/* parameter to force sap into 11n */
 	bool sap_force_11n_for_11ac;
 	bool go_force_11n_for_11ac;

+ 30 - 1
core/hdd/inc/wlan_hdd_regulatory.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -63,4 +63,33 @@ int hdd_reg_set_country(struct hdd_context *hdd_ctx, char *country_code);
  */
 int hdd_reg_set_band(struct net_device *dev, u8 ui_band);
 
+/**
+ * hdd_update_indoor_channel() - enable/disable indoor channel
+ * @hdd_ctx: hdd context
+ * @disable: whether to enable / disable indoor channel
+ *
+ * enable/disable indoor channel in wiphy/cds
+ *
+ * Return: void
+ */
+void hdd_update_indoor_channel(struct  hdd_context *hdd_ctx,
+					bool disable);
+/**
+ * hdd_modify_indoor_channel_state_flags() - modify wiphy flags and cds state
+ * @wiphy_chan: wiphy channel number
+ * @cds_chan: cds channel structure
+ * @chan_enum: channel enum maintain in reg db
+ * @chan_num: channel index
+ * @disable: Disable/enable the flags
+ *
+ * Modify wiphy flags and cds state if channel is indoor.
+ *
+ * Return: void
+ */
+void hdd_modify_indoor_channel_state_flags(
+	struct hdd_context *hdd_ctx,
+	struct ieee80211_channel *wiphy_chan,
+	struct regulatory_channel *cds_chan,
+	enum channel_enum chan_enum, int chan_num, bool disable);
+
 #endif

+ 11 - 1
core/hdd/src/wlan_hdd_cfg.c

@@ -4377,6 +4377,14 @@ struct reg_table_entry g_registry_table[] = {
 		     CFG_INDOOR_CHANNEL_SUPPORT_MIN,
 		     CFG_INDOOR_CHANNEL_SUPPORT_MAX),
 
+	REG_VARIABLE(CFG_MARK_INDOOR_AS_DISABLE_NAME,
+		     WLAN_PARAM_Integer,
+		     struct hdd_config, force_ssc_disable_indoor_channel,
+		     VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		     CFG_MARK_INDOOR_AS_DISABLE_DEFAULT,
+		     CFG_MARK_INDOOR_AS_DISABLE_MIN,
+		     CFG_MARK_INDOOR_AS_DISABLE_MAX),
+
 	REG_VARIABLE(CFG_SAP_TX_LEAKAGE_THRESHOLD_NAME,
 		WLAN_PARAM_Integer,
 		struct hdd_config, sap_tx_leakage_threshold,
@@ -7060,7 +7068,9 @@ void hdd_cfg_print(struct hdd_context *hdd_ctx)
 	hdd_debug("Name = [%s] Value = [%u]",
 		   CFG_HT_MPDU_DENSITY_NAME,
 		   hdd_ctx->config->ht_mpdu_density);
-
+	hdd_debug("Name = [%s] value = [%d]",
+		   CFG_MARK_INDOOR_AS_DISABLE_NAME,
+		   hdd_ctx->config->force_ssc_disable_indoor_channel);
 
 #ifdef FEATURE_LFR_SUBNET_DETECTION
 	hdd_notice("Name = [%s] Value = [%d]",

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

@@ -90,6 +90,8 @@
 #include <wlan_p2p_ucfg_api.h>
 #include "sir_api.h"
 #include <wlan_green_ap_ucfg_api.h>
+#include "sme_api.h"
+#include "wlan_hdd_regulatory.h"
 
 #define    IS_UP(_dev) \
 	(((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
@@ -7658,7 +7660,6 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 
 	ENTER();
 
-
 	hdd_notify_teardown_tdls_links(adapter->hdd_vdev);
 
 	if (policy_mgr_is_hw_mode_change_in_progress(hdd_ctx->hdd_psoc)) {
@@ -7706,6 +7707,18 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 	clear_bit(ACS_PENDING, &adapter->event_flags);
 	clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
 
+	/* Mark the indoor channel (passive) to disable */
+	if (iniConfig->force_ssc_disable_indoor_channel) {
+		hdd_update_indoor_channel(hdd_ctx, true);
+		if (QDF_IS_STATUS_ERROR(
+		    sme_update_channel_list(hdd_ctx->hHal))) {
+			hdd_update_indoor_channel(hdd_ctx, false);
+			hdd_err("Can't start BSS: update channel list failed");
+			qdf_mem_free(sme_config);
+			return -EINVAL;
+		}
+	}
+
 	pConfig = &adapter->session.ap.sap_config;
 
 	pBeacon = adapter->session.ap.beacon;
@@ -8287,6 +8300,11 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 	goto free;
 
 error:
+	/* Revert the indoor to passive marking if START BSS fails */
+	if (iniConfig->force_ssc_disable_indoor_channel) {
+		hdd_update_indoor_channel(hdd_ctx, false);
+		sme_update_channel_list(hdd_ctx->hHal);
+	}
 	clear_bit(SOFTAP_INIT_DONE, &adapter->event_flags);
 	wlan_hdd_undo_acs(adapter);
 

+ 109 - 1
core/hdd/src/wlan_hdd_regulatory.c

@@ -221,6 +221,8 @@ static void reg_program_config_vars(struct hdd_context *hdd_ctx,
 	config_vars->dfs_enabled = hdd_ctx->config->enableDFSChnlScan;
 	config_vars->indoor_chan_enabled =
 		hdd_ctx->config->indoor_channel_support;
+	config_vars->force_ssc_disable_indoor_channel =
+		hdd_ctx->config->force_ssc_disable_indoor_channel;
 	config_vars->band_capability = hdd_ctx->config->nBandCapability;
 	config_vars->restart_beaconing = hdd_ctx->config->
 		restart_beaconing_on_chan_avoid_event;
@@ -436,6 +438,11 @@ static void hdd_process_regulatory_data(struct hdd_context *hdd_ctx,
 			if (!reset)
 				hdd_modify_wiphy(wiphy, wiphy_chan);
 
+			if (hdd_ctx->config->force_ssc_disable_indoor_channel &&
+			     (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY))
+				cds_chan->chan_flags |=
+					REGULATORY_CHAN_INDOOR_ONLY;
+
 			if (wiphy_chan->flags & IEEE80211_CHAN_DISABLED) {
 				cds_chan->state = CHANNEL_STATE_DISABLE;
 				cds_chan->chan_flags |=
@@ -454,7 +461,7 @@ static void hdd_process_regulatory_data(struct hdd_context *hdd_ctx,
 			} else if (wiphy_chan->flags &
 				     IEEE80211_CHAN_INDOOR_ONLY) {
 				cds_chan->chan_flags |=
-					REGULATORY_CHAN_INDOOR_ONLY;
+						REGULATORY_CHAN_INDOOR_ONLY;
 				if (hdd_ctx->config->indoor_channel_support
 				    == false) {
 					cds_chan->state = CHANNEL_STATE_DFS;
@@ -553,6 +560,107 @@ static int hdd_regulatory_init_no_offload(struct hdd_context *hdd_ctx,
 }
 #endif
 
+/**
+ * hdd_modify_indoor_channel_state_flags() - modify wiphy flags and cds state
+ * @wiphy_chan: wiphy channel number
+ * @cds_chan: cds channel structure
+ * @disable: Disable/enable the flags
+ *
+ * Modify wiphy flags and cds state if channel is indoor.
+ *
+ * Return: void
+ */
+void hdd_modify_indoor_channel_state_flags(
+	struct hdd_context *hdd_ctx,
+	struct ieee80211_channel *wiphy_chan,
+	struct regulatory_channel *cds_chan,
+	enum channel_enum chan_enum, int chan_num, bool disable)
+{
+	bool indoor_support = hdd_ctx->config->indoor_channel_support;
+
+	/* Mark indoor channel to disable in wiphy and cds */
+	if (disable) {
+		if (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY) {
+			wiphy_chan->flags |=
+				IEEE80211_CHAN_DISABLED;
+			hdd_info("Mark indoor channel %d as disable",
+				cds_chan->center_freq);
+			cds_chan->state =
+				CHANNEL_STATE_DISABLE;
+		}
+	} else {
+		if (wiphy_chan->flags & IEEE80211_CHAN_INDOOR_ONLY) {
+			wiphy_chan->flags &=
+					~IEEE80211_CHAN_DISABLED;
+			 /*
+			  * Indoor channels may be marked as dfs / enable
+			  * during regulatory processing
+			  */
+			if ((wiphy_chan->flags &
+				(IEEE80211_CHAN_RADAR |
+				IEEE80211_CHAN_PASSIVE_SCAN)) ||
+			     ((indoor_support == false) &&
+				(wiphy_chan->flags &
+				IEEE80211_CHAN_INDOOR_ONLY)))
+				cds_chan->state =
+					CHANNEL_STATE_DFS;
+			else
+				cds_chan->state =
+					CHANNEL_STATE_ENABLE;
+			hdd_debug("Mark indoor channel %d as cds_chan state %d",
+					cds_chan->chan_num, cds_chan->state);
+		}
+	}
+
+}
+
+void hdd_update_indoor_channel(struct hdd_context *hdd_ctx,
+					bool disable)
+{
+	int band_num;
+	int chan_num;
+	enum channel_enum chan_enum = CHAN_ENUM_1;
+	struct ieee80211_channel *wiphy_chan, *wiphy_chan_144 = NULL;
+	struct regulatory_channel *cds_chan;
+	uint8_t band_capability;
+	struct wiphy *wiphy = hdd_ctx->wiphy;
+
+	ENTER();
+	hdd_debug("mark indoor channel disable: %d", disable);
+
+	band_capability = hdd_ctx->curr_band;
+	for (band_num = 0; band_num < HDD_NUM_NL80211_BANDS; band_num++) {
+
+		if (wiphy->bands[band_num] == NULL)
+			continue;
+
+		for (chan_num = 0;
+		     chan_num < wiphy->bands[band_num]->n_channels &&
+		     chan_enum < NUM_CHANNELS;
+		     chan_num++) {
+
+			wiphy_chan =
+				&(wiphy->bands[band_num]->channels[chan_num]);
+			cds_chan = &(reg_channels[chan_enum]);
+			if (chan_enum == CHAN_ENUM_144)
+				wiphy_chan_144 = wiphy_chan;
+
+			chan_enum++;
+			hdd_modify_indoor_channel_state_flags(hdd_ctx,
+				wiphy_chan, cds_chan,
+				chan_enum, chan_num, disable);
+		}
+	}
+
+	/* Notify the regulatory domain to update the channel list */
+	if (QDF_IS_STATUS_ERROR(ucfg_reg_notify_sap_event(hdd_ctx->hdd_pdev,
+		disable))) {
+		hdd_err("Failed to notify sap event");
+	}
+	EXIT();
+
+}
+
 /**
  * hdd_program_country_code() - process channel information from country code
  * @hdd_ctx: hddc context

+ 8 - 0
core/hdd/src/wlan_hdd_softap_tx_rx.c

@@ -49,6 +49,7 @@
 #include <wlan_hdd_object_manager.h>
 #include "wlan_p2p_ucfg_api.h"
 #include <wlan_hdd_ipa.h>
+#include <wlan_hdd_regulatory.h>
 
 /* Preprocessor definitions and constants */
 #undef QCA_HDD_SAP_DUMP_SK_BUFF
@@ -1070,6 +1071,13 @@ QDF_STATUS hdd_softap_stop_bss(struct hdd_adapter *adapter)
 			}
 		}
 	}
+
+	/*  Mark the indoor channel (passive) to enable  */
+	if (hdd_ctx->config->force_ssc_disable_indoor_channel) {
+		hdd_update_indoor_channel(hdd_ctx, false);
+		sme_update_channel_list(hdd_ctx->hHal);
+	}
+
 	return qdf_status;
 }
 

+ 4 - 0
core/sme/inc/sme_api.h

@@ -522,6 +522,10 @@ QDF_STATUS sme_change_country_code(tHalHandle hHal,
 		bool sendRegHint);
 QDF_STATUS sme_generic_change_country_code(tHalHandle hHal,
 					   uint8_t *pCountry);
+
+
+QDF_STATUS sme_update_channel_list(tpAniSirGlobal mac_ctx);
+
 QDF_STATUS sme_tx_fail_monitor_start_stop_ind(tHalHandle hHal,
 		uint8_t tx_fail_count,
 		void *txFailIndCallback);

+ 33 - 0
core/sme/src/common/sme_api.c

@@ -6023,6 +6023,39 @@ sme_handle_generic_change_country_code(tpAniSirGlobal mac_ctx,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * sme_update_channel_list() - Update configured channel list to fwr
+ * This is a synchronous API.
+ *
+ * @mac_ctx - The handle returned by mac_open.
+ *
+ * Return QDF_STATUS  SUCCESS.
+ * FAILURE or RESOURCES  The API finished and failed.
+ */
+QDF_STATUS
+sme_update_channel_list(tpAniSirGlobal mac_ctx)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = sme_acquire_global_lock(&mac_ctx->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		/* Update umac channel (enable/disable) from cds channels */
+		status = csr_get_channel_and_power_list(mac_ctx);
+		if (status != QDF_STATUS_SUCCESS) {
+			sme_err("fail to get Channels");
+			sme_release_global_lock(&mac_ctx->sme);
+			return status;
+		}
+
+		csr_apply_channel_power_info_wrapper(mac_ctx);
+		csr_scan_filter_results(mac_ctx);
+		sme_disconnect_connected_sessions(mac_ctx);
+		sme_release_global_lock(&mac_ctx->sme);
+	}
+
+	return status;
+}
+
 static bool
 sme_search_in_base_ch_lst(tpAniSirGlobal mac_ctx, uint8_t curr_ch)
 {