wlan: Avoid PNO during active session or session in progress
Avoid race condition of enabling PNO when there is exisiting
active session or during the session being establishment.
Change-Id: Ibc4641f598301c8807d953db90fed99ece4616ea
CRs-Fixed: 623887
(cherry picked from commit 3aec5c618d7c3b0ac522b6cf8876468b777bfca3)
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index cfe9b51..9cc4ff2 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -8317,6 +8317,33 @@
return eHAL_STATUS_SUCCESS;
}
+void hdd_cfg80211_sched_scan_start_status_cb(void *callbackContext, VOS_STATUS status)
+{
+ hdd_adapter_t *pAdapter = callbackContext;
+ hdd_context_t *pHddCtx;
+
+ if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ FL("Invalid adapter or adapter has invalid magic"));
+ return;
+ }
+
+ pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ if (0 != wlan_hdd_validate_context(pHddCtx))
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ FL("HDD context is not valid"));
+ return;
+ }
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ FL("PNO enable response status = %d"), status);
+
+ pAdapter->pno_req_status = (status == VOS_STATUS_SUCCESS) ? 0 : -EBUSY;
+ complete(&pAdapter->pno_comp_var);
+}
+
/*
* FUNCTION: wlan_hdd_cfg80211_sched_scan_start
* NL interface to enable PNO
@@ -8509,6 +8536,11 @@
pPnoRequest->modePNO = SIR_PNO_MODE_IMMEDIATE;
+ INIT_COMPLETION(pAdapter->pno_comp_var);
+ pPnoRequest->statusCallback = hdd_cfg80211_sched_scan_start_status_cb;
+ pPnoRequest->callbackContext = pAdapter;
+ pAdapter->pno_req_status = 0;
+
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"SessionId %d, enable %d, modePNO %d, ucScanTimersCount %d",
pAdapter->sessionId, pPnoRequest->enable, pPnoRequest->modePNO,
@@ -8525,10 +8557,26 @@
goto error;
}
- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
- "PNO scanRequest offloaded");
+ ret = wait_for_completion_timeout(
+ &pAdapter->pno_comp_var,
+ msecs_to_jiffies(WLAN_WAIT_TIME_PNO));
+ if (0 >= ret)
+ {
+ // Did not receive the response for PNO enable in time.
+ // Assuming the PNO enable was success.
+ // Returning error from here, because we timeout, results
+ // in side effect of Wifi (Wifi Setting) not to work.
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ FL("Timed out waiting for PNO to be Enabled"));
+ ret = 0;
+ goto error;
+ }
+
+ ret = pAdapter->pno_req_status;
error:
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ FL("PNO scanRequest offloaded ret = %d"), ret);
vos_mem_free(pPnoRequest);
return ret;
}
@@ -8616,11 +8664,12 @@
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"Failed to disabled PNO");
ret = -EINVAL;
+ goto error;
}
+error:
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
- "%s: PNO scan disabled", __func__);
-
+ FL("PNO scan disabled ret = %d"), ret);
vos_mem_free(pPnoRequest);
EXIT();
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 72e1cf9..f442f4f 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -5263,6 +5263,7 @@
init_completion(&pAdapter->linkup_event_var);
init_completion(&pAdapter->cancel_rem_on_chan_var);
init_completion(&pAdapter->rem_on_chan_ready_event);
+ init_completion(&pAdapter->pno_comp_var);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
init_completion(&pAdapter->offchannel_tx_event);
#endif