qcacmn: Add support to enable/disable scan with reason code

Adds support to enable/disable scan for psoc/vdev with reason,
so that multiple clients can enable/disable the scan at same time.

Scan will remain disabled till all clients enable it back.

Change-Id: I8d840b24210095accb56ac9a2697ec26e8a5eb17
CRs-Fixed: 2362093
This commit is contained in:
Abhishek Singh 2018-11-21 14:34:49 +05:30 • committed by nshrivas
commit 502095b236
6 changed files with 161 additions and 92 deletions

View file

@ -238,12 +238,12 @@ struct pdev_scan_info {
* struct scan_vdev_obj - scan vdev obj
* @pno_match_evt_received: pno match received
* @pno_in_progress: pno in progress
* @is_vdev_delete_in_progress: flag to indicate if vdev del is in progress
* @scan_disabled: if scan is disabled for this vdev
*/
struct scan_vdev_obj {
bool pno_match_evt_received;
bool pno_in_progress;
bool is_vdev_delete_in_progress;
uint32_t scan_disabled;
};
/**
@ -461,7 +461,7 @@ struct scan_cb {
/**
* struct wlan_scan_obj - scan object definition
* @enable_scan: if scan is enabled
* @scan_disabled: if scan is disabled
* @scan_db: scan cache data base
* @cc_db: pointer of country code data base
* @lock: spin lock
@ -482,7 +482,7 @@ struct scan_cb {
* scan config to event handlers
*/
struct wlan_scan_obj {
bool enable_scan;
uint32_t scan_disabled;
qdf_spinlock_t lock;
qdf_atomic_t scan_ids;
struct scan_dbs scan_db[WLAN_UMAC_MAX_PDEVS];

View file

@ -367,6 +367,44 @@ scm_scan_serialize_callback(struct wlan_serialization_command *cmd,
return status;
}
bool scm_is_scan_allowed(struct wlan_objmgr_vdev *vdev)
{
struct wlan_scan_obj *scan_psoc_obj;
struct scan_vdev_obj *scan_vdev_obj;
if (!vdev) {
scm_err("vdev is NULL");
return false;
}
scan_psoc_obj = wlan_vdev_get_scan_obj(vdev);
if (!scan_psoc_obj) {
scm_err("Couldn't find scan psoc object");
return false;
}
if (scan_psoc_obj->scan_disabled) {
scm_err_rl("scan disabled %x, for psoc",
scan_psoc_obj->scan_disabled);
return false;
}
scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
if (!scan_vdev_obj) {
scm_err("Couldn't find scan vdev object");
return false;
}
if (scan_vdev_obj->scan_disabled) {
scm_err_rl("scan disabled %x on vdev_id:%d",
scan_vdev_obj->scan_disabled,
wlan_vdev_get_id(vdev));
return false;
}
return true;
}
QDF_STATUS
scm_scan_start_req(struct scheduler_msg *msg)
{
@ -374,7 +412,6 @@ scm_scan_start_req(struct scheduler_msg *msg)
enum wlan_serialization_status ser_cmd_status;
struct scan_start_request *req = NULL;
struct wlan_scan_obj *scan_obj;
struct scan_vdev_obj *scan_vdev_priv_obj;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!msg) {
@ -389,29 +426,16 @@ scm_scan_start_req(struct scheduler_msg *msg)
}
req = msg->bodyptr;
scan_obj = wlan_vdev_get_scan_obj(req->vdev);
if (!scan_obj) {
scm_debug("Couldn't find scan object");
status = QDF_STATUS_E_NULL_VALUE;
goto err;
}
if (!scan_obj->enable_scan) {
if (!scm_is_scan_allowed(req->vdev)) {
scm_err("scan disabled, rejecting the scan req");
status = QDF_STATUS_E_NULL_VALUE;
goto err;
}
scan_vdev_priv_obj = wlan_get_vdev_scan_obj(req->vdev);
if (!scan_vdev_priv_obj) {
scm_debug("Couldn't find scan priv object");
status = QDF_STATUS_E_NULL_VALUE;
goto err;
}
if (scan_vdev_priv_obj->is_vdev_delete_in_progress) {
scm_err("Can't allow scan on vdev_id:%d",
wlan_vdev_get_id(req->vdev));
scan_obj = wlan_vdev_get_scan_obj(req->vdev);
if (!scan_obj) {
scm_debug("Couldn't find scan object");
status = QDF_STATUS_E_NULL_VALUE;
goto err;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2018 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
@ -44,6 +44,14 @@ struct scan_event_listeners {
struct cb_handler cb[MAX_SCAN_EVENT_LISTENERS];
};
/**
* scm_is_scan_allowed() - check if scan is allowed
* @vdev: vdev for which scan allowed is check
*
* Return: true if scan is allowed else false
*/
bool scm_is_scan_allowed(struct wlan_objmgr_vdev *vdev);
/**
* scm_scan_start_req() - scan start req core api
* @msg: scheduler message object containing start scan req params

View file

@ -577,6 +577,19 @@ struct scan_filter {
struct qdf_mac_addr bssid_hint;
};
/**
* enum scan_disable_reason - scan enable/disable reason
* @REASON_SUSPEND: reason is suspend
* @REASON_SYSTEM_DOWN: reason is system going down
* @REASON_USER_SPACE: reason is user space initiated
* @REASON_VDEV_DOWN: reason is vdev going down
*/
enum scan_disable_reason {
REASON_SUSPEND = 0x1,
REASON_SYSTEM_DOWN = 0x2,
REASON_USER_SPACE = 0x4,
REASON_VDEV_DOWN = 0x8,
};
/**
* enum scan_priority - scan priority definitions

View file

@ -174,21 +174,46 @@ QDF_STATUS
ucfg_scan_start(struct scan_start_request *req);
/**
* ucfg_scan_set_enable() - Public API to disable/enable scans
* ucfg_scan_set_psoc_enable() - Public API to enable scans for psoc
* @psoc: psoc on which scans need to be disabled
* @enable: enable scan if true disable is false
* @reason: reason for enable/disabled
*
* Return: QDF_STATUS.
*/
QDF_STATUS ucfg_scan_set_enable(struct wlan_objmgr_psoc *psoc, bool enable);
QDF_STATUS ucfg_scan_psoc_set_enable(struct wlan_objmgr_psoc *psoc,
enum scan_disable_reason reason);
/**
* ucfg_scan_get_enable() - Public API to get if scan is enabled or disabled
* @psoc: psoc on which scans status need to be checked
* ucfg_scan_psoc_set_disable() - Public API to disable scans for psoc
* @psoc: psoc on which scans need to be disabled
* @reason: reason for enable/disabled
*
* Return: true if enabled else false.
* Return: QDF_STATUS.
*/
bool ucfg_scan_get_enable(struct wlan_objmgr_psoc *psoc);
QDF_STATUS ucfg_scan_psoc_set_disable(struct wlan_objmgr_psoc *psoc,
enum scan_disable_reason reason);
/**
* ucfg_scan_vdev_set_enable() - Public API to enable scans for vdev
* @psoc: psoc on which scans need to be disabled
* @reason: reason for enable/disabled
*
* Return: QDF_STATUS.
*/
QDF_STATUS ucfg_scan_vdev_set_enable(struct wlan_objmgr_vdev *vdev,
enum scan_disable_reason reason);
/**
* ucfg_scan_vdev_set_disable() - Public API to disable scans for vdev
* @psoc: psoc on which scans need to be disabled
* @reason: reason for enable/disabled
*
* Return: QDF_STATUS.
*/
QDF_STATUS ucfg_scan_vdev_set_disable(struct wlan_objmgr_vdev *vdev,
enum scan_disable_reason reason);
/**
* ucfg_scan_set_miracast() - Public API to disable/enable miracast flag
@ -614,21 +639,6 @@ void ucfg_scan_set_bt_activity(struct wlan_objmgr_psoc *psoc,
*/
bool ucfg_scan_get_bt_activity(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_scan_set_vdev_del_in_progress() - API to mark vdev delete in progress
* @vdev: pointer to vdev object
*
* Return: none
*/
void ucfg_scan_set_vdev_del_in_progress(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_scan_clear_vdev_del_in_progress() - API to reset vdev delete in progress
* @vdev: pointer to vdev object
*
* Return: none
*/
void ucfg_scan_clear_vdev_del_in_progress(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_scan_cfg_set_active_dwelltime() - API to set scan active dwelltime
* @psoc: pointer to psoc object

View file

@ -879,6 +879,12 @@ ucfg_scan_start(struct scan_start_request *req)
return QDF_STATUS_E_NULL_VALUE;
}
if (!scm_is_scan_allowed(req->vdev)) {
scm_err("scan disabled, rejecting the scan req");
scm_scan_free_scan_request_mem(req);
return QDF_STATUS_E_AGAIN;
}
scan_obj = wlan_pdev_get_scan_obj(pdev);
if (!scan_obj) {
scm_err("Failed to get scan object");
@ -886,12 +892,6 @@ ucfg_scan_start(struct scan_start_request *req)
return QDF_STATUS_E_NULL_VALUE;
}
if (!scan_obj->enable_scan) {
scm_err("scan disabled, rejecting the scan req");
scm_scan_free_scan_request_mem(req);
return QDF_STATUS_E_AGAIN;
}
scm_debug("reqid: %d, scanid: %d, vdevid: %d",
req->scan_req.scan_req_id, req->scan_req.scan_id,
req->scan_req.vdev_id);
@ -932,7 +932,8 @@ ucfg_scan_start(struct scan_start_request *req)
return status;
}
QDF_STATUS ucfg_scan_set_enable(struct wlan_objmgr_psoc *psoc, bool enable)
QDF_STATUS ucfg_scan_psoc_set_enable(struct wlan_objmgr_psoc *psoc,
enum scan_disable_reason reason)
{
struct wlan_scan_obj *scan_obj;
@ -941,24 +942,69 @@ QDF_STATUS ucfg_scan_set_enable(struct wlan_objmgr_psoc *psoc, bool enable)
scm_err("Failed to get scan object");
return QDF_STATUS_E_NULL_VALUE;
}
scan_obj->enable_scan = enable;
scm_debug("set enable_scan to %d", scan_obj->enable_scan);
scan_obj->scan_disabled &= ~reason;
scm_debug("Psoc scan_disabled %x", scan_obj->scan_disabled);
return QDF_STATUS_SUCCESS;
}
bool ucfg_scan_get_enable(struct wlan_objmgr_psoc *psoc)
QDF_STATUS ucfg_scan_psoc_set_disable(struct wlan_objmgr_psoc *psoc,
enum scan_disable_reason reason)
{
struct wlan_scan_obj *scan_obj;
scan_obj = wlan_psoc_get_scan_obj(psoc);
if (!scan_obj) {
scm_err("Failed to get scan object");
return false;
return QDF_STATUS_E_NULL_VALUE;
}
return scan_obj->enable_scan;
scan_obj->scan_disabled |= reason;
scm_debug("Psoc scan_disabled %x", scan_obj->scan_disabled);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ucfg_scan_vdev_set_enable(struct wlan_objmgr_vdev *vdev,
enum scan_disable_reason reason)
{
struct scan_vdev_obj *scan_vdev_obj;
scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
if (!scan_vdev_obj) {
scm_err("null scan_vdev_obj");
return QDF_STATUS_E_NULL_VALUE;
}
scan_vdev_obj->scan_disabled &= ~reason;
scm_debug("Vdev scan_disabled %x", scan_vdev_obj->scan_disabled);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ucfg_scan_vdev_set_disable(struct wlan_objmgr_vdev *vdev,
enum scan_disable_reason reason)
{
struct scan_vdev_obj *scan_vdev_obj;
scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
if (!scan_vdev_obj) {
scm_err("null scan_vdev_obj");
return QDF_STATUS_E_NULL_VALUE;
}
scan_vdev_obj->scan_disabled |= reason;
scm_debug("Vdev scan_disabled %x", scan_vdev_obj->scan_disabled);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ucfg_scan_set_miracast(
struct wlan_objmgr_psoc *psoc, bool enable)
{
@ -1359,7 +1405,7 @@ static QDF_STATUS
wlan_scan_global_init(struct wlan_objmgr_psoc *psoc,
struct wlan_scan_obj *scan_obj)
{
scan_obj->enable_scan = true;
scan_obj->scan_disabled = 0;
scan_obj->drop_bcn_on_chan_mismatch = true;
scan_obj->disable_timeout = false;
scan_obj->scan_def.active_dwell =
@ -1980,7 +2026,7 @@ ucfg_scan_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg)
QDF_STATUS status = QDF_STATUS_SUCCESS;
int i;
ucfg_scan_set_enable(psoc, false);
ucfg_scan_psoc_set_disable(psoc, REASON_SUSPEND);
/* Check all pdev */
for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) {
pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_SCAN_ID);
@ -2002,7 +2048,7 @@ ucfg_scan_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg)
static QDF_STATUS
ucfg_scan_resume_handler(struct wlan_objmgr_psoc *psoc, void *arg)
{
ucfg_scan_set_enable(psoc, true);
ucfg_scan_psoc_set_enable(psoc, REASON_SUSPEND);
return QDF_STATUS_SUCCESS;
}
@ -2229,38 +2275,6 @@ bool ucfg_scan_get_bt_activity(struct wlan_objmgr_psoc *psoc)
return scan_obj->bt_a2dp_enabled;
}
void ucfg_scan_set_vdev_del_in_progress(struct wlan_objmgr_vdev *vdev)
{
struct scan_vdev_obj *scan_vdev_obj;
if (!vdev) {
scm_err("invalid vdev");
return;
}
scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
if (!scan_vdev_obj) {
scm_err("null scan_vdev_obj");
return;
}
scan_vdev_obj->is_vdev_delete_in_progress = true;
}
void ucfg_scan_clear_vdev_del_in_progress(struct wlan_objmgr_vdev *vdev)
{
struct scan_vdev_obj *scan_vdev_obj;
if (!vdev) {
scm_err("invalid vdev");
return;
}
scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
if (!scan_vdev_obj) {
scm_err("null scan_vdev_obj");
return;
}
scan_vdev_obj->is_vdev_delete_in_progress = false;
}
QDF_STATUS
ucfg_scan_set_global_config(struct wlan_objmgr_psoc *psoc,
enum scan_config config, uint32_t val)