Browse Source

qcacld-3.0: Consider NAN enabling also as connection in progress

There is a race condition while handling the below scenario,
1. NAN enable request is received from framework.
2. Policy mgr opportunistic timer expired and set hw mode
   initiated to Single MAC mode in scheduler thread at
   the same time

As the opportunistic timer handler doesn't have any info if
NAN enable initiated in DBS mode, it's configuring the hw
mode to Single Mac Mode just before NAN enable request is sent
to firmware. So the NAN enable request is sent to firmware in
Single Mac Mode which is not allowed by firmware.

NAN enable/disable is also similar to connection in progress
status in case of STA. So provide NAN enable/disable status
through hdd_is_connection_in_progress() to the opportunistic
timer handler. Opportunistic timer handler restarts the timer as
connection(NAN enable/disable) is in progress.

Also set hw_mode_change_in_progress before checking the
connection progress status. This is to avoid a possible race in
the below scenario,
1. NAN-enable sets the state but scheduler thread had read the
   state just before that
2. NAN-enable read the hw_mode_change_in_progress just
   before it gets set by scheduler thread.

Change-Id: I1a184c84520deb3f6ad1ec010a0fdefda96a5364
CRs-Fixed: 2566841
Srinivas Dasari 5 years ago
parent
commit
b24bdd3f73

+ 13 - 0
components/nan/dispatcher/inc/nan_ucfg_api.h

@@ -340,6 +340,13 @@ ucfg_nan_check_and_disable_unsupported_ndi(struct wlan_objmgr_psoc *psoc,
  */
 QDF_STATUS ucfg_ndi_remove_entry_from_policy_mgr(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * ucfg_nan_is_enable_disable_in_progress() - Is NAN enable/disable in progress
+ * @psoc: Pointer to PSOC object
+ *
+ * Return: True if NAN discovery enable/disable is in progress, false otherwise
+ */
+bool ucfg_nan_is_enable_disable_in_progress(struct wlan_objmgr_psoc *psoc);
 #else /* WLAN_FEATURE_NAN */
 
 static inline
@@ -379,5 +386,11 @@ enum nan_datapath_state ucfg_nan_get_ndi_state(struct wlan_objmgr_vdev *vdev)
 	return NAN_DATA_INVALID_STATE;
 }
 
+static inline
+bool ucfg_nan_is_enable_disable_in_progress(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
+
 #endif /* WLAN_FEATURE_NAN */
 #endif /* _NAN_UCFG_API_H_ */

+ 15 - 0
components/nan/dispatcher/src/nan_ucfg_api.c

@@ -951,3 +951,18 @@ QDF_STATUS ucfg_ndi_remove_entry_from_policy_mgr(struct wlan_objmgr_vdev *vdev)
 
 	return QDF_STATUS_SUCCESS;
 }
+
+bool ucfg_nan_is_enable_disable_in_progress(struct wlan_objmgr_psoc *psoc)
+{
+	enum nan_disc_state nan_state;
+
+	nan_state = nan_get_discovery_state(psoc);
+	if (nan_state == NAN_DISC_ENABLE_IN_PROGRESS ||
+	    nan_state == NAN_DISC_DISABLE_IN_PROGRESS) {
+		nan_info("NAN enable/disable is in progress, state: %u",
+			 nan_state);
+		return true;
+	}
+
+	return false;
+}

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

@@ -15675,6 +15675,14 @@ static QDF_STATUS hdd_is_connection_in_progress_iterator(
 		}
 	}
 
