summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiangwei Dong <liangwei@codeaurora.org>2016-09-27 03:58:27 -0400
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-10-18 13:31:28 +0530
commit02428a400e3f5e3231386b33a8c89401b329eba7 (patch)
treecce7b3e594fafda8724e0b04ddbbfab7f4de60d1
parentb0c45166b16d670d7f414d2ea8ab29decd467399 (diff)
qcacld-2.0: On demand OBSS scan of SAP
To shorten the SAP starting time, the OBSS scan can be skipped if the ACS scan is performed and the ACS scan channels cover the OBSS scan channel list. This change caches the ACS channel list and skip the OBSS scan if necessary. Change-Id: Iae54115051ae037c83b8dd2b639754f941c1d0f5 CRs-Fixed: 1073053
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg80211.h3
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h3
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg80211.c88
-rw-r--r--CORE/HDD/src/wlan_hdd_hostapd.c85
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c39
-rw-r--r--CORE/SAP/inc/sapApi.h15
-rw-r--r--CORE/SAP/src/sapApiLinkCntl.c2
-rw-r--r--CORE/SAP/src/sapFsm.c43
-rw-r--r--CORE/SAP/src/sapInternal.h1
9 files changed, 245 insertions, 34 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h
index b68ab6da55db..329f8bb09ca4 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h
@@ -2025,6 +2025,9 @@ struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
tCsrRoamInfo *pRoamInfo
);
+int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
+ hdd_adapter_t *pAdapter);
+
#ifdef FEATURE_WLAN_LFR
int wlan_hdd_cfg80211_pmksa_candidate_notify(
hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index de9ca053f13a..d79201fc1ade 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1775,6 +1775,9 @@ struct hdd_context_s
#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
vos_timer_t skip_acs_scan_timer;
v_U8_t skip_acs_scan_status;
+ uint8_t *last_acs_channel_list;
+ uint8_t num_of_channels;
+ spinlock_t acs_skip_lock;
#endif
vos_wake_lock_t sap_dfs_wakelock;
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index e9847797d3c4..016b2671fd81 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -17093,12 +17093,17 @@ wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
return bss;
}
-/*
- * FUNCTION: wlan_hdd_cfg80211_update_bss
+/**
+ * wlan_hdd_cfg80211_update_bss() - update scan result to cfg80211
+ * @wiphy: wiphy context
+ * @pAdapter: hdd_adapter_t context
+ *
+ * This function will update the cached scan result to cfg80211 module
+ *
+ * Return: 0 for updating successfully
+ * other value for error
*/
-static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
- hdd_adapter_t *pAdapter
- )
+int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy, hdd_adapter_t *pAdapter)
{
tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
tCsrScanResultInfo *pScanResult;
@@ -17688,6 +17693,66 @@ bool hdd_isConnectionInProgress(hdd_context_t *pHddCtx)
return false;
}
+#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
+/**
+ * wlan_hdd_sap_skip_scan_check() - The function will check OBSS
+ * scan skip or not for SAP.
+ * @hdd_ctx: pointer to hdd context.
+ * @request: pointer to scan request.
+ *
+ * This function will check the scan request's chan list against the
+ * previous ACS scan chan list. If all the chan are covered by
+ * previous ACS scan, we can skip the scan and return scan complete
+ * to save the SAP starting time.
+ *
+ * Return: true to skip the scan,
+ * false to continue the scan
+ */
+static bool wlan_hdd_sap_skip_scan_check(hdd_context_t *hdd_ctx,
+ struct cfg80211_scan_request *request)
+{
+ int i, j;
+ bool skip;
+
+ hddLog(LOG1, FL("HDD_ACS_SKIP_STATUS = %d"),
+ hdd_ctx->skip_acs_scan_status);
+ if (hdd_ctx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN)
+ return false;
+ spin_lock(&hdd_ctx->acs_skip_lock);
+ if (hdd_ctx->last_acs_channel_list == NULL ||
+ hdd_ctx->num_of_channels == 0 ||
+ request->n_channels == 0) {
+ spin_unlock(&hdd_ctx->acs_skip_lock);
+ return false;
+ }
+ skip = true;
+ for (i = 0; i < request->n_channels ; i++ ) {
+ bool find = false;
+ for (j = 0; j < hdd_ctx->num_of_channels; j++) {
+ if (hdd_ctx->last_acs_channel_list[j] ==
+ request->channels[i]->hw_value) {
+ find = true;
+ break;
+ }
+ }
+ if (!find) {
+ skip = false;
+ hddLog(LOG1, FL("Chan %d isn't in ACS chan list"),
+ request->channels[i]->hw_value);
+ break;
+ }
+ }
+ spin_unlock(&hdd_ctx->acs_skip_lock);
+ return skip;
+}
+#else
+static bool wlan_hdd_sap_skip_scan_check(hdd_context_t *hdd_ctx,
+ struct cfg80211_scan_request *request)
+{
+ return false;
+}
+#endif
+
static void wlan_hdd_cfg80211_scan_block_cb(struct work_struct *work)
{
hdd_adapter_t *adapter = container_of(work,
@@ -17779,6 +17844,9 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
* Thus we return null scan result. If we return scan failure
* hostapd fails secondary AP startup.
*/
+ hddLog(LOGE,
+ FL("##In DFS Master mode. Scan aborted"));
+
pAdapter->request = request;
vos_init_work(&pAdapter->scan_block_work,
@@ -17852,6 +17920,16 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
hddLog(LOGE, FL("Scan not allowed"));
return -EBUSY;
}
+ /* Check whether SAP scan can be skipped or not */
+ if (pAdapter->device_mode == WLAN_HDD_SOFTAP &&
+ wlan_hdd_sap_skip_scan_check(pHddCtx, request)) {
+ hddLog(LOGE, FL("sap scan skipped"));
+ pAdapter->request = request;
+ vos_init_work(&pAdapter->scan_block_work,
+ wlan_hdd_cfg80211_scan_block_cb);
+ schedule_work(&pAdapter->scan_block_work);
+ return 0;
+ }
vos_mem_zero( &scanRequest, sizeof(scanRequest));
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 67791575975f..3ab859ebb1f1 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -1286,6 +1286,78 @@ static VOS_STATUS hdd_wlan_set_dfs_nol(const void *pdfs_list, u16 sdfs_list)
}
#endif
+#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
+/**
+ * hdd_handle_acs_scan_event() - handle acs scan event for SAP
+ * @sap_event: tpSap_Event
+ * @adapter: hdd_adapter_t for SAP
+ *
+ * The function is to handle the eSAP_ACS_SCAN_SUCCESS_EVENT event.
+ * It will update scan result to cfg80211 and start a timer to flush the
+ * cached acs scan result.
+ *
+ * Return: VOS_STATUS_SUCCESS on success,
+ other value on failure
+ */
+static VOS_STATUS hdd_handle_acs_scan_event(tpSap_Event sap_event,
+ hdd_adapter_t *adapter)
+{
+ hdd_context_t *hdd_ctx;
+ struct tsap_acs_scan_complete_event *comp_evt;
+ VOS_STATUS vos_status;
+ int chan_list_size;
+
+ hdd_ctx = (hdd_context_t*)(adapter->pHddCtx);
+ if (!hdd_ctx) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is null"));
+ return VOS_STATUS_E_FAILURE;
+ }
+ comp_evt = &sap_event->sapevt.sap_acs_scan_comp;
+ hdd_ctx->skip_acs_scan_status = eSAP_SKIP_ACS_SCAN;
+ spin_lock(&hdd_ctx->acs_skip_lock);
+ vos_mem_free(hdd_ctx->last_acs_channel_list);
+ hdd_ctx->last_acs_channel_list = NULL;
+ hdd_ctx->num_of_channels = 0;
+ /* cache the previous ACS scan channel list .
+ * If the following OBSS scan chan list is covered by ACS chan list,
+ * we can skip OBSS Scan to save SAP starting total time.
+ */
+ if (comp_evt->num_of_channels && comp_evt->channellist) {
+ chan_list_size = comp_evt->num_of_channels *
+ sizeof(comp_evt->channellist[0]);
+ hdd_ctx->last_acs_channel_list = vos_mem_malloc(
+ chan_list_size);
+ if (hdd_ctx->last_acs_channel_list) {
+ vos_mem_copy(hdd_ctx->last_acs_channel_list,
+ comp_evt->channellist,
+ chan_list_size);
+ hdd_ctx->num_of_channels = comp_evt->num_of_channels;
+ }
+ }
+ spin_unlock(&hdd_ctx->acs_skip_lock);
+ /* Update ACS scan result to cfg80211. Then OBSS scan can reuse the
+ * scan result.
+ */
+ if (wlan_hdd_cfg80211_update_bss(hdd_ctx->wiphy, adapter))
+ hddLog(VOS_TRACE_LEVEL_INFO, FL("NO SCAN result"));
+
+ hddLog(LOG1, FL("Reusing Last ACS scan result for %d sec"),
+ ACS_SCAN_EXPIRY_TIMEOUT_S);
+ vos_timer_stop( &hdd_ctx->skip_acs_scan_timer);
+ vos_status = vos_timer_start( &hdd_ctx->skip_acs_scan_timer,
+ ACS_SCAN_EXPIRY_TIMEOUT_S * 1000);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status))
+ hddLog(LOGE, FL("Failed to start ACS scan expiry timer"));
+ return VOS_STATUS_SUCCESS;
+}
+#else
+static VOS_STATUS hdd_handle_acs_scan_event(tpSap_Event sap_event,
+ hdd_adapter_t *adapter)
+{
+ return VOS_STATUS_SUCCESS;
+}
+#endif
+
VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCallback)
{
hdd_adapter_t *pHostapdAdapter;
@@ -2147,19 +2219,8 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa
else
return hdd_chan_change_notify(pHostapdAdapter, dev,
pSapEvent->sapevt.sapChSelected.pri_ch);
-#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
case eSAP_ACS_SCAN_SUCCESS_EVENT:
- pHddCtx->skip_acs_scan_status = eSAP_SKIP_ACS_SCAN;
- hddLog(LOG1, FL("Reusing Last ACS scan result for %d sec"),
- ACS_SCAN_EXPIRY_TIMEOUT_S);
- vos_timer_stop( &pHddCtx->skip_acs_scan_timer);
- vos_status = vos_timer_start( &pHddCtx->skip_acs_scan_timer,
- ACS_SCAN_EXPIRY_TIMEOUT_S * 1000);
- if (!VOS_IS_STATUS_SUCCESS(vos_status))
- hddLog(LOGE, FL("Failed to start ACS scan expiry timer"));
- return VOS_STATUS_SUCCESS;
-#endif
-
+ return hdd_handle_acs_scan_event(pSapEvent, pHostapdAdapter);
case eSAP_DFS_NOL_GET:
hddLog(VOS_TRACE_LEVEL_INFO,
FL("Received eSAP_DFS_NOL_GET event"));
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 0268797bc8ef..dbb748ad9969 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -13070,6 +13070,11 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx)
hddLog(VOS_TRACE_LEVEL_ERROR,
"%s: Cannot deallocate ACS Skip timer", __func__);
}
+ spin_lock(&pHddCtx->acs_skip_lock);
+ vos_mem_free(pHddCtx->last_acs_channel_list);
+ pHddCtx->last_acs_channel_list = NULL;
+ pHddCtx->num_of_channels = 0;
+ spin_unlock(&pHddCtx->acs_skip_lock);
#endif
if (pConfig && !pConfig->enablePowersaveOffload)
@@ -13304,19 +13309,34 @@ void __hdd_wlan_exit(void)
}
#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
+/**
+ * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
+ * @data: pointer to hdd_context_t
+ *
+ * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
+ * Then new ACS request will do a fresh scan without reusing the cached
+ * scan information.
+ *
+ * Return: void
+ */
void hdd_skip_acs_scan_timer_handler(void * data)
{
- hdd_context_t *hdd_ctx = (hdd_context_t *) data;
- hdd_adapter_t *ap_adapter;
+ hdd_context_t *hdd_ctx = (hdd_context_t *) data;
+ hdd_adapter_t *ap_adapter;
- hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip"));
- hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
+ hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip"));
+ hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
+ spin_lock(&hdd_ctx->acs_skip_lock);
+ vos_mem_free(hdd_ctx->last_acs_channel_list);
+ hdd_ctx->last_acs_channel_list = NULL;
+ hdd_ctx->num_of_channels = 0;
+ spin_unlock(&hdd_ctx->acs_skip_lock);
- /* Get first SAP adapter to clear results */
- ap_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP);
- if (!hdd_ctx->hHal || !ap_adapter)
- return;
- sme_ScanFlushResult(hdd_ctx->hHal, ap_adapter->sessionId);
+ /* Get first SAP adapter to clear results */
+ ap_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_SOFTAP);
+ if (!hdd_ctx->hHal || !ap_adapter)
+ return;
+ sme_ScanFlushResult(hdd_ctx->hHal, ap_adapter->sessionId);
}
#endif
@@ -15514,6 +15534,7 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc)
hdd_skip_acs_scan_timer_handler, (void *)pHddCtx);
if (!VOS_IS_STATUS_SUCCESS(status))
hddLog(LOGE, FL("Failed to init ACS Skip timer\n"));
+ spin_lock_init(&pHddCtx->acs_skip_lock);
#endif
#ifdef WLAN_FEATURE_NAN
diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h
index 76c662b7c6c6..324173dd313d 100644
--- a/CORE/SAP/inc/sapApi.h
+++ b/CORE/SAP/inc/sapApi.h
@@ -189,9 +189,7 @@ typedef enum {
eSAP_DFS_NOL_GET, /* Event sent when user need to get the DFS NOL from CNSS */
eSAP_DFS_NOL_SET, /* Event sent when user need to set the DFS NOL to CNSS */
eSAP_DFS_NO_AVAILABLE_CHANNEL, /* No ch available after DFS RADAR detect */
-#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
eSAP_ACS_SCAN_SUCCESS_EVENT,
-#endif
eSAP_ACS_CHANNEL_SELECTED,
eSAP_ECSA_CHANGE_CHAN_IND,
} eSapHddEvent;
@@ -387,6 +385,18 @@ typedef struct sap_ChSelected_s {
} tSap_ChSelectedEvent;
/**
+ * struct tsap_acs_scan_complete_event - acs scan complete event
+ * @status: status of acs scan
+ * @channellist: acs scan channels
+ * @num_of_channels: number of channels
+ */
+struct tsap_acs_scan_complete_event{
+ uint8_t status;
+ uint8_t *channellist;
+ uint8_t num_of_channels;
+};
+
+/**
* struct sap_ch_change_ind - channel change indication
* @new_chan: channel to change
*/
@@ -420,6 +430,7 @@ typedef struct sap_Event_s {
tSap_DfsNolInfo sapDfsNolInfo; /*eSAP_DFS_NOL_XXX */
/*eSAP_ACS_CHANNEL_SELECTED */
tSap_ChSelectedEvent sapChSelected;
+ struct tsap_acs_scan_complete_event sap_acs_scan_comp;
struct sap_ch_change_ind sap_chan_cng_ind;
} sapevt;
} tSap_Event, *tpSap_Event;
diff --git a/CORE/SAP/src/sapApiLinkCntl.c b/CORE/SAP/src/sapApiLinkCntl.c
index 758ce58c9ef5..3944c0847b51 100644
--- a/CORE/SAP/src/sapApiLinkCntl.c
+++ b/CORE/SAP/src/sapApiLinkCntl.c
@@ -260,6 +260,7 @@ WLANSAP_ScanCallback
* the result */
vos_mem_free(psapContext->channelList);
psapContext->channelList = NULL;
+ psapContext->num_of_channel = 0;
}
#endif
@@ -501,6 +502,7 @@ WLANSAP_PreStartBssAcsScanCallback
*/
vos_mem_free(psapContext->channelList);
psapContext->channelList = NULL;
+ psapContext->num_of_channel = 0;
}
#endif
diff --git a/CORE/SAP/src/sapFsm.c b/CORE/SAP/src/sapFsm.c
index e43e3cfb9a20..9e4fcac14c25 100644
--- a/CORE/SAP/src/sapFsm.c
+++ b/CORE/SAP/src/sapFsm.c
@@ -2764,7 +2764,7 @@ sapGotoChannelSel
scanRequest.requestType = eCSR_SCAN_SOFTAP_CHANNEL_RANGE;
sapContext->channelList = channelList;
-
+ sapContext->num_of_channel = numOfChannels;
#endif
/* Set requestType to Full scan */
@@ -2825,6 +2825,7 @@ sapGotoChannelSel
sapContext->channel = sapContext->channelList[0];
vos_mem_free(sapContext->channelList);
sapContext->channelList = NULL;
+ sapContext->num_of_channel = 0;
}
#endif
if (VOS_TRUE == sapDoAcsPreStartBss)
@@ -3155,6 +3156,33 @@ sapGotoDisconnected
return vosStatus;
}
+#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
+/**
+ * sap_handle_acs_scan_event() - handle acs scan event for SAP
+ * @sap_context: ptSapContext
+ * @sap_event: tSap_Event
+ * @status: status of acs scan
+ *
+ * The function is to handle the eSAP_ACS_SCAN_SUCCESS_EVENT event.
+ *
+ * Return: void
+ */
+static void sap_handle_acs_scan_event(ptSapContext sap_context,
+ tSap_Event *sap_event, eSapStatus status)
+{
+ sap_event->sapHddEventCode = eSAP_ACS_SCAN_SUCCESS_EVENT;
+ sap_event->sapevt.sap_acs_scan_comp.status = status;
+ sap_event->sapevt.sap_acs_scan_comp.num_of_channels =
+ sap_context->num_of_channel;
+ sap_event->sapevt.sap_acs_scan_comp.channellist =
+ sap_context->channelList;
+}
+#else
+static void sap_handle_acs_scan_event(ptSapContext sap_context,
+ tSap_Event *sap_event, eSapStatus status)
+{
+}
+#endif
/*==========================================================================
FUNCTION sapSignalHDDevent
@@ -3261,14 +3289,17 @@ sapSignalHDDevent
VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,
"In %s, SAP event callback event = %s : %d", __func__,
"eSAP_DFS event", sapHddevent);
-#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
- case eSAP_ACS_SCAN_SUCCESS_EVENT:
-#endif
sapApAppEvent.sapHddEventCode = sapHddevent;
sapApAppEvent.sapevt.sapStopBssCompleteEvent.status =
- (eSapStatus )context;
+ (eSapStatus )context;
+ break;
+ case eSAP_ACS_SCAN_SUCCESS_EVENT:
+ VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,
+ "In %s, SAP event callback event = %s : %d", __func__,
+ "ACS Scan event", sapHddevent);
+ sap_handle_acs_scan_event(sapContext, &sapApAppEvent,
+ (eSapStatus)context);
break;
-
case eSAP_ACS_CHANNEL_SELECTED:
sapApAppEvent.sapHddEventCode = sapHddevent;
if ( eSAP_STATUS_SUCCESS == (eSapStatus )context)
diff --git a/CORE/SAP/src/sapInternal.h b/CORE/SAP/src/sapInternal.h
index 77ed03e00a97..c5bc6cf86ab1 100644
--- a/CORE/SAP/src/sapInternal.h
+++ b/CORE/SAP/src/sapInternal.h
@@ -246,6 +246,7 @@ typedef struct sSapContext {
v_U32_t nStaAddIeLength;
v_U8_t pStaAddIE[MAX_ASSOC_IND_IE_LEN];
v_U8_t *channelList;
+ uint8_t num_of_channel;
tSapChannelListInfo SapChnlList;
uint16_t vht_channel_width;
uint16_t ch_width_orig;