From f95b9e4248554c27ab27fd0ec9169f3621186452 Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Tue, 25 Apr 2017 12:12:01 +0530 Subject: [PATCH] qcacmn: Add wait for cancel scan on pdev and vdev Add cancel scan sync api which will wait for scan to be aborted on pdev or vdev. Change-Id: Ie02eb981154856cda38ef70f42fdfcf82bb88961 CRs-Fixed: 2038092 --- os_if/linux/scan/inc/wlan_cfg80211_scan.h | 4 +- os_if/linux/scan/src/wlan_cfg80211_scan.c | 14 ++-- .../dispatcher/inc/wlan_scan_public_structs.h | 3 + umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h | 13 ++++ umac/scan/dispatcher/src/wlan_scan_ucfg_api.c | 73 ++++++++++++++++++- 5 files changed, 100 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 16c838bf211c..b517d83892e3 100644 --- a/os_if/linux/scan/inc/wlan_cfg80211_scan.h +++ b/os_if/linux/scan/inc/wlan_cfg80211_scan.h @@ -216,6 +216,7 @@ int wlan_cfg80211_abort_scan(struct wlan_objmgr_pdev *pdev); * @pdev_id: pdev id * @vdev_id: vdev id * @scan_id: scan id + * @sync: if wait for scan complete is required * * Generic API to abort scans * @@ -224,7 +225,8 @@ int wlan_cfg80211_abort_scan(struct wlan_objmgr_pdev *pdev); QDF_STATUS wlan_abort_scan(struct wlan_objmgr_pdev *pdev, uint32_t pdev_id, uint32_t vdev_id, - wlan_scan_id scan_id); + wlan_scan_id scan_id, + bool sync); /** * wlan_cfg80211_cleanup_scan_queue() - remove entries in scan queue diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index eac5daf29a14..5d404d2349c5 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -216,7 +216,7 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev, SCAN_NOT_IN_PROGRESS) { status = wlan_abort_scan(pdev, wlan_objmgr_pdev_get_pdev_id(pdev), - INVAL_VDEV_ID, INVAL_SCAN_ID); + INVAL_VDEV_ID, INVAL_SCAN_ID, true); if (QDF_IS_STATUS_ERROR(status)) { cfg80211_err("aborting the existing scan is unsuccessful"); wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); @@ -1118,7 +1118,7 @@ static int wlan_get_scanid(struct wlan_objmgr_pdev *pdev, QDF_STATUS wlan_abort_scan(struct wlan_objmgr_pdev *pdev, uint32_t pdev_id, uint32_t vdev_id, - wlan_scan_id scan_id) + wlan_scan_id scan_id, bool sync) { struct scan_cancel_request *req; struct pdev_osif_priv *osif_ctx; @@ -1163,7 +1163,11 @@ QDF_STATUS wlan_abort_scan(struct wlan_objmgr_pdev *pdev, req->cancel_req.req_type = WLAN_SCAN_CANCEL_PDEV_ALL; else req->cancel_req.req_type = WLAN_SCAN_CANCEL_VDEV_ALL; - status = ucfg_scan_cancel(req); + + if (sync) + status = ucfg_scan_cancel_sync(req); + else + status = ucfg_scan_cancel(req); if (QDF_IS_STATUS_ERROR(status)) cfg80211_err("Cancel scan request failed"); @@ -1181,7 +1185,7 @@ int wlan_cfg80211_abort_scan(struct wlan_objmgr_pdev *pdev) if (ucfg_scan_get_pdev_status(pdev) != SCAN_NOT_IN_PROGRESS) wlan_abort_scan(pdev, pdev_id, - INVAL_VDEV_ID, INVAL_SCAN_ID); + INVAL_VDEV_ID, INVAL_SCAN_ID, true); return 0; } @@ -1211,7 +1215,7 @@ int wlan_vendor_abort_scan(struct wlan_objmgr_pdev *pdev, if (ucfg_scan_get_pdev_status(pdev) != SCAN_NOT_IN_PROGRESS) wlan_abort_scan(pdev, pdev_id, - INVAL_VDEV_ID, scan_id); + INVAL_VDEV_ID, scan_id, true); } return 0; } diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index c115386475eb..7b28d407a792 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -46,6 +46,9 @@ typedef uint32_t wlan_scan_id; #define SCM_BSS_CAP_VALUE_UAPSD 1 #define SCM_BSS_CAP_VALUE_5GHZ 2 +#define SCM_CANCEL_SCAN_WAIT_TIME 50 +#define SCM_CANCEL_SCAN_WAIT_ITERATION 100 + #define BURST_SCAN_MAX_NUM_OFFCHANNELS 3 #define P2P_SCAN_MAX_BURST_DURATION 180 /* Increase dwell time for P2P search in ms */ diff --git a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h index 503c566ae5a1..401057b1d872 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h @@ -183,6 +183,19 @@ ucfg_scan_start(struct scan_start_request *req); QDF_STATUS ucfg_scan_cancel(struct scan_cancel_request *req); +/** + * ucfg_scan_cancel_sync() - Public API to stop a scan and wait + * till all scan are completed + * @req: stop scan request params + * + * The Public API to stop a scan and wait + * till all scan are completed + * + * Return: 0 for success or error code. + */ +QDF_STATUS +ucfg_scan_cancel_sync(struct scan_cancel_request *req); + /** * ucfg_scan_get_result() - The Public API to get scan results * @pdev: pdev info diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index 6cdb017802f9..09ab0877e11c 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -401,6 +401,77 @@ ucfg_scan_cancel(struct scan_cancel_request *req) return status; } +QDF_STATUS +ucfg_scan_cancel_sync(struct scan_cancel_request *req) +{ + QDF_STATUS status; + bool cancel_vdev = false, cancel_pdev = false; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_pdev *pdev; + uint32_t max_wait_iterations = SCM_CANCEL_SCAN_WAIT_ITERATION; + qdf_event_t cancel_scan_event; + + if (!req || !req->vdev) { + scm_err("vdev: %p, req: %p", req->vdev, req); + if (req) + qdf_mem_free(req); + return QDF_STATUS_E_NULL_VALUE; + } + + if (req->cancel_req.req_type == + WLAN_SCAN_CANCEL_PDEV_ALL) + cancel_pdev = true; + else if (req->cancel_req.req_type == + WLAN_SCAN_CANCEL_VDEV_ALL) + cancel_vdev = true; + + vdev = req->vdev; + status = ucfg_scan_cancel(req); + if (QDF_IS_STATUS_ERROR(status)) { + scm_err("failed to post to QDF_MODULE_ID_OS_IF"); + return status; + } + + /* + * If cancel req is to cancel all scan of pdev or vdev + * wait untill all scan of pdev or vdev get cancelled + */ + qdf_event_create(&cancel_scan_event); + qdf_event_reset(&cancel_scan_event); + + if (cancel_pdev) { + wlan_vdev_obj_lock(vdev); + pdev = wlan_vdev_get_pdev(vdev); + wlan_vdev_obj_unlock(vdev); + while ((ucfg_scan_get_pdev_status(pdev) != + SCAN_NOT_IN_PROGRESS) && max_wait_iterations) { + scm_debug("wait for all pdev scan to get complete"); + qdf_wait_single_event(&cancel_scan_event, + qdf_system_msecs_to_ticks( + SCM_CANCEL_SCAN_WAIT_TIME)); + max_wait_iterations--; + } + } else if (cancel_vdev) { + while ((ucfg_scan_get_vdev_status(vdev) != + SCAN_NOT_IN_PROGRESS) && max_wait_iterations) { + scm_debug("wait for all vdev scan to get complete"); + qdf_wait_single_event(&cancel_scan_event, + qdf_system_msecs_to_ticks( + SCM_CANCEL_SCAN_WAIT_TIME)); + max_wait_iterations--; + } + } + + qdf_event_destroy(&cancel_scan_event); + + if (!max_wait_iterations) { + scm_err("Failed to wait for scans to get complete"); + return QDF_STATUS_E_TIMEOUT; + } + + return status; +} + wlan_scan_requester ucfg_scan_register_requester(struct wlan_objmgr_psoc *psoc, uint8_t *name, scan_event_handler event_cb, void *arg) @@ -896,7 +967,7 @@ ucfg_scan_get_pdev_status(struct wlan_objmgr_pdev *pdev) if (!pdev) { scm_err("null pdev"); - return QDF_STATUS_E_NULL_VALUE; + return SCAN_NOT_IN_PROGRESS; } status = wlan_serialization_pdev_scan_status(pdev);