qcacld-3.0: Implement CBS for EasyMesh
Implement the continuous background scan for EasyMesh. Change-Id: I2607474d5663f21b4d740316ae407bf1398a8ef7 CRs-Fixed: 3095580
This commit is contained in:

committed by
Madan Koyyalamudi

parent
764df553b9
commit
813660e27f
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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 above
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <wlan_reg_services_api.h>
|
||||
#include <wlan_mlme_api.h>
|
||||
#include <ieee80211_external.h>
|
||||
#include <wlan_cfg80211_scan.h>
|
||||
|
||||
/**
|
||||
* struct son_mlme_deliver_cbs - son mlme deliver callbacks
|
||||
@@ -36,6 +37,9 @@ struct son_mlme_deliver_cbs {
|
||||
|
||||
static struct son_mlme_deliver_cbs g_son_mlme_deliver_cbs;
|
||||
|
||||
static struct son_cbs *g_son_cbs[WLAN_MAX_VDEVS];
|
||||
static qdf_spinlock_t g_cbs_lock;
|
||||
|
||||
QDF_STATUS
|
||||
wlan_son_register_mlme_deliver_cb(struct wlan_objmgr_psoc *psoc,
|
||||
mlme_deliver_cb cb,
|
||||
@@ -614,3 +618,648 @@ int wlan_son_anqp_frame(struct wlan_objmgr_vdev *vdev, int subtype,
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wlan_son_deliver_cbs(struct wlan_objmgr_vdev *vdev,
|
||||
wlan_cbs_event_type type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wlan_son_deliver_mlme_event(vdev,
|
||||
NULL,
|
||||
MLME_EVENT_CBS_STATUS,
|
||||
&type);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wlan_son_deliver_cbs_completed(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
return wlan_son_deliver_cbs(vdev, CBS_COMPLETE);
|
||||
}
|
||||
|
||||
static int wlan_son_deliver_cbs_cancelled(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
return wlan_son_deliver_cbs(vdev, CBS_CANCELLED);
|
||||
}
|
||||
|
||||
static void
|
||||
wlan_son_cbs_set_state(struct son_cbs *cbs, enum son_cbs_state state)
|
||||
{
|
||||
qdf_debug("Change State CBS OLD[%d] --> NEW[%d]",
|
||||
cbs->cbs_state, state);
|
||||
cbs->cbs_state = state;
|
||||
}
|
||||
|
||||
static enum
|
||||
son_cbs_state wlan_son_cbs_get_state(struct son_cbs *cbs)
|
||||
{
|
||||
return cbs->cbs_state;
|
||||
}
|
||||
|
||||
static void
|
||||
wlan_son_cbs_init_dwell_params(struct son_cbs *cbs,
|
||||
int dwell_split_time,
|
||||
int dwell_rest_time)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!cbs || !cbs->vdev)
|
||||
return;
|
||||
qdf_debug("dwell_split_time %d, dwell_rest_time %d",
|
||||
dwell_split_time, dwell_rest_time);
|
||||
qdf_debug("vdev_id: %d\n", wlan_vdev_get_id(cbs->vdev));
|
||||
|
||||
switch (dwell_split_time) {
|
||||
case CBS_DWELL_TIME_10MS:
|
||||
cbs->max_arr_size_used = 10;
|
||||
cbs->dwell_split_cnt = cbs->max_arr_size_used - 1;
|
||||
cbs->max_dwell_split_cnt = cbs->max_arr_size_used - 1;
|
||||
for (i = 0; i < cbs->max_arr_size_used; i++)
|
||||
cbs->scan_dwell_rest[i] = dwell_rest_time;
|
||||
for (i = 0; i < cbs->max_arr_size_used; i++)
|
||||
cbs->scan_offset[i] = i * dwell_split_time;
|
||||
break;
|
||||
case CBS_DWELL_TIME_25MS:
|
||||
cbs->max_arr_size_used = 8;
|
||||
cbs->dwell_split_cnt = cbs->max_arr_size_used - 1;
|
||||
cbs->max_dwell_split_cnt = cbs->max_arr_size_used - 1;
|
||||
if (dwell_rest_time % TOTAL_DWELL_TIME == 0) {
|
||||
cbs->scan_dwell_rest[0] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[1] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[2] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[3] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[4] = dwell_rest_time +
|
||||
TOTAL_DWELL_TIME -
|
||||
DEFAULT_BEACON_INTERVAL;
|
||||
cbs->scan_dwell_rest[5] = dwell_rest_time +
|
||||
TOTAL_DWELL_TIME -
|
||||
DEFAULT_BEACON_INTERVAL;
|
||||
cbs->scan_dwell_rest[6] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[7] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[8] = 0;
|
||||
cbs->scan_dwell_rest[9] = 0;
|
||||
cbs->scan_offset[0] = 0;
|
||||
cbs->scan_offset[1] = 0;
|
||||
cbs->scan_offset[2] = dwell_split_time;
|
||||
cbs->scan_offset[3] = dwell_split_time;
|
||||
cbs->scan_offset[4] = 2 * dwell_split_time;
|
||||
cbs->scan_offset[5] = 2 * dwell_split_time;
|
||||
cbs->scan_offset[6] = 3 * dwell_split_time;
|
||||
cbs->scan_offset[7] = 3 * dwell_split_time;
|
||||
cbs->scan_offset[8] = 0;
|
||||
cbs->scan_offset[9] = 0;
|
||||
} else {
|
||||
for (i = 0; i < cbs->max_arr_size_used - 1; i++)
|
||||
cbs->scan_dwell_rest[i] = dwell_rest_time;
|
||||
|
||||
cbs->scan_dwell_rest[8] = 0;
|
||||
cbs->scan_dwell_rest[9] = 0;
|
||||
cbs->scan_offset[0] = 0;
|
||||
cbs->scan_offset[1] = dwell_split_time;
|
||||
cbs->scan_offset[2] = 2 * dwell_split_time;
|
||||
cbs->scan_offset[3] = 3 * dwell_split_time;
|
||||
cbs->scan_offset[4] = 0;
|
||||
cbs->scan_offset[5] = dwell_split_time;
|
||||
cbs->scan_offset[6] = 2 * dwell_split_time;
|
||||
cbs->scan_offset[7] = 3 * dwell_split_time;
|
||||
cbs->scan_offset[8] = 0;
|
||||
cbs->scan_offset[9] = 0;
|
||||
}
|
||||
break;
|
||||
case CBS_DWELL_TIME_50MS:
|
||||
cbs->max_arr_size_used = 4;
|
||||
cbs->dwell_split_cnt = cbs->max_arr_size_used - 1;
|
||||
cbs->max_dwell_split_cnt = cbs->max_arr_size_used - 1;
|
||||
if (dwell_rest_time % TOTAL_DWELL_TIME == 0) {
|
||||
cbs->scan_dwell_rest[0] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[1] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[2] = dwell_rest_time +
|
||||
TOTAL_DWELL_TIME -
|
||||
DEFAULT_BEACON_INTERVAL;
|
||||
cbs->scan_dwell_rest[3] = dwell_rest_time +
|
||||
TOTAL_DWELL_TIME -
|
||||
DEFAULT_BEACON_INTERVAL;
|
||||
cbs->scan_dwell_rest[4] = 0;
|
||||
cbs->scan_dwell_rest[5] = 0;
|
||||
cbs->scan_dwell_rest[6] = 0;
|
||||
cbs->scan_dwell_rest[7] = 0;
|
||||
cbs->scan_dwell_rest[8] = 0;
|
||||
cbs->scan_dwell_rest[9] = 0;
|
||||
cbs->scan_offset[0] = 0;
|
||||
cbs->scan_offset[1] = 0;
|
||||
cbs->scan_offset[2] = dwell_split_time;
|
||||
cbs->scan_offset[3] = dwell_split_time;
|
||||
cbs->scan_offset[4] = 0;
|
||||
cbs->scan_offset[5] = 0;
|
||||
cbs->scan_offset[6] = 0;
|
||||
cbs->scan_offset[7] = 0;
|
||||
cbs->scan_offset[8] = 0;
|
||||
cbs->scan_offset[9] = 0;
|
||||
} else {
|
||||
cbs->scan_dwell_rest[0] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[1] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[2] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[3] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[4] = 0;
|
||||
cbs->scan_dwell_rest[5] = 0;
|
||||
cbs->scan_dwell_rest[6] = 0;
|
||||
cbs->scan_dwell_rest[7] = 0;
|
||||
cbs->scan_dwell_rest[8] = 0;
|
||||
cbs->scan_dwell_rest[9] = 0;
|
||||
cbs->scan_offset[0] = 0;
|
||||
cbs->scan_offset[1] = dwell_split_time;
|
||||
cbs->scan_offset[2] = 0;
|
||||
cbs->scan_offset[3] = dwell_split_time;
|
||||
cbs->scan_offset[4] = 0;
|
||||
cbs->scan_offset[5] = 0;
|
||||
cbs->scan_offset[6] = 0;
|
||||
cbs->scan_offset[7] = 0;
|
||||
cbs->scan_offset[8] = 0;
|
||||
cbs->scan_offset[9] = 0;
|
||||
}
|
||||
break;
|
||||
case CBS_DWELL_TIME_75MS:
|
||||
cbs->max_arr_size_used = 4;
|
||||
cbs->dwell_split_cnt = cbs->max_arr_size_used - 1;
|
||||
cbs->max_dwell_split_cnt = cbs->max_arr_size_used - 1;
|
||||
if (dwell_rest_time % TOTAL_DWELL_TIME == 0) {
|
||||
cbs->scan_dwell_rest[0] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[1] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[2] = dwell_rest_time +
|
||||
TOTAL_DWELL_TIME -
|
||||
DEFAULT_BEACON_INTERVAL;
|
||||
cbs->scan_dwell_rest[3] = dwell_rest_time +
|
||||
TOTAL_DWELL_TIME -
|
||||
DEFAULT_BEACON_INTERVAL;
|
||||
cbs->scan_dwell_rest[4] = 0;
|
||||
cbs->scan_dwell_rest[5] = 0;
|
||||
cbs->scan_dwell_rest[6] = 0;
|
||||
cbs->scan_dwell_rest[7] = 0;
|
||||
cbs->scan_dwell_rest[8] = 0;
|
||||
cbs->scan_dwell_rest[9] = 0;
|
||||
cbs->scan_offset[0] = 0;
|
||||
cbs->scan_offset[1] = 0;
|
||||
cbs->scan_offset[2] = DEFAULT_BEACON_INTERVAL -
|
||||
dwell_split_time;
|
||||
cbs->scan_offset[3] = DEFAULT_BEACON_INTERVAL -
|
||||
dwell_split_time;
|
||||
cbs->scan_offset[4] = 0;
|
||||
cbs->scan_offset[5] = 0;
|
||||
cbs->scan_offset[6] = 0;
|
||||
cbs->scan_offset[7] = 0;
|
||||
cbs->scan_offset[8] = 0;
|
||||
cbs->scan_offset[9] = 0;
|
||||
} else {
|
||||
cbs->scan_dwell_rest[0] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[1] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[2] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[3] = dwell_rest_time;
|
||||
cbs->scan_dwell_rest[4] = 0;
|
||||
cbs->scan_dwell_rest[5] = 0;
|
||||
cbs->scan_dwell_rest[6] = 0;
|
||||
cbs->scan_dwell_rest[7] = 0;
|
||||
cbs->scan_dwell_rest[8] = 0;
|
||||
cbs->scan_dwell_rest[9] = 0;
|
||||
cbs->scan_offset[0] = 0;
|
||||
cbs->scan_offset[1] = DEFAULT_BEACON_INTERVAL -
|
||||
dwell_split_time;
|
||||
cbs->scan_offset[2] = 0;
|
||||
cbs->scan_offset[3] = DEFAULT_BEACON_INTERVAL -
|
||||
dwell_split_time;
|
||||
cbs->scan_offset[4] = 0;
|
||||
cbs->scan_offset[5] = 0;
|
||||
cbs->scan_offset[6] = 0;
|
||||
cbs->scan_offset[7] = 0;
|
||||
cbs->scan_offset[8] = 0;
|
||||
cbs->scan_offset[9] = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qdf_err("Dwell time not supported\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int wlan_son_cbs_start(struct son_cbs *cbs)
|
||||
{
|
||||
struct scan_start_request *req;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
QDF_STATUS status;
|
||||
|
||||
psoc = wlan_vdev_get_psoc(cbs->vdev);
|
||||
if (!psoc) {
|
||||
qdf_err("invalid psoc");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req = qdf_mem_malloc(sizeof(*req));
|
||||
if (!req) {
|
||||
qdf_err("failed to malloc");
|
||||
return -ENOMEM;
|
||||
}
|
||||
qdf_mem_copy(req, &cbs->scan_params, sizeof(*req));
|
||||
|
||||
cbs->cbs_scan_id = ucfg_scan_get_scan_id(psoc);
|
||||
req->scan_req.scan_id = cbs->cbs_scan_id;
|
||||
qdf_debug("vdev_id: %d req->scan_req.scan_id: %u",
|
||||
wlan_vdev_get_id(cbs->vdev), req->scan_req.scan_id);
|
||||
|
||||
status = ucfg_scan_start(req);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_err("failed to start cbs");
|
||||
wlan_son_deliver_cbs_cancelled(cbs->vdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qdf_debug("cbs start");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wlan_son_cbs_stop(struct son_cbs *cbs)
|
||||
{
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
QDF_STATUS status;
|
||||
|
||||
pdev = wlan_vdev_get_pdev(cbs->vdev);
|
||||
if (!pdev) {
|
||||
qdf_err("invalid pdev");
|
||||
return -EINVAL;
|
||||
}
|
||||
qdf_debug("vdev_id: %d", wlan_vdev_get_id(cbs->vdev));
|
||||
|
||||
if (ucfg_scan_get_pdev_status(pdev) != SCAN_NOT_IN_PROGRESS) {
|
||||
qdf_info("cbs_scan_id: %u abort scan", cbs->cbs_scan_id);
|
||||
status = wlan_abort_scan(pdev,
|
||||
wlan_objmgr_pdev_get_pdev_id(pdev),
|
||||
cbs->vdev->vdev_objmgr.vdev_id,
|
||||
cbs->cbs_scan_id,
|
||||
true);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_err("failed to abort cbs");
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wlan_cbs_timer_handler(void *arg)
|
||||
{
|
||||
struct son_cbs *cbs = (struct son_cbs *)arg;
|
||||
enum son_cbs_state state;
|
||||
|
||||
state = wlan_son_cbs_get_state(cbs);
|
||||
qdf_debug("state: %d", state);
|
||||
if (state == CBS_REST) {
|
||||
qdf_debug("vdev_id: %d dwell_split_cnt: %d",
|
||||
wlan_vdev_get_id(cbs->vdev),
|
||||
cbs->dwell_split_cnt);
|
||||
qdf_spin_lock_bh(&g_cbs_lock);
|
||||
wlan_son_cbs_set_state(cbs, CBS_SCAN);
|
||||
cbs->dwell_split_cnt--;
|
||||
wlan_son_cbs_start(cbs);
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
} else if (state == CBS_WAIT) {
|
||||
wlan_son_cbs_enable(cbs->vdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int wlan_cbs_iterate(struct son_cbs *cbs)
|
||||
{
|
||||
int offset_array_idx;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
|
||||
if (!cbs || !cbs->vdev)
|
||||
return -EINVAL;
|
||||
qdf_spin_lock_bh(&g_cbs_lock);
|
||||
qdf_debug("dwell_split_cnt: %d", cbs->dwell_split_cnt);
|
||||
if (cbs->dwell_split_cnt < 0) {
|
||||
psoc = wlan_vdev_get_psoc(cbs->vdev);
|
||||
if (!psoc) {
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
wlan_son_deliver_cbs_completed(cbs->vdev);
|
||||
|
||||
ucfg_scan_unregister_requester(psoc,
|
||||
cbs->cbs_scan_requestor);
|
||||
qdf_debug("Unregister cbs_scan_requestor: %u",
|
||||
cbs->cbs_scan_requestor);
|
||||
|
||||
if (cbs->wait_time) {
|
||||
wlan_son_cbs_set_state(cbs, CBS_WAIT);
|
||||
qdf_timer_mod(&cbs->cbs_timer,
|
||||
cbs->wait_time);
|
||||
} else {
|
||||
wlan_son_cbs_set_state(cbs, CBS_INIT);
|
||||
}
|
||||
} else {
|
||||
offset_array_idx = cbs->max_arr_size_used -
|
||||
cbs->dwell_split_cnt - 1;
|
||||
if (offset_array_idx < MIN_SCAN_OFFSET_ARRAY_SIZE ||
|
||||
offset_array_idx > MAX_SCAN_OFFSET_ARRAY_SIZE) {
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (cbs->scan_dwell_rest[offset_array_idx] == 0) {
|
||||
cbs->dwell_split_cnt--;
|
||||
wlan_son_cbs_start(cbs);
|
||||
} else {
|
||||
wlan_son_cbs_set_state(cbs, CBS_REST);
|
||||
qdf_timer_mod(&cbs->cbs_timer,
|
||||
cbs->scan_dwell_rest[offset_array_idx]);
|
||||
}
|
||||
}
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wlan_cbs_scan_event_cb(struct wlan_objmgr_vdev *vdev,
|
||||
struct scan_event *event,
|
||||
void *arg)
|
||||
{
|
||||
qdf_debug("event type: %d", event->type);
|
||||
switch (event->type) {
|
||||
case SCAN_EVENT_TYPE_FOREIGN_CHANNEL:
|
||||
case SCAN_EVENT_TYPE_FOREIGN_CHANNEL_GET_NF:
|
||||
break;
|
||||
case SCAN_EVENT_TYPE_COMPLETED:
|
||||
wlan_cbs_iterate(arg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int wlan_son_cbs_init(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < WLAN_MAX_VDEVS; i++) {
|
||||
if (g_son_cbs[i]) {
|
||||
qdf_mem_free(g_son_cbs[i]);
|
||||
g_son_cbs[i] = NULL;
|
||||
}
|
||||
g_son_cbs[i] = qdf_mem_malloc(sizeof(*g_son_cbs[i]));
|
||||
if (!g_son_cbs[i]) {
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
qdf_mem_free(g_son_cbs[j]);
|
||||
g_son_cbs[i] = NULL;
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
qdf_timer_init(NULL,
|
||||
&g_son_cbs[i]->cbs_timer,
|
||||
wlan_cbs_timer_handler,
|
||||
g_son_cbs[i],
|
||||
QDF_TIMER_TYPE_WAKE_APPS);
|
||||
|
||||
g_son_cbs[i]->rest_time = CBS_DEFAULT_RESTTIME;
|
||||
g_son_cbs[i]->dwell_time = CBS_DEFAULT_DWELL_TIME;
|
||||
g_son_cbs[i]->wait_time = CBS_DEFAULT_WAIT_TIME;
|
||||
g_son_cbs[i]->dwell_split_time = CBS_DEFAULT_DWELL_SPLIT_TIME;
|
||||
g_son_cbs[i]->min_dwell_rest_time = CBS_DEFAULT_DWELL_REST_TIME;
|
||||
|
||||
wlan_son_cbs_set_state(g_son_cbs[i], CBS_INIT);
|
||||
}
|
||||
qdf_spinlock_create(&g_cbs_lock);
|
||||
qdf_debug("cbs init");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wlan_son_cbs_deinit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
qdf_spinlock_destroy(&g_cbs_lock);
|
||||
for (i = 0; i < WLAN_MAX_VDEVS; i++) {
|
||||
if (!g_son_cbs[i])
|
||||
return -EINVAL;
|
||||
if (g_son_cbs[i]->vdev) {
|
||||
wlan_objmgr_vdev_release_ref(g_son_cbs[i]->vdev,
|
||||
WLAN_SON_ID);
|
||||
qdf_debug("vdev_id: %d dereferenced",
|
||||
wlan_vdev_get_id(g_son_cbs[i]->vdev));
|
||||
}
|
||||
qdf_timer_free(&g_son_cbs[i]->cbs_timer);
|
||||
qdf_mem_free(g_son_cbs[i]);
|
||||
g_son_cbs[i] = NULL;
|
||||
}
|
||||
|
||||
qdf_debug("cbs deinit");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wlan_son_cbs_enable(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct scan_start_request *req;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
enum son_cbs_state state;
|
||||
struct son_cbs *cbs;
|
||||
QDF_STATUS status;
|
||||
|
||||
cbs = g_son_cbs[wlan_vdev_get_id(vdev)];
|
||||
psoc = wlan_vdev_get_psoc(vdev);
|
||||
if (!psoc) {
|
||||
qdf_err("invalid psoc");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
state = wlan_son_cbs_get_state(cbs);
|
||||
if (state != CBS_INIT &&
|
||||
state != CBS_WAIT) {
|
||||
qdf_err("can't start scan in state %d", state);
|
||||
return -EINVAL;
|
||||
}
|
||||
qdf_debug("State: %d", state);
|
||||
|
||||
qdf_spin_lock_bh(&g_cbs_lock);
|
||||
if (!cbs->vdev) {
|
||||
cbs->vdev = vdev;
|
||||
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_SON_ID);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
qdf_err("Failed to get VDEV reference");
|
||||
return -EAGAIN;
|
||||
}
|
||||
qdf_debug("vdev_id: %d referenced",
|
||||
wlan_vdev_get_id(vdev));
|
||||
}
|
||||
cbs->cbs_scan_requestor =
|
||||
ucfg_scan_register_requester(psoc,
|
||||
(uint8_t *)"cbs",
|
||||
wlan_cbs_scan_event_cb,
|
||||
(void *)cbs);
|
||||
qdf_debug("cbs_scan_requestor: %u vdev_id: %d",
|
||||
cbs->cbs_scan_requestor, wlan_vdev_get_id(vdev));
|
||||
|
||||
if (!cbs->cbs_scan_requestor) {
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_SON_ID);
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
qdf_err("ucfg_scan_register_requestor failed");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req = &cbs->scan_params;
|
||||
ucfg_scan_init_default_params(vdev, req);
|
||||
req->scan_req.scan_req_id = cbs->cbs_scan_requestor;
|
||||
|
||||
req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
|
||||
req->scan_req.scan_priority = SCAN_PRIORITY_HIGH;
|
||||
req->scan_req.scan_f_bcast_probe = true;
|
||||
|
||||
req->scan_req.scan_f_passive = true;
|
||||
req->scan_req.max_rest_time = DEFAULT_SCAN_MAX_REST_TIME;
|
||||
req->scan_req.scan_f_forced = true;
|
||||
|
||||
req->scan_req.scan_flags = 0;
|
||||
req->scan_req.dwell_time_active = cbs->dwell_split_time;
|
||||
req->scan_req.dwell_time_passive = cbs->dwell_split_time + 5;
|
||||
req->scan_req.min_rest_time = CBS_DEFAULT_MIN_REST_TIME;
|
||||
req->scan_req.max_rest_time = CBS_DEFAULT_DWELL_REST_TIME;
|
||||
req->scan_req.scan_f_passive = false;
|
||||
req->scan_req.scan_f_2ghz = true;
|
||||
req->scan_req.scan_f_5ghz = true;
|
||||
req->scan_req.scan_f_offchan_mgmt_tx = true;
|
||||
req->scan_req.scan_f_offchan_data_tx = true;
|
||||
req->scan_req.scan_f_chan_stat_evnt = true;
|
||||
|
||||
if (cbs->min_dwell_rest_time % DEFAULT_BEACON_INTERVAL) {
|
||||
cbs->min_dwell_rest_time =
|
||||
(cbs->min_dwell_rest_time /
|
||||
(2 * DEFAULT_BEACON_INTERVAL)) *
|
||||
(2 * DEFAULT_BEACON_INTERVAL) +
|
||||
(cbs->min_dwell_rest_time % 200 < 100) ? 100 : 200;
|
||||
}
|
||||
|
||||
wlan_son_cbs_init_dwell_params(cbs,
|
||||
cbs->dwell_split_time,
|
||||
cbs->min_dwell_rest_time);
|
||||
|
||||
cbs->dwell_split_cnt--;
|
||||
wlan_son_cbs_set_state(cbs, CBS_SCAN);
|
||||
|
||||
wlan_son_cbs_start(cbs);
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
|
||||
qdf_debug("cbs enable");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wlan_son_cbs_disable(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct son_cbs *cbs;
|
||||
|
||||
if (!vdev) {
|
||||
qdf_err("invalid psoc");
|
||||
return -EINVAL;
|
||||
}
|
||||
psoc = wlan_vdev_get_psoc(vdev);
|
||||
if (!psoc) {
|
||||
qdf_err("invalid psoc");
|
||||
return -EINVAL;
|
||||
}
|
||||
cbs = g_son_cbs[wlan_vdev_get_id(vdev)];
|
||||
if (!cbs->vdev) {
|
||||
qdf_err("vdev null");
|
||||
return -EINVAL;
|
||||
}
|
||||
wlan_son_deliver_cbs_cancelled(vdev);
|
||||
|
||||
qdf_timer_sync_cancel(&cbs->cbs_timer);
|
||||
|
||||
wlan_son_cbs_stop(cbs);
|
||||
|
||||
qdf_debug("cbs_scan_requestor: %d vdev_id: %d",
|
||||
cbs->cbs_scan_requestor, wlan_vdev_get_id(vdev));
|
||||
ucfg_scan_unregister_requester(psoc, cbs->cbs_scan_requestor);
|
||||
|
||||
qdf_spin_lock_bh(&g_cbs_lock);
|
||||
wlan_son_cbs_set_state(cbs, CBS_INIT);
|
||||
if (vdev == cbs->vdev) {
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_SON_ID);
|
||||
qdf_debug("vdev_id: %d dereferenced",
|
||||
vdev->vdev_objmgr.vdev_id);
|
||||
}
|
||||
cbs->vdev = NULL;
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
|
||||
qdf_debug("cbs disable");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wlan_son_set_cbs(struct wlan_objmgr_vdev *vdev,
|
||||
bool enable)
|
||||
{
|
||||
qdf_debug("Enable: %u", enable);
|
||||
|
||||
if (!vdev && !g_son_cbs[wlan_vdev_get_id(vdev)])
|
||||
return -EINVAL;
|
||||
|
||||
if (enable)
|
||||
wlan_son_cbs_enable(vdev);
|
||||
else
|
||||
wlan_son_cbs_disable(vdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wlan_son_set_cbs_wait_time(struct wlan_objmgr_vdev *vdev,
|
||||
uint32_t val)
|
||||
{
|
||||
if (!g_son_cbs[wlan_vdev_get_id(vdev)])
|
||||
return -EINVAL;
|
||||
|
||||
qdf_debug("vdev_id: %d wait time %d", wlan_vdev_get_id(vdev), val);
|
||||
wlan_son_set_cbs(vdev, false);
|
||||
|
||||
if (val % DEFAULT_BEACON_INTERVAL != 0) {
|
||||
val = (val / (2 * DEFAULT_BEACON_INTERVAL)) *
|
||||
(2 * DEFAULT_BEACON_INTERVAL) +
|
||||
(val % (2 * DEFAULT_BEACON_INTERVAL) <
|
||||
DEFAULT_BEACON_INTERVAL) ?
|
||||
DEFAULT_BEACON_INTERVAL :
|
||||
2 * DEFAULT_BEACON_INTERVAL;
|
||||
}
|
||||
qdf_spin_lock_bh(&g_cbs_lock);
|
||||
g_son_cbs[wlan_vdev_get_id(vdev)]->wait_time = val;
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
|
||||
wlan_son_set_cbs(vdev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wlan_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev,
|
||||
uint32_t val)
|
||||
{
|
||||
if (!g_son_cbs[wlan_vdev_get_id(vdev)])
|
||||
return -EINVAL;
|
||||
|
||||
qdf_debug("vdev_id: %d dwell split time %d",
|
||||
wlan_vdev_get_id(vdev), val);
|
||||
if (val != CBS_DWELL_TIME_10MS &&
|
||||
val != CBS_DWELL_TIME_25MS &&
|
||||
val != CBS_DWELL_TIME_50MS &&
|
||||
val != CBS_DWELL_TIME_75MS) {
|
||||
qdf_err("dwell time not supported ");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wlan_son_set_cbs(vdev, false);
|
||||
|
||||
qdf_spin_lock_bh(&g_cbs_lock);
|
||||
g_son_cbs[wlan_vdev_get_id(vdev)]->dwell_split_time = val;
|
||||
qdf_spin_unlock_bh(&g_cbs_lock);
|
||||
|
||||
wlan_son_set_cbs(vdev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user