Procházet zdrojové kódy

qcacld-3.0: Fix safe channel switch failure

For the AP+AP SCC LTE-Coex case, when channel avoidance event
is reported, the channel switch request for SAP will be blocked
by policy manager if the target channel is different with the
operating channel of the existing SAP due to the SCC policy.

Need to update the logic to give higher priority to the channel
avoidance request.

Another change is to move the dfs_radar_found ref counter from
hdd_ctx to hdd_adapter so that the channel switch request of
the 2nd SAP will not be blocked when the 1st one is still in
progress since it might take some time to get VDEV restart
response from FW.

Change-Id: I8594b35b70276f7ed3884697caf69a99ee91b952
CRs-Fixed: 2171958
Min Liu před 7 roky
rodič
revize
2fef579fc1

+ 5 - 2
core/hdd/inc/wlan_hdd_main.h

@@ -1120,6 +1120,8 @@ struct hdd_adapter {
 		struct hdd_ap_ctx ap;
 	} session;
 
+	qdf_atomic_t dfs_radar_found;
+
 #ifdef WLAN_FEATURE_TSF
 	/* tsf value received from firmware */
 	uint64_t cur_target_time;
@@ -1545,7 +1547,6 @@ struct hdd_context {
 	/* defining the firmware version */
 	uint32_t target_fw_version;
 	uint32_t target_fw_vers_ext;
-	qdf_atomic_t dfs_radar_found;
 
 	/* defining the chip/rom version */
 	uint32_t target_hw_version;
@@ -2164,13 +2165,15 @@ int hdd_update_acs_timer_reason(struct hdd_adapter *adapter, uint8_t reason);
  * hdd_switch_sap_channel() - Move SAP to the given channel
  * @adapter: AP adapter
  * @channel: Channel
+ * @forced: Force to switch channel, ignore SCC/MCC check
  *
  * Moves the SAP interface by invoking the function which
  * executes the callback to perform channel switch using (E)CSA.
  *
  * Return: None
  */
-void hdd_switch_sap_channel(struct hdd_adapter *adapter, uint8_t channel);
+void hdd_switch_sap_channel(struct hdd_adapter *adapter, uint8_t channel,
+			    bool forced);
 
 void hdd_update_macaddr(struct hdd_config *config,
 			struct qdf_mac_addr hw_macaddr);

+ 3 - 2
core/hdd/src/wlan_hdd_cfg80211.c

@@ -11185,7 +11185,8 @@ static int hdd_update_acs_channel(struct hdd_adapter *adapter, uint8_t reason,
 		sap_config->acs_cfg.ch_width = channel_list->chan_width;
 		hdd_ap_ctx->sap_config.ch_width_orig =
 				channel_list->chan_width;
-		hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
+		hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch,
+				       true);
 		break;
 
 	default:
@@ -20931,7 +20932,7 @@ static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
 
 	ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
 
-	ret = hdd_softap_set_channel_change(dev, channel, ch_width);
+	ret = hdd_softap_set_channel_change(dev, channel, ch_width, false);
 	return ret;
 }
 

+ 22 - 16
core/hdd/src/wlan_hdd_hostapd.c

@@ -214,8 +214,6 @@ int hdd_sap_context_init(struct hdd_context *hdd_ctx)
 	qdf_wake_lock_create(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock");
 	qdf_spinlock_create(&hdd_ctx->sap_update_info_lock);
 
-	qdf_atomic_init(&hdd_ctx->dfs_radar_found);
-
 	return 0;
 }
 
@@ -1176,7 +1174,7 @@ static void wlan_hdd_sap_pre_cac_success(void *data)
 	wlan_hdd_set_pre_cac_complete_status(ap_adapter, true);
 	i = hdd_softap_set_channel_change(ap_adapter->dev,
 			ap_adapter->pre_cac_chan,
-			CH_WIDTH_MAX);
+			CH_WIDTH_MAX, false);
 	if (0 != i) {
 		hdd_err("failed to change channel");
 		wlan_hdd_set_pre_cac_complete_status(ap_adapter, false);
@@ -1691,7 +1689,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 		hostapd_state->qdf_status =
 			pSapEvent->sapevt.sapStartBssCompleteEvent.status;
 
-		qdf_atomic_set(&hdd_ctx->dfs_radar_found, 0);
+		qdf_atomic_set(&adapter->dfs_radar_found, 0);
 		wlansap_get_dfs_ignore_cac(hdd_ctx->hHal, &ignoreCAC);
 
 		/* DFS requirement: DO NOT transmit during CAC. */
@@ -1944,7 +1942,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 			hdd_debug("Sent CAC start to user space");
 		}
 