+	if (ucfg_nan_is_enable_disable_in_progress(hdd_ctx->psoc)) {
+		context->out_reason = NAN_ENABLE_DISABLE_IN_PROGRESS;
+		context->out_vdev_id = NAN_PSEUDO_VDEV_ID;
+		context->connection_in_progress = true;
+
+		return QDF_STATUS_E_ABORTED;
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 2 - 0
core/mac/inc/sir_api.h

@@ -5532,6 +5532,7 @@ struct sme_rcpi_req {
  * @EAPOL_IN_PROGRESS: STA/P2P-CLI is in middle of EAPOL/WPS exchange
  * @SAP_EAPOL_IN_PROGRESS: SAP/P2P-GO is in middle of EAPOL/WPS exchange
  * @SAP_CONNECTION_IN_PROGRESS: SAP/P2P-GO is in middle of connection.
+ * @NAN_ENABLE_DISABLE_IN_PROGRESS: NAN is in middle of enable/disable discovery
  */
 enum scan_reject_states {
 	SCAN_REJECT_DEFAULT = 0,
@@ -5540,6 +5541,7 @@ enum scan_reject_states {
 	EAPOL_IN_PROGRESS,
 	SAP_EAPOL_IN_PROGRESS,
 	SAP_CONNECTION_IN_PROGRESS,
+	NAN_ENABLE_DISABLE_IN_PROGRESS,
 };
 
 /**

+ 21 - 19
core/sme/src/csr/csr_api_roam.c

@@ -21128,22 +21128,6 @@ void csr_process_set_hw_mode(struct mac_context *mac, tSmeCmd *command)
 		}
 	}
 
-	if ((POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC ==
-		command->u.set_hw_mode_cmd.reason) &&
-		(true == mac->sme.get_connection_info_cb(NULL, NULL))) {
-		sme_err("Set HW mode refused: conn in progress");
-		policy_mgr_restart_opportunistic_timer(mac->psoc, false);
-		goto fail;
-	}
-
-	if ((POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC ==
-		command->u.set_hw_mode_cmd.reason) &&
-		(!command->u.set_hw_mode_cmd.hw_mode_index &&
-		!policy_mgr_need_opportunistic_upgrade(mac->psoc, NULL))) {
-		sme_err("Set HW mode to SMM not needed anymore");
-		goto fail;
-	}
-
 	hw_mode = policy_mgr_get_hw_mode_change_from_hw_mode_index(
 			mac->psoc, command->u.set_hw_mode_cmd.hw_mode_index);
 
@@ -21154,6 +21138,22 @@ void csr_process_set_hw_mode(struct mac_context *mac, tSmeCmd *command)
 
 	policy_mgr_set_hw_mode_change_in_progress(mac->psoc, hw_mode);
 
+	if ((POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC ==
+	     command->u.set_hw_mode_cmd.reason) &&
+	    (true == mac->sme.get_connection_info_cb(NULL, NULL))) {
+		sme_err("Set HW mode refused: conn in progress");
+		policy_mgr_restart_opportunistic_timer(mac->psoc, false);
+		goto reset_state;
+	}
+
+	if ((POLICY_MGR_UPDATE_REASON_OPPORTUNISTIC ==
+	     command->u.set_hw_mode_cmd.reason) &&
+	    (!command->u.set_hw_mode_cmd.hw_mode_index &&
+	     !policy_mgr_need_opportunistic_upgrade(mac->psoc, NULL))) {
+		sme_err("Set HW mode to SMM not needed anymore");
+		goto reset_state;
+	}
+
 	cmd->messageType = eWNI_SME_SET_HW_MODE_REQ;
 	cmd->length = len;
 	cmd->set_hw.hw_mode_index = command->u.set_hw_mode_cmd.hw_mode_index;
@@ -21171,13 +21171,15 @@ void csr_process_set_hw_mode(struct mac_context *mac, tSmeCmd *command)
 
 	status = umac_send_mb_message_to_mac(cmd);
 	if (QDF_STATUS_SUCCESS != status) {
-		policy_mgr_set_hw_mode_change_in_progress(mac->psoc,
-			POLICY_MGR_HW_MODE_NOT_IN_PROGRESS);
 		sme_err("Posting to PE failed");
 		cmd = NULL;
-		goto fail;
+		goto reset_state;
 	}
 	return;
+
+reset_state:
+	policy_mgr_set_hw_mode_change_in_progress(mac->psoc,
+			POLICY_MGR_HW_MODE_NOT_IN_PROGRESS);
 fail:
 	if (cmd)
 		qdf_mem_free(cmd);