Browse Source

qcacmn: Defer the channel switch if it is already in progress

When sta+sap scc enabled on dfs channel then SAP cannot operate on
DFS channel in standalone mode. If STA+SAP are operating in SCC mode
on a DFS channel and STA gets disconnected from reference AP then driver
schedules a workqueue to move the SAP from DFS channel to user configured
channel. At this time if STA again connects to reference AP within few ms
then driver again schedules one more workqueue to move the SAP to STA's
channel. Sometimes the second workqueue may fail to switch the channel
if first one is not yet completed. So added event variable to schedule
second workqueue only when first one is complete.

CRs-Fixed: 2267005
Change-Id: Ia6ce4b6264c35f6d2c809e2a3f65f535e930874e
Bala Venkatesh 6 years ago
parent
commit
1e9e680a92

+ 22 - 0
umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -1146,6 +1146,28 @@ QDF_STATUS policy_mgr_reset_connection_update(struct wlan_objmgr_psoc *psoc);
  */
 QDF_STATUS policy_mgr_set_connection_update(struct wlan_objmgr_psoc *psoc);
 
+/**
+ * policy_mgr_set_chan_switch_complete_evt() - set channel
+ * switch completion event
+ * @psoc: PSOC object information
+ * Sets the channel switch completion event.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS policy_mgr_set_chan_switch_complete_evt(
+		struct wlan_objmgr_psoc *psoc);
+
+/**
+ * policy_mgr_reset_chan_switch_complete_evt() - reset channel
+ * switch completion event
+ * @psoc: PSOC object information
+ * Resets the channel switch completion event.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS policy_mgr_reset_chan_switch_complete_evt(
+		struct wlan_objmgr_psoc *psoc);
+
 /**
  * policy_mgr_set_opportunistic_update() - Set opportunistic
  * update event

+ 54 - 0
umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c

@@ -881,6 +881,14 @@ void policy_mgr_check_sta_ap_concurrent_ch_intf(void *data)
 		goto end;
 	}
 
+	policy_mgr_debug("wait if channel switch is already in progress");
+	status = qdf_wait_single_event(
+				&pm_ctx->channel_switch_complete_evt,
+				CHANNEL_SWITCH_COMPLETE_TIMEOUT);
+
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		policy_mgr_err("wait for event failed, still continue with channel switch");
+	}
 	if (!pm_ctx->hdd_cbacks.wlan_hdd_get_channel_for_sap_restart) {
 		policy_mgr_err("SAP restart get channel callback in NULL");
 		goto end;
@@ -1181,6 +1189,52 @@ QDF_STATUS policy_mgr_set_connection_update(struct wlan_objmgr_psoc *psoc)
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS policy_mgr_set_chan_switch_complete_evt(
+		struct wlan_objmgr_psoc *psoc)
+{
+	QDF_STATUS status;
+	struct policy_mgr_psoc_priv_obj *policy_mgr_context;
+
+	policy_mgr_context = policy_mgr_get_context(psoc);
+
+	if (!policy_mgr_context) {
+		policy_mgr_err("Invalid context");
+		return QDF_STATUS_E_FAILURE;
+	}
+	status = qdf_event_set(
+			&policy_mgr_context->channel_switch_complete_evt);
+
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		policy_mgr_err("set event failed");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS policy_mgr_reset_chan_switch_complete_evt(
+		struct wlan_objmgr_psoc *psoc)
+{
+	QDF_STATUS status;
+	struct policy_mgr_psoc_priv_obj *policy_mgr_context;
+
+	policy_mgr_context = policy_mgr_get_context(psoc);
+
+	if (!policy_mgr_context) {
+		policy_mgr_err("Invalid context");
+		return QDF_STATUS_E_FAILURE;
+	}
+	status = qdf_event_reset(
+			&policy_mgr_context->channel_switch_complete_evt);
+
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		policy_mgr_err("reset event failed");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS policy_mgr_set_opportunistic_update(struct wlan_objmgr_psoc *psoc)
 {
 	QDF_STATUS status;

+ 2 - 0
umac/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h

@@ -35,6 +35,7 @@
 
 #define PM_24_GHZ_CHANNEL_6   (6)
 #define PM_5_GHZ_CHANNEL_36   (36)
+#define CHANNEL_SWITCH_COMPLETE_TIMEOUT   (2000)
 
 /**
  * Policy Mgr hardware mode list bit-mask definitions.
@@ -265,6 +266,7 @@ struct policy_mgr_psoc_priv_obj {
 	uint8_t cur_conc_system_pref;
 	uint8_t sta_sap_scc_on_dfs_chan_allowed;
 	qdf_event_t opportunistic_update_done_evt;
+	qdf_event_t channel_switch_complete_evt;
 	send_mode_change_event_cb mode_change_cb;
 };
 

+ 12 - 0
umac/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c

@@ -403,6 +403,11 @@ QDF_STATUS policy_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
 		return status;
 	}
 
+	status = qdf_event_create(&pm_ctx->channel_switch_complete_evt);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		policy_mgr_err("channel_switch_complete_evt init failed");
+		return status;
+	}
 	pm_ctx->do_hw_mode_change = false;
 	pm_ctx->hw_mode_change_in_progress = POLICY_MGR_HW_MODE_NOT_IN_PROGRESS;
 	/* reset sap mandatory channels */
@@ -477,6 +482,13 @@ QDF_STATUS policy_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc)
 		status = QDF_STATUS_E_FAILURE;
 		QDF_ASSERT(0);
 	}
+	/* destroy channel_switch_complete_evt */
+	if (!QDF_IS_STATUS_SUCCESS(qdf_event_destroy
+		(&pm_ctx->channel_switch_complete_evt))) {
+		policy_mgr_err("Failed to destroy channel_switch_complete evt");
+		status = QDF_STATUS_E_FAILURE;
+		QDF_ASSERT(0);
+	}
 
 	/* deallocate dbs_opportunistic_timer */
 	if (QDF_TIMER_STATE_RUNNING ==