-		qdf_atomic_set(&hdd_ctx->dfs_radar_found, 0);
+		qdf_atomic_set(&adapter->dfs_radar_found, 0);
 		break;
 	case eSAP_DFS_CAC_INTERRUPTED:
 		/*
@@ -2586,7 +2584,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 				pSapEvent->sapevt.sap_chan_cng_ind.new_chan);
 		if (hdd_softap_set_channel_change(dev,
 			 pSapEvent->sapevt.sap_chan_cng_ind.new_chan,
-			 CH_WIDTH_MAX))
+			 CH_WIDTH_MAX, false))
 			return QDF_STATUS_E_FAILURE;
 		else
 			return QDF_STATUS_SUCCESS;
@@ -2801,11 +2799,12 @@ int hdd_softap_unpack_ie(tHalHandle halHandle,
  * @target_channel: target channel number.
  * @target_bw: Target bandwidth to move.
  * If no bandwidth is specified, the value is CH_WIDTH_MAX
+ * @forced: Force to switch channel, ignore SCC/MCC check
  *
  * Return: 0 for success, non zero for failure
  */
 int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
-				 enum phy_ch_width target_bw)
+				 enum phy_ch_width target_bw, bool forced)
 {
 	QDF_STATUS status;
 	int ret = 0;
@@ -2850,7 +2849,7 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
 	 * once the channel change is completed and SAP will
 	 * post eSAP_START_BSS_EVENT success event to HDD.
 	 */
-	if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
+	if (qdf_atomic_inc_return(&adapter->dfs_radar_found) > 1) {
 		hdd_err("Channel switch in progress!!");
 		return -EBUSY;
 	}
@@ -2861,7 +2860,7 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
 	status = wlansap_set_channel_change_with_csa(
 		WLAN_HDD_GET_SAP_CTX_PTR(adapter),
 		(uint32_t)target_channel,
-		target_bw, true);
+		target_bw, forced);
 
 	if (QDF_STATUS_SUCCESS != status) {
 		hdd_err("SAP set channel failed for channel: %d, bw: %d",
@@ -2871,7 +2870,7 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
 		 * radar found flag and also restart the netif
 		 * queues.
 		 */
-		qdf_atomic_set(&hdd_ctx->dfs_radar_found, 0);
+		qdf_atomic_set(&adapter->dfs_radar_found, 0);
 
 		ret = -EINVAL;
 	}
@@ -2885,6 +2884,7 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
  * @ap_adapter: HDD adapter
  * @target_channel: Channel to which switch must happen
  * @target_bw: Bandwidth of the target channel
+ * @forced: Force to switch channel, ignore SCC/MCC check
  *
  * Invokes the necessary API to perform channel switch for the SAP or GO
  *
@@ -2892,7 +2892,8 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
  */
 void hdd_sap_restart_with_channel_switch(struct hdd_adapter *ap_adapter,
 					uint32_t target_channel,
-					uint32_t target_bw)
+					uint32_t target_bw,
+					bool forced)
 {
 	struct net_device *dev = ap_adapter->dev;
 	int ret;
@@ -2904,7 +2905,8 @@ void hdd_sap_restart_with_channel_switch(struct hdd_adapter *ap_adapter,
 		return;
 	}
 
-	ret = hdd_softap_set_channel_change(dev, target_channel, target_bw);
+	ret = hdd_softap_set_channel_change(dev, target_channel,
+					    target_bw, forced);
 	if (ret) {
 		hdd_err("channel switch failed");
 		return;
@@ -2913,7 +2915,8 @@ void hdd_sap_restart_with_channel_switch(struct hdd_adapter *ap_adapter,
 
 void hdd_sap_restart_chan_switch_cb(struct wlan_objmgr_psoc *psoc,
 				    uint8_t vdev_id, uint32_t channel,
-				    uint32_t channel_bw)
+				    uint32_t channel_bw,
+				    bool forced)
 {
 	struct hdd_adapter *ap_adapter =
 		wlan_hdd_get_adapter_from_vdev(psoc, vdev_id);
@@ -2923,7 +2926,7 @@ void hdd_sap_restart_chan_switch_cb(struct wlan_objmgr_psoc *psoc,
 		return;
 	}
 	hdd_sap_restart_with_channel_switch(ap_adapter, channel,
-					    channel_bw);
+					    channel_bw, forced);
 }
 
 QDF_STATUS wlan_hdd_get_channel_for_sap_restart(
@@ -3020,7 +3023,7 @@ QDF_STATUS wlan_hdd_get_channel_for_sap_restart(
 	hdd_info("SAP channel change with CSA/ECSA");
 	hdd_sap_restart_chan_switch_cb(psoc, vdev_id,
 		hdd_ap_ctx->sap_config.channel,
-		hdd_ap_ctx->sap_config.ch_params.ch_width);
+		hdd_ap_ctx->sap_config.ch_params.ch_width, false);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -3382,7 +3385,8 @@ static __iw_softap_setparam(struct net_device *dev,
 			hdd_debug("SET Channel Change to new channel= %d",
 			       set_value);
 			ret = hdd_softap_set_channel_change(dev, set_value,
-								CH_WIDTH_MAX);
+								CH_WIDTH_MAX,
+								false);
 		} else {
 			hdd_err("Channel Change Failed, Device in test mode");
 			ret = -EINVAL;
@@ -6488,6 +6492,8 @@ struct hdd_adapter *hdd_wlan_create_ap_dev(struct hdd_context *hdd_ctx,
 	spin_lock_init(&adapter->pause_map_lock);
 	adapter->start_time = adapter->last_time = qdf_system_ticks();
 
+	qdf_atomic_init(&adapter->dfs_radar_found);
+
 	return adapter;
 }
 

+ 8 - 4
core/hdd/src/wlan_hdd_hostapd.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -59,18 +59,21 @@ hdd_translate_rsn_to_csr_auth_type(uint8_t auth_suite[4]);
 
 int hdd_softap_set_channel_change(struct net_device *dev,
 					int target_channel,
-					enum phy_ch_width target_bw);
+					enum phy_ch_width target_bw,
+					bool forced);
 
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 void hdd_sap_restart_with_channel_switch(struct hdd_adapter *adapter,
 				uint32_t target_channel,
-				uint32_t target_bw);
+				uint32_t target_bw,
+				bool forced);
 /**
  * hdd_sap_restart_chan_switch_cb() - Function to restart SAP with
  * a different channel
  * @psoc: PSOC object information
  * @vdev_id: vdev id
  * @channel: channel to switch
+ * @forced: Force to switch channel, ignore SCC/MCC check
  *
  * This function restarts SAP with a different channel
  *
@@ -79,7 +82,8 @@ void hdd_sap_restart_with_channel_switch(struct hdd_adapter *adapter,
  */
 void hdd_sap_restart_chan_switch_cb(struct wlan_objmgr_psoc *psoc,
 				    uint8_t vdev_id, uint32_t channel,
-				    uint32_t channel_bw);
+				    uint32_t channel_bw,
+				    bool forced);
 /**
  * wlan_hdd_get_channel_for_sap_restart() - Function to get
  * suitable channel and restart SAP

+ 1 - 1
core/hdd/src/wlan_hdd_ioctl.c

@@ -6722,7 +6722,7 @@ static int drv_cmd_set_channel_switch(struct hdd_adapter *adapter,
 
 	hdd_debug("CH:%d BW:%d", chan_number, chan_bw);
 
-	status = hdd_softap_set_channel_change(dev, chan_number, width);
+	status = hdd_softap_set_channel_change(dev, chan_number, width, false);
 	if (status) {
 		hdd_err("Set channel change fail");
 		return status;

+ 7 - 4
core/hdd/src/wlan_hdd_main.c

@@ -7571,13 +7571,15 @@ static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
  * hdd_switch_sap_channel() - Move SAP to the given channel
  * @adapter: AP adapter
  * @channel: Channel
+ * @forced: Force to switch channel, ignore SCC/MCC check
  *
  * Moves the SAP interface by invoking the function which
  * executes the callback to perform channel switch using (E)CSA.
  *
  * Return: None
  */
