wlan: Allow single PNO scan at a time.
Its possible that, PNO scan is enabled either through wext or
through supplicant.
Changes have been made to allow only one PNO scan at a given time
by adding new variable, isPnoEnable.
Change-Id: Ifee337d5bb6175acdd5f6997942125e5306e89e0
CRs-Fixed: 622466
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 15f8df5..2abfc77 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1272,6 +1272,7 @@
#endif /* FEATURE_WLAN_CH_AVOID */
v_BOOL_t btCoexModeSet;
+ v_BOOL_t isPnoEnable;
};
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 8d8c299..3f3b3a9 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -8396,11 +8396,20 @@
return -EBUSY;
}
+ if (TRUE == pHddCtx->isPnoEnable)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ FL("already PNO is enabled"));
+ return -EBUSY;
+ }
+ pHddCtx->isPnoEnable = TRUE;
+
pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
if (NULL == pPnoRequest)
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
"%s: vos_mem_malloc failed", __func__);
+ pHddCtx->isPnoEnable = FALSE;
return -ENOMEM;
}
@@ -8570,11 +8579,13 @@
}
ret = pAdapter->pno_req_status;
+ return ret;
error:
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
FL("PNO scanRequest offloaded ret = %d"), ret);
vos_mem_free(pPnoRequest);
+ pHddCtx->isPnoEnable = FALSE;
return ret;
}
@@ -8663,6 +8674,7 @@
ret = -EINVAL;
goto error;
}
+ pHddCtx->isPnoEnable = FALSE;
error:
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 5754fb4..3efa537 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -6874,6 +6874,7 @@
union iwreq_data *wrqu, char *extra, int nOffset)
{
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
/* pnoRequest is a large struct, so we make it static to avoid stack
overflow. This API is only invoked via ioctl, so it is
serialized by the kernel rtnl_lock and hence does not need to be
@@ -6881,6 +6882,7 @@
static tSirPNOScanReq pnoRequest;
char *ptr;
v_U8_t i,j, ucParams, ucMode;
+ eHalStatus status = eHAL_STATUS_FAILURE;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -6937,20 +6939,35 @@
{
/*Disable PNO*/
memset(&pnoRequest, 0, sizeof(pnoRequest));
- sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), &pnoRequest,
+ status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ &pnoRequest,
pAdapter->sessionId,
found_pref_network_cb, pAdapter);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: failed to disable PNO", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+ pHddCtx->isPnoEnable = FALSE;
return VOS_STATUS_SUCCESS;
}
+ if (TRUE == pHddCtx->isPnoEnable)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
+ FL("already PNO is enabled"));
+ return -EBUSY;
+ }
+ pHddCtx->isPnoEnable = TRUE;
+
ptr += nOffset;
if (1 != sscanf(ptr,"%hhu %n", &(pnoRequest.ucNetworksCount), &nOffset))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"PNO count input not valid %s",ptr);
- return VOS_STATUS_E_FAILURE;
-
+ goto error;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -6965,7 +6982,7 @@
( pnoRequest.ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Network input is not correct");
- return VOS_STATUS_E_FAILURE;
+ goto error;
}
ptr += nOffset;
@@ -6991,7 +7008,7 @@
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"SSID Len %d is not correct for network %d",
pnoRequest.aNetworks[i].ssId.length, i);
- return VOS_STATUS_E_FAILURE;
+ goto error;
}
/*Advance to SSID*/
@@ -7011,7 +7028,7 @@
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
"Incorrect cmd %s",ptr);
- return VOS_STATUS_E_FAILURE;
+ goto error;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -7063,7 +7080,7 @@
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"PNO broadcast network type input is not valid %s",ptr);
- return VOS_STATUS_E_FAILURE;
+ goto error;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -7080,7 +7097,7 @@
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"PNO rssi threshold input is not valid %s",ptr);
- return VOS_STATUS_E_FAILURE;
+ goto error;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -7109,7 +7126,7 @@
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"Incorrect cmd - too many scan timers");
- return VOS_STATUS_E_FAILURE;
+ goto error;
}
for ( i = 0; i < pnoRequest.scanTimers.ucScanTimersCount; i++ )
@@ -7123,7 +7140,7 @@
{
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
"Incorrect cmd - diff params then expected %d", ucParams);
- return VOS_STATUS_E_FAILURE;
+ goto error;
}
VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -7157,11 +7174,20 @@
pnoRequest.modePNO = SIR_PNO_MODE_ON_SUSPEND;
}
- sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), &pnoRequest,
+ status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), &pnoRequest,
pAdapter->sessionId,
found_pref_network_cb, pAdapter);
-
- return VOS_STATUS_SUCCESS;
+ if (eHAL_STATUS_SUCCESS == status)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: PNO enabled", __func__);
+ return VOS_STATUS_SUCCESS;
+ }
+error:
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to enable PNO", __func__);
+ pHddCtx->isPnoEnable = FALSE;
+ return VOS_STATUS_E_FAILURE;
}/*iw_set_pno*/
VOS_STATUS iw_set_rssi_filter(struct net_device *dev, struct iw_request_info *info,