Explorar el Código

qcacld-3.0: Avoid VDEV restart for SAP when roaming in progress

Currently, driver allows VDEV-RESTART on SAP interface in order to
channel switch or hidden ssid connection when roaming is in progress
on STA interface. This leads to two simultaneous vdev starts or
vdev-restart in FW which causes the FW to assert.

Add changes to reject the channel switch for SAP or in hidden ssid
connection if roaming is in progress on any STA interface.

Change-Id: I1cea389021049779b5aa00145e2470cd67158edd
CRs-Fixed: 2390235
Abhinav Kumar hace 6 años
padre
commit
338e57d779

+ 11 - 1
core/hdd/inc/wlan_hdd_main.h

@@ -1234,7 +1234,7 @@ struct hdd_adapter {
 		struct hdd_ap_ctx ap;
 	} session;
 
-	qdf_atomic_t dfs_radar_found;
+	qdf_atomic_t ch_switch_in_progress;
 
 #ifdef WLAN_FEATURE_TSF
 	/* tsf value received from firmware */
@@ -3662,4 +3662,14 @@ void wlan_hdd_send_tcp_param_update_event(struct hdd_context *hdd_ctx,
 QDF_STATUS hdd_md_host_evt_cb(void *ctx, struct sir_md_evt *event);
 #endif /* WLAN_FEATURE_MOTION_DETECTION */
 
+/**
+ * hdd_hidden_ssid_enable_roaming() - enable roaming after hidden ssid rsp
+ * @hdd_handle: Hdd handler
+ * @vdev_id: Vdev Id
+ *
+ * This is a wrapper function to enable roaming after getting hidden
+ * ssid rsp
+ */
+void hdd_hidden_ssid_enable_roaming(hdd_handle_t hdd_handle, uint8_t vdev_id);
+
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 43 - 10
core/hdd/src/wlan_hdd_hostapd.c

@@ -1729,7 +1729,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 		hostapd_state->qdf_status =
 			pSapEvent->sapevt.sapStartBssCompleteEvent.status;
 
-		qdf_atomic_set(&adapter->dfs_radar_found, 0);
+		qdf_atomic_set(&adapter->ch_switch_in_progress, 0);
 
 		status = policy_mgr_set_chan_switch_complete_evt(
 						hdd_ctx->psoc);
@@ -1939,7 +1939,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 			hdd_debug("Sent CAC start to user space");
 		}
 
-		qdf_atomic_set(&adapter->dfs_radar_found, 0);
+		qdf_atomic_set(&adapter->ch_switch_in_progress, 0);
 		break;
 	case eSAP_DFS_CAC_INTERRUPTED:
 		/*
@@ -2529,7 +2529,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 		return QDF_STATUS_SUCCESS;
 	case eSAP_ECSA_CHANGE_CHAN_IND:
 		hdd_debug("Channel change indication from peer for channel %d",
-				pSapEvent->sapevt.sap_chan_cng_ind.new_chan);
+			  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, false))
@@ -2551,6 +2551,18 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 		schedule_work(&adapter->sap_stop_bss_work);
 		return QDF_STATUS_SUCCESS;
 
+	case eSAP_CHANNEL_CHANGE_RESP:
+		hdd_debug("Channel change rsp status = %d",
+			  pSapEvent->sapevt.ch_change_rsp_status);
+		/*
+		 * Set the ch_switch_in_progress flag to zero and also enable
+		 * roaming once channel change process (success/failure)
+		 * is completed
+		 */
+		qdf_atomic_set(&adapter->ch_switch_in_progress, 0);
+		wlan_hdd_enable_roaming(adapter);
+		return QDF_STATUS_SUCCESS;
+
 	default:
 		hdd_debug("SAP message is not handled");
 		goto stopbss;
@@ -2832,7 +2844,7 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
 	}
 
 	/*
-	 * Set the dfs_radar_found flag to mimic channel change
+	 * Set the ch_switch_in_progress flag to mimic channel change
 	 * when a radar is found. This will enable synchronizing
 	 * SAP and HDD states similar to that of radar indication.
 	 * Suspend the netif queues to stop queuing Tx frames
@@ -2840,7 +2852,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(&adapter->dfs_radar_found) > 1) {
+	if (qdf_atomic_inc_return(&adapter->ch_switch_in_progress) > 1) {
 		hdd_err("Channel switch in progress!!");
 		return -EBUSY;
 	}
@@ -2864,14 +2876,14 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
 				target_channel,
 				adapter->session_id)) {
 		hdd_err("Channel switch failed due to concurrency check failure");
-		qdf_atomic_set(&adapter->dfs_radar_found, 0);
+		qdf_atomic_set(&adapter->ch_switch_in_progress, 0);
 		return -EINVAL;
 	}
 
 	status = policy_mgr_reset_chan_switch_complete_evt(hdd_ctx->psoc);
 	if (!QDF_IS_STATUS_SUCCESS(status)) {
 		hdd_err("clear event failed");
-		qdf_atomic_set(&adapter->dfs_radar_found, 0);
+		qdf_atomic_set(&adapter->ch_switch_in_progress, 0);
 		return -EINVAL;
 	}
 
@@ -2880,9 +2892,24 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel,
 						      &scc_on_lte_coex);
 	if (!QDF_IS_STATUS_SUCCESS(status)) {
 		hdd_err("can't get STA-SAP SCC on lte coex channel setting");
-		qdf_atomic_set(&adapter->dfs_radar_found, 0);
+		qdf_atomic_set(&adapter->ch_switch_in_progress, 0);
 		return -EINVAL;
 	}
+
+	/*
+	 * Reject channel change req  if reassoc in progress on any adapter.
+	 * sme_is_any_session_in_middle_of_roaming is for LFR2 and
+	 * hdd_is_roaming_in_progress is for LFR3
+	 */
+	if (sme_is_any_session_in_middle_of_roaming(hdd_ctx->mac_handle) ||
+	    hdd_is_roaming_in_progress(hdd_ctx)) {
+		hdd_info("Channel switch not allowed as reassoc in progress");
+		qdf_atomic_set(&adapter->ch_switch_in_progress, 0);
+		return -EINVAL;
+	}
+	/* Disable Roaming on all adapters before doing channel change */
+	wlan_hdd_disable_roaming(adapter);
+
 	/*
 	 * Post the Channel Change request to SAP.
 	 */
@@ -2900,7 +2927,13 @@ 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(&adapter->dfs_radar_found, 0);
+		qdf_atomic_set(&adapter->ch_switch_in_progress, 0);
+
+		/*
+		 * If Posting of the Channel Change request fails
+		 * enable roaming on all adapters
+		 */
+		wlan_hdd_enable_roaming(adapter);
 
 		ret = -EINVAL;
 	}
@@ -3351,7 +3384,7 @@ 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);
+	qdf_atomic_init(&adapter->ch_switch_in_progress);
 
 	return adapter;
 }

+ 18 - 0
core/hdd/src/wlan_hdd_hostapd_wext.c

@@ -549,11 +549,29 @@ static __iw_softap_setparam(struct net_device *dev,
 	{
 		QDF_STATUS status;
 
+		/*
+		 * Reject hidden ssid param update  if reassoc in progress on
+		 * any adapter. sme_is_any_session_in_middle_of_roaming is for
+		 * LFR2 and hdd_is_roaming_in_progress is for LFR3
+		 */
+		if (hdd_is_roaming_in_progress(hdd_ctx) ||
+		    sme_is_any_session_in_middle_of_roaming(mac_handle)) {
+			hdd_info("Reassociation in progress");
+			return -EINVAL;
+		}
+
+		/*
+		 * Disable Roaming on all adapters before start of
+		 * start of Hidden ssid connection
+		 */
+		wlan_hdd_disable_roaming(adapter);
+
 		status = sme_update_session_param(mac_handle,
 				adapter->session_id,
 				SIR_PARAM_SSID_HIDDEN, set_value);
 		if (QDF_STATUS_SUCCESS != status) {
 			hdd_err("QCSAP_PARAM_HIDE_SSID failed");
+			wlan_hdd_enable_roaming(adapter);
 			return -EIO;
 		}
 		break;

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

@@ -12198,6 +12198,8 @@ int hdd_register_cb(struct hdd_context *hdd_ctx)
 
 	sme_set_link_layer_ext_cb(mac_handle,
 			wlan_hdd_cfg80211_link_layer_stats_ext_callback);
+	sme_update_hidden_ssid_status_cb(mac_handle,
+					 hdd_hidden_ssid_enable_roaming);
 
 	status = sme_set_lost_link_info_cb(mac_handle,
 					   hdd_lost_link_info_cb);
@@ -15175,6 +15177,21 @@ void hdd_set_rx_mode_rps(bool enable)
 	}
 }
 
+void hdd_hidden_ssid_enable_roaming(hdd_handle_t hdd_handle, uint8_t vdev_id)
+{
+	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
+	struct hdd_adapter *adapter;
+
+	adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+
+	if (!adapter) {
+		hdd_err("Adapter is null");
+		return;
+	}
+	/* enable roaming on all adapters once hdd get hidden ssid rsp */
+	wlan_hdd_enable_roaming(adapter);
+}
+
 /* Register the module init/exit functions */
 module_init(hdd_module_init);
 module_exit(hdd_module_exit);

+ 3 - 1
core/mac/inc/wni_api.h

@@ -234,7 +234,9 @@ enum eWniMsgTypes {
 	eWNI_SME_CSA_RESTART_REQ = SIR_SME_MSG_TYPES_BEGIN + 148,
 	eWNI_SME_CSA_RESTART_RSP = SIR_SME_MSG_TYPES_BEGIN + 149,
 	WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU = SIR_SME_MSG_TYPES_BEGIN + 150,
-	eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 151
+	/* To indicate Hidden ssid start complition to upper layer */
+	eWNI_SME_HIDDEN_SSID_RESTART_RSP = SIR_SME_MSG_TYPES_BEGIN + 151,
+	eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 152
 };
 
 typedef struct sAniCfgTxRateCtrs {

+ 11 - 0
core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c

@@ -2741,6 +2741,8 @@ void lim_process_mlm_update_hidden_ssid_rsp(struct mac_context *mac_ctx,
 {
 	struct pe_session *session_entry;
 	tpHalHiddenSsidVdevRestart hidden_ssid_vdev_restart;
+	struct scheduler_msg message = {0};
+	QDF_STATUS status;
 
 	hidden_ssid_vdev_restart = (tpHalHiddenSsidVdevRestart)(msg->bodyptr);
 
@@ -2761,6 +2763,15 @@ void lim_process_mlm_update_hidden_ssid_rsp(struct mac_context *mac_ctx,
 	sch_set_fixed_beacon_fields(mac_ctx, session_entry);
 	lim_send_beacon(mac_ctx, session_entry);
 
+	message.type = eWNI_SME_HIDDEN_SSID_RESTART_RSP;
+	message.bodyval = hidden_ssid_vdev_restart->sessionId;
+	status = scheduler_post_message(QDF_MODULE_ID_PE,
+					QDF_MODULE_ID_SME,
+					QDF_MODULE_ID_SME, &message);
+
+	if (status != QDF_STATUS_SUCCESS)
+		pe_err("Failed to post message %u", status);
+
 free_req:
 	if (NULL != hidden_ssid_vdev_restart) {
 		qdf_mem_free(hidden_ssid_vdev_restart);

+ 1 - 1
core/mac/src/pe/lim/lim_types.h

@@ -546,7 +546,7 @@ void lim_send_deauth_mgmt_frame(struct mac_context *, uint16_t, tSirMacAddr, str
 				bool waitForAck);
 
 void lim_process_mlm_update_hidden_ssid_rsp(struct mac_context *mac_ctx,
-		struct scheduler_msg *msg);
+					    struct scheduler_msg *msg);
 
 tSirResultCodes lim_mlm_add_bss(struct mac_context *, tLimMlmStartReq *,
 				struct pe_session *pe_session);

+ 1 - 0
core/mac/src/sys/legacy/src/utils/src/mac_trace.c

@@ -374,6 +374,7 @@ uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg)
 		CASE_RETURN_STRING(eWNI_SME_CSA_RESTART_REQ);
 		CASE_RETURN_STRING(eWNI_SME_CSA_RESTART_RSP);
 		CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END);
+		CASE_RETURN_STRING(eWNI_SME_HIDDEN_SSID_RESTART_RSP);
 	default:
 		return (uint8_t *) "UNKNOWN";
 		break;

+ 3 - 0
core/sap/inc/sap_api.h

@@ -169,6 +169,8 @@ typedef enum {
 	eSAP_ACS_CHANNEL_SELECTED,
 	eSAP_ECSA_CHANGE_CHAN_IND,
 	eSAP_DFS_NEXT_CHANNEL_REQ,
+	/* Event sent channel switch status to upper layer */
+	eSAP_CHANNEL_CHANGE_RESP,
 } eSapHddEvent;
 
 typedef enum {
@@ -427,6 +429,7 @@ typedef struct sap_Event_s {
 		struct sap_ch_selected_s sap_ch_selected;
 		struct sap_ch_change_ind sap_chan_cng_ind;
 		struct sap_acs_scan_complete_event sap_acs_scan_comp;
+		QDF_STATUS ch_change_rsp_status;
 	} sapevt;
 } tSap_Event, *tpSap_Event;
 

+ 11 - 1
core/sap/src/sap_api_link_cntl.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019 The Linux Foundation. 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
@@ -1206,6 +1206,11 @@ wlansap_roam_callback(void *ctx, struct csr_roam_info *csr_roam_info,
 	case eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS:
 		wlansap_roam_process_ch_change_success(mac_ctx, sap_ctx,
 						csr_roam_info, &qdf_ret_status);
+
+		qdf_ret_status =
+			sap_signal_hdd_event(sap_ctx, csr_roam_info,
+					     eSAP_CHANNEL_CHANGE_RESP,
+					     (void *)QDF_STATUS_SUCCESS);
 		break;
 	case eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE:
 		/* This is much more serious issue, we have to vacate the
@@ -1213,6 +1218,11 @@ wlansap_roam_callback(void *ctx, struct csr_roam_info *csr_roam_info,
 		 * failed, stop the BSS operation completely and inform hostapd
 		 */
 		qdf_ret_status = wlansap_stop_bss(sap_ctx);
+
+		qdf_ret_status =
+			sap_signal_hdd_event(sap_ctx, csr_roam_info,
+					     eSAP_CHANNEL_CHANGE_RESP,
+					     (void *)QDF_STATUS_E_FAILURE);
 		break;
 	case eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND:
 		qdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,

+ 9 - 0
core/sap/src/sap_fsm.c

@@ -1736,6 +1736,15 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx,
 			     sap_ctx->sessionId, sap_ctx->self_mac_addr,
 			     sap_ctx->channel);
 		break;
+
+	case eSAP_CHANNEL_CHANGE_RESP:
+		sap_ap_event.sapHddEventCode = eSAP_CHANNEL_CHANGE_RESP;
+		sap_ap_event.sapevt.ch_change_rsp_status = (QDF_STATUS)context;
+		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
+			  "In %s, SAP event callback event = %s",
+			 __func__, "eSAP_CHANNEL_CHANGE_RESP");
+		break;
+
 	default:
 		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
 			  FL("SAP Unknown callback event = %d"),

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

@@ -3197,4 +3197,13 @@ QDF_STATUS sme_set_thermal_mgmt(mac_handle_t mac_handle,
 				uint16_t lower_thresh_deg,
 				uint16_t higher_thresh_deg);
 #endif /* FW_THERMAL_THROTTLE_SUPPORT */
+
+/**
+ * sme_update_hidden_ssid_status_cb() - cb fun to update hidden ssid stats
+ * @mac_handle: mac handler
+ * @cb: cb of type hidden_ssid_cb
+ */
+QDF_STATUS sme_update_hidden_ssid_status_cb(mac_handle_t mac_handle,
+					    hidden_ssid_cb cb);
+
 #endif /* #if !defined( __SME_API_H ) */

+ 10 - 0
core/sme/inc/sme_internal.h

@@ -227,6 +227,13 @@ typedef void (*rso_cmd_status_cb)(hdd_handle_t hdd_handle,
  */
 typedef void (*lost_link_info_cb)(hdd_handle_t hdd_handle,
 				  struct sir_lost_link_info *lost_link_info);
+/**
+ * typedef hidden_ssid_cb - hidden ssid rsp callback fun
+ * @hdd_handle: HDD handle registered with SME
+ * @vdev_id: Vdev Id
+ */
+typedef void (*hidden_ssid_cb)(hdd_handle_t hdd_handle,
+				uint8_t vdev_id);
 
 #ifdef WLAN_FEATURE_MOTION_DETECTION
 typedef QDF_STATUS (*md_host_evt_cb)(void *hdd_ctx, sir_md_evt *event);
@@ -323,6 +330,9 @@ typedef struct tagSmeStruct {
 	md_host_evt_cb md_host_evt_cb;
 	void *md_ctx;
 #endif /* WLAN_FEATURE_MOTION_DETECTION */
+	/* hidden ssid rsp callback */
+	hidden_ssid_cb hidden_ssid_cb;
+
 } tSmeStruct, *tpSmeStruct;
 
 #endif /* #if !defined( __SMEINTERNAL_H ) */

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

@@ -2247,6 +2247,12 @@ QDF_STATUS sme_process_msg(struct mac_context *mac, struct scheduler_msg *pMsg)
 			mac->sme.bt_activity_info_cb(mac->hdd_handle,
 						      pMsg->bodyval);
 		break;
+	case eWNI_SME_HIDDEN_SSID_RESTART_RSP:
+		if (mac->sme.hidden_ssid_cb)
+			mac->sme.hidden_ssid_cb(mac->hdd_handle, pMsg->bodyval);
+		else
+			sme_err("callback is NULL");
+		break;
 	default:
 
 		if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN)
@@ -15020,3 +15026,18 @@ QDF_STATUS sme_set_thermal_mgmt(mac_handle_t mac_handle,
 	return qdf_status;
 }
 #endif /* FW_THERMAL_THROTTLE_SUPPORT */
+
+QDF_STATUS sme_update_hidden_ssid_status_cb(mac_handle_t mac_handle,
+					    hidden_ssid_cb cb)
+{
+	QDF_STATUS status;
+	struct mac_context *mac = MAC_CONTEXT(mac_handle);
+
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		mac->sme.hidden_ssid_cb = cb;
+		sme_release_global_lock(&mac->sme);
+	}
+
+	return status;
+}