-void hdd_switch_sap_channel(struct hdd_adapter *adapter, uint8_t channel)
+void hdd_switch_sap_channel(struct hdd_adapter *adapter, uint8_t channel,
+			    bool forced)
 {
 	struct hdd_ap_ctx *hdd_ap_ctx;
 	tHalHandle *hal_handle;
@@ -7612,7 +7614,7 @@ void hdd_switch_sap_channel(struct hdd_adapter *adapter, uint8_t channel)
 
 	policy_mgr_change_sap_channel_with_csa(hdd_ctx->hdd_psoc,
 		adapter->session_id, channel,
-		hdd_ap_ctx->sap_config.ch_width_orig);
+		hdd_ap_ctx->sap_config.ch_width_orig, forced);
 }
 
 int hdd_update_acs_timer_reason(struct hdd_adapter *adapter, uint8_t reason)
@@ -7717,7 +7719,8 @@ void hdd_unsafe_channel_restart_sap(struct hdd_context *hdd_ctxt)
 			hdd_debug("driver to start sap: %d",
 				hdd_ctxt->config->sap_internal_restart);
 			if (hdd_ctxt->config->sap_internal_restart)
-				hdd_switch_sap_channel(adapter, restart_chan);
+				hdd_switch_sap_channel(adapter, restart_chan,
+						       true);
 			else
 				return;
 		}
@@ -7782,7 +7785,7 @@ static void hdd_lte_coex_restart_sap(struct hdd_adapter *adapter,
 
 	wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
 				    WLAN_SVC_LTE_COEX_IND, NULL, 0);
-	hdd_switch_sap_channel(adapter, restart_chan);
+	hdd_switch_sap_channel(adapter, restart_chan, true);
 }
 
 int hdd_clone_local_unsafe_chan(struct hdd_context *hdd_ctx,

+ 13 - 9
core/sap/src/sap_module.c

@@ -1253,8 +1253,9 @@ wlansap_update_csa_channel_params(struct sap_context *sap_context,
  * @sapContext: Pointer to SAP context
  * @targetChannel: Target channel
  * @target_bw: Target bandwidth
- * @strict: if true switch to the requested channel always, fail
- *        otherwise
+ * @strict: if true switch to the requested channel always,
+ *        SCC/MCC check will be ignored,
+ *        fail otherwise
  *
  * This api function does a channel change to the target channel specified.
  * CSA IE is included in the beacons before doing a channel change.
@@ -1315,13 +1316,16 @@ QDF_STATUS wlansap_set_channel_change_with_csa(struct sap_context *sapContext,
 		 * validate target channel switch w.r.t various concurrency
 		 * rules set.
 		 */
-		valid = wlan_sap_validate_channel_switch(hHal, targetChannel,
-				sapContext);
-		if (!valid) {
-			QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
-					FL("Channel switch to %u is not allowed due to concurrent channel interference"),
-					targetChannel);
-			return QDF_STATUS_E_FAULT;
+		if (!strict) {
+			valid = wlan_sap_validate_channel_switch(hHal,
+				targetChannel, sapContext);
+			if (!valid) {
+				QDF_TRACE(QDF_MODULE_ID_SAP,
+					  QDF_TRACE_LEVEL_ERROR,
+					  FL("Channel switch to %u is not allowed due to concurrent channel interference"),
+					  targetChannel);
+				return QDF_STATUS_E_FAULT;
+			}
 		}
 		/*
 		 * Post a CSA IE request to SAP state machine with