From 0c1dedb899d3abed5e7e78f31feddcc30d1cc8ea Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Tue, 13 Nov 2018 18:24:20 +0530 Subject: [PATCH] qcacmn: Add support to acquire wake lock during user scan Acquire wakelock to handle the case where APP's send scan to connect. If suspend is received during scan, scan will be aborted and APP will not get scan result and will not connect. eg if PNO is implemented in framework. Fix is to avoid the system suspend by taking the wake-lock during scan. Added INI wake_lock_in_user_scan to control this. The INI is disabled by default. Change-Id: I62fdbbcbc6f049cb4e36e774d5a417600a2dfa86 CRs-Fixed: 2381622 --- os_if/linux/scan/inc/wlan_cfg80211_scan.h | 6 +- os_if/linux/scan/src/wlan_cfg80211_scan.c | 98 +++++++++++++++++-- umac/scan/core/src/wlan_scan_main.h | 2 + umac/scan/dispatcher/inc/wlan_scan_cfg.h | 21 ++++ umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h | 9 ++ umac/scan/dispatcher/src/wlan_scan_ucfg_api.c | 13 +++ 6 files changed, 142 insertions(+), 7 deletions(-) diff --git a/os_if/linux/scan/inc/wlan_cfg80211_scan.h b/os_if/linux/scan/inc/wlan_cfg80211_scan.h index 1634303d16..62be6bc6f0 100644 --- a/os_if/linux/scan/inc/wlan_cfg80211_scan.h +++ b/os_if/linux/scan/inc/wlan_cfg80211_scan.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -45,6 +45,8 @@ #define QCOM_VENDOR_IE_AGE_TYPE 0x100 #define QCOM_VENDOR_IE_AGE_LEN (sizeof(qcom_ie_age) - 2) #define SCAN_DONE_EVENT_BUF_SIZE 4096 +#define SCAN_WAKE_LOCK_CONNECT_DURATION (1 * 1000) /* in msec */ +#define SCAN_WAKE_LOCK_SCAN_DURATION (5 * 1000) /* in msec */ /** * typedef struct qcom_ie_age - age ie @@ -79,12 +81,14 @@ typedef struct { * scan_req_q_lock: Protect scan request queue * req_id: Scan request Id * runtime_pm_lock: Runtime suspend lock + * scan_wake_lock: Scan wake lock */ struct osif_scan_pdev{ qdf_list_t scan_req_q; qdf_mutex_t scan_req_q_lock; wlan_scan_requester req_id; qdf_runtime_lock_t runtime_pm_lock; + qdf_wake_lock_t scan_wake_lock; }; /* diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index d1e5cc2dd6..b4231ec72a 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -38,6 +38,9 @@ #include #endif #include +#ifdef FEATURE_WLAN_DIAG_SUPPORT +#include "host_diag_core_event.h" +#endif static const struct nla_policy scan_policy[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1] = { @@ -864,6 +867,58 @@ nla_put_failure: qdf_mem_free(req); } +/** + * wlan_scan_acquire_wake_lock_timeout() - acquire scan wake lock + * @psoc: psoc ptr + * @scan_wake_lock: Scan wake lock + * @timeout: timeout in ms + * + * Return: void + */ +static inline +void wlan_scan_acquire_wake_lock_timeout(struct wlan_objmgr_psoc *psoc, + qdf_wake_lock_t *scan_wake_lock, + uint32_t timeout) +{ + if (!psoc || !scan_wake_lock) + return; + + if (ucfg_scan_wake_lock_in_user_scan(psoc)) + qdf_wake_lock_timeout_acquire(scan_wake_lock, timeout); +} + + +/** + * wlan_scan_release_wake_lock() - release scan wake lock + * @psoc: psoc ptr + * @scan_wake_lock: Scan wake lock + * + * Return: void + */ +#ifdef FEATURE_WLAN_DIAG_SUPPORT +static inline +void wlan_scan_release_wake_lock(struct wlan_objmgr_psoc *psoc, + qdf_wake_lock_t *scan_wake_lock) +{ + if (!psoc || !scan_wake_lock) + return; + + if (ucfg_scan_wake_lock_in_user_scan(psoc)) + qdf_wake_lock_release(scan_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_SCAN); +} +#else +static inline +void wlan_scan_release_wake_lock(struct wlan_objmgr_psoc *psoc, + qdf_wake_lock_t *scan_wake_lock) +{ + if (!psoc || !scan_wake_lock) + return; + + if (ucfg_scan_wake_lock_in_user_scan(psoc)) + qdf_wake_lock_release(scan_wake_lock, 0); +} +#endif /** * wlan_cfg80211_scan_done_callback() - scan done callback function called after @@ -937,10 +992,26 @@ static void wlan_cfg80211_scan_done_callback( wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); allow_suspend: osif_priv = wlan_pdev_get_ospriv(pdev); - if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) + if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) { + struct wlan_objmgr_psoc *psoc; + qdf_runtime_pm_allow_suspend( &osif_priv->osif_scan->runtime_pm_lock); + psoc = wlan_pdev_get_psoc(pdev); + wlan_scan_release_wake_lock(psoc, + &osif_priv->osif_scan->scan_wake_lock); + /* + * Acquire wakelock to handle the case where APP's tries + * to suspend immediately after the driver gets connect + * request(i.e after scan) from supplicant, this result in + * app's is suspending and not able to process the connect + * request to AP + */ + wlan_scan_acquire_wake_lock_timeout(psoc, + &osif_priv->osif_scan->scan_wake_lock, + SCAN_WAKE_LOCK_CONNECT_DURATION); + } } QDF_STATUS wlan_scan_runtime_pm_init(struct wlan_objmgr_pdev *pdev) @@ -990,9 +1061,10 @@ QDF_STATUS wlan_cfg80211_scan_priv_init(struct wlan_objmgr_pdev *pdev) } /* Initialize the scan request queue */ osif_priv->osif_scan = scan_priv; + scan_priv->req_id = req_id; qdf_list_create(&scan_priv->scan_req_q, WLAN_MAX_SCAN_COUNT); qdf_mutex_create(&scan_priv->scan_req_q_lock); - scan_priv->req_id = req_id; + qdf_wake_lock_create(&scan_priv->scan_wake_lock, "scan_wake_lock"); return QDF_STATUS_SUCCESS; } @@ -1008,11 +1080,12 @@ QDF_STATUS wlan_cfg80211_scan_priv_deinit(struct wlan_objmgr_pdev *pdev) wlan_cfg80211_cleanup_scan_queue(pdev, NULL); scan_priv = osif_priv->osif_scan; - ucfg_scan_unregister_requester(psoc, scan_priv->req_id); - qdf_list_destroy(&scan_priv->scan_req_q); + qdf_wake_lock_destroy(&scan_priv->scan_wake_lock); qdf_mutex_destroy(&scan_priv->scan_req_q_lock); - qdf_mem_free(scan_priv); + qdf_list_destroy(&scan_priv->scan_req_q); + ucfg_scan_unregister_requester(psoc, scan_priv->req_id); osif_priv->osif_scan = NULL; + qdf_mem_free(scan_priv); return QDF_STATUS_SUCCESS; } @@ -1385,6 +1458,16 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, wlan_scan_request_enqueue(pdev, request, params->source, req->scan_req.scan_id); + /* + * Acquire wakelock to handle the case where APP's send scan to connect. + * If suspend is received during scan scan will be aborted and APP will + * not get scan result and not connect. eg if PNO is implemented in + * framework. + */ + wlan_scan_acquire_wake_lock_timeout(psoc, + &osif_priv->osif_scan->scan_wake_lock, + SCAN_WAKE_LOCK_SCAN_DURATION); + qdf_runtime_pm_prevent_suspend( &osif_priv->osif_scan->runtime_pm_lock); @@ -1395,9 +1478,12 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, cfg80211_err("HO is in progress.So defer the scan by informing busy"); wlan_scan_request_dequeue(pdev, scan_id, &request, ¶ms->source, &netdev); - if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) + if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) { qdf_runtime_pm_allow_suspend( &osif_priv->osif_scan->runtime_pm_lock); + wlan_scan_release_wake_lock(psoc, + &osif_priv->osif_scan->scan_wake_lock); + } } ret = qdf_status_to_os_return(qdf_status); diff --git a/umac/scan/core/src/wlan_scan_main.h b/umac/scan/core/src/wlan_scan_main.h index bc4628670b..6a74eb3098 100644 --- a/umac/scan/core/src/wlan_scan_main.h +++ b/umac/scan/core/src/wlan_scan_main.h @@ -279,6 +279,7 @@ struct extscan_def_config { * @active_dwell: default active dwell time * @allow_dfs_chan_in_first_scan: first scan should contain dfs channels or not. * @allow_dfs_chan_in_scan: Scan DFS channels or not. + * @use_wake_lock_in_user_scan: if wake lock will be acquired during user scan * @active_dwell_2g: default active dwell time for 2G channels, if it's not zero * @passive_dwell:default passive dwell time * @max_rest_time: default max rest time @@ -356,6 +357,7 @@ struct scan_default_params { uint32_t active_dwell; bool allow_dfs_chan_in_first_scan; bool allow_dfs_chan_in_scan; + bool use_wake_lock_in_user_scan; uint32_t active_dwell_2g; uint32_t passive_dwell; uint32_t max_rest_time; diff --git a/umac/scan/dispatcher/inc/wlan_scan_cfg.h b/umac/scan/dispatcher/inc/wlan_scan_cfg.h index 04f2275cbd..3c22b13356 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_cfg.h +++ b/umac/scan/dispatcher/inc/wlan_scan_cfg.h @@ -434,6 +434,26 @@ CFG_VALUE_OR_DEFAULT, \ "minimum time spent on home channel") +/* + * + * wake_lock_in_user_scan - use wake lock during user scan + * @Min: 0 + * @Max: 1 + * @Default: 0 + * + * This ini is used to define if wake lock is held used during user scan req + * + * Related: Scan + * + * Usage: Internal/External + * + * + */ +#define CFG_ENABLE_WAKE_LOCK_IN_SCAN CFG_INI_BOOL( \ + "wake_lock_in_user_scan", \ + false, \ + "use wake lock during scan") + /* * * gIdleTimeConc - Data inactivity time in msec. @@ -464,6 +484,7 @@ #define CFG_SCAN_ALL \ CFG(CFG_DROP_BCN_ON_CHANNEL_MISMATCH) \ + CFG(CFG_ENABLE_WAKE_LOCK_IN_SCAN) \ CFG(CFG_ACTIVE_MAX_CHANNEL_TIME) \ CFG(CFG_ENABLE_DFS_SCAN) \ CFG(CFG_INITIAL_NO_DFS_SCAN) \ diff --git a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h index 6c105ba940..d997d248fd 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h @@ -778,6 +778,15 @@ void ucfg_scan_cfg_set_dfs_chan_scan_allowed(struct wlan_objmgr_psoc *psoc, return wlan_scan_cfg_set_dfs_chan_scan_allowed(psoc, dfs_scan_enable); } +/** + * ucfg_scan_wake_lock_in_user_scan() - API to determine if wake lock in user + * scan is used. + * @psoc: pointer to psoc object + * + * Return: true if wake lock in user scan is required + */ +bool ucfg_scan_wake_lock_in_user_scan(struct wlan_objmgr_psoc *psoc); + /** * ucfg_scan_cfg_get_conc_max_resttime() - API to get max rest time * @psoc: pointer to psoc object diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index 7780264533..03398114a6 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -1475,6 +1475,8 @@ wlan_scan_global_init(struct wlan_objmgr_psoc *psoc, !cfg_get(psoc, CFG_INITIAL_NO_DFS_SCAN); scan_obj->scan_def.allow_dfs_chan_in_scan = cfg_get(psoc, CFG_ENABLE_DFS_SCAN); + scan_obj->scan_def.use_wake_lock_in_user_scan = + cfg_get(psoc, CFG_ENABLE_WAKE_LOCK_IN_SCAN); scan_obj->scan_def.active_dwell_2g = cfg_get(psoc, CFG_ACTIVE_MAX_2G_CHANNEL_TIME); scan_obj->scan_def.passive_dwell = @@ -2319,6 +2321,17 @@ bool ucfg_scan_get_bt_activity(struct wlan_objmgr_psoc *psoc) return scan_obj->bt_a2dp_enabled; } +bool ucfg_scan_wake_lock_in_user_scan(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_scan_obj *scan_obj; + + scan_obj = wlan_psoc_get_scan_obj(psoc); + if (!scan_obj) + return false; + + return scan_obj->scan_def.use_wake_lock_in_user_scan; +} + QDF_STATUS ucfg_scan_set_global_config(struct wlan_objmgr_psoc *psoc, enum scan_config config, uint32_t val)