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)