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:
Li Feng 2021-08-19 16:48:02 +08:00 committed by Madan Koyyalamudi
parent 764df553b9
commit 813660e27f
7 changed files with 987 additions and 6 deletions

View File

@ -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
@ -26,6 +26,91 @@
#include <wlan_objmgr_pdev_obj.h>
#include <reg_services_public_struct.h>
#define TOTAL_DWELL_TIME 200
#define CBS_DEFAULT_RESTTIME 500 /* msec */
#define CBS_DEFAULT_DWELL_TIME 50 /* msec */
#define CBS_DEFAULT_WAIT_TIME 1000 /* 1 sec */
#define CBS_DEFAULT_DWELL_SPLIT_TIME 50 /* msec */
#define CBS_DEFAULT_DWELL_REST_TIME 500 /* msec */
#define CBS_DEFAULT_MIN_REST_TIME 50 /* msec */
#define DEFAULT_BEACON_INTERVAL 100
#define CBS_DWELL_TIME_10MS 10
#define CBS_DWELL_TIME_25MS 25
#define CBS_DWELL_TIME_50MS 50
#define CBS_DWELL_TIME_75MS 75
#define MIN_SCAN_OFFSET_ARRAY_SIZE 0
#define MAX_SCAN_OFFSET_ARRAY_SIZE 9
#define SCAN_START_OFFSET_MIN 26
#define DEFAULT_SCAN_MAX_REST_TIME 500
/**
* enum son_cbs_state - son cbs state enumeration
* @CBS_INIT: init state
* @CBS_SCAN: scanning state
* @CBS_REST: rest state
* @CBS_RANK: rank state
* @CBS_WAIT: wait state
*/
enum son_cbs_state {
CBS_INIT,
CBS_SCAN,
CBS_REST,
CBS_RANK,
CBS_WAIT,
};
/**
* struct son_cbs - son cbs struction
* @vdev: vdev
* @cbs_lock: cbs spin lock
* @cbs_timer: cbs timer
* @cbs_state: cbs state
* @cbs_scan_requestor: scan requestor
* @cbs_scan_id: scan id
* @dwell_time: dwell time configuration
* @rest_time: rest time configuration
* @wait_time: wait time configuration
* @scan_intvl_time: interval time configuration
* @scan_params: scan params
* @max_dwell_split_cnt: max dwell split counter
* @dwell_split_cnt: dwell split counter
* @scan_offset: scan offset array
* @scan_dwell_rest: scan dwell rest array
* @min_dwell_rest_time: nub dwell rest time
* @dwell_split_time: dwell split time
* @max_arr_size_used: max array size used
*/
struct son_cbs {
struct wlan_objmgr_vdev *vdev;
spinlock_t cbs_lock;
qdf_timer_t cbs_timer;
enum son_cbs_state cbs_state;
wlan_scan_requester cbs_scan_requestor;
wlan_scan_id cbs_scan_id;
uint32_t dwell_time;
uint32_t rest_time;
uint32_t wait_time;
int32_t scan_intvl_time;
struct scan_start_request scan_params;
uint8_t max_dwell_split_cnt;
int8_t dwell_split_cnt;
uint32_t scan_offset[10];
uint32_t scan_dwell_rest[10];
uint32_t min_dwell_rest_time;
uint32_t dwell_split_time;
uint8_t max_arr_size_used;
};
/**
* mlme_deliver_cb - cb to deliver mlme event
* @vdev: pointer to vdev
@ -88,6 +173,60 @@ QDF_STATUS wlan_son_peer_set_kickout_allow(struct wlan_objmgr_vdev *vdev,
struct wlan_objmgr_peer *peer,
bool kickout_allow);
/**
* wlan_son_cbs_init() - son cbs init
*
* Return: 0 if succeed
*/
int wlan_son_cbs_init(void);
/* wlan_son_cbs_deinit - son cbs deinit
*
* Return: 0 if succeed
*/
int wlan_son_cbs_deinit(void);
/* wlan_son_cbs_enable() - son cbs enable
* @vdev: pointer to vdev
*
* Return: 0 if succeed
*/
int wlan_son_cbs_enable(struct wlan_objmgr_vdev *vdev);
/* wlan_son_cbs_disable() - son cbs disable
* @vdev: pointer to vdev
*
* Return: 0 if succeed
*/
int wlan_son_cbs_disable(struct wlan_objmgr_vdev *vdev);
/* wlan_son_set_cbs() - son cbs set
* @vdev: pointer to vdev
* @enable: enable or disable son cbs
*
* Return: 0 if succeed
*/
int wlan_son_set_cbs(struct wlan_objmgr_vdev *vdev,
bool enable);
/* wlan_son_set_cbs_wait_time() - cbs wait time configure
* @vdev: pointer to vdev
* @val: wait time value
*
* Return: 0 if succeed
*/
int wlan_son_set_cbs_wait_time(struct wlan_objmgr_vdev *vdev,
uint32_t val);
/* wlan_son_set_cbs_dwell_split_time() - cbs dwell spilt time configure
* @vdev: pointer to vdev
* @val: dwell spilt time value
*
* Return: 0 if succeed
*/
int wlan_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev,
uint32_t val);
#ifdef WLAN_FEATURE_SON
/**
* wlan_son_peer_is_kickout_allow() - Is peer is allowed to kickout

View File

@ -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
@ -129,4 +129,58 @@ QDF_STATUS ucfg_son_register_deliver_opmode_cb(struct wlan_objmgr_psoc *psoc,
QDF_STATUS ucfg_son_register_deliver_smps_cb(struct wlan_objmgr_psoc *psoc,
mlme_deliver_cb cb);
/**
* ucfg_son_cbs_init() - son cbs init
*
* Return: 0 if succeed
*/
int ucfg_son_cbs_init(void);
/* ucfg_son_cbs_deinit - son cbs deinit
*
* Return: 0 if succeed
*/
int ucfg_son_cbs_deinit(void);
/* ucfg_son_set_cbs() - son cbs set
* @vdev: pointer to vdev
* @enable: enable or disable son cbs
*
* Return: 0 if succeed
*/
int ucfg_son_set_cbs(struct wlan_objmgr_vdev *vdev,
bool enable);
/* ucfg_son_set_cbs_wait_time() - cbs wait time configure
* @vdev: pointer to vdev
* @val: wait time value
*
* Return: 0 if succeed
*/
int ucfg_son_set_cbs_wait_time(struct wlan_objmgr_vdev *vdev,
uint32_t val);
/* ucfg_son_set_cbs_dwell_split_time() - cbs dwell spilt time configure
* @vdev: pointer to vdev
* @val: dwell spilt time value
*
* Return: 0 if succeed
*/
int ucfg_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev,
uint32_t val);
#ifdef WLAN_FEATURE_SON
/* ucfg_son_disable_cbs() - son cbs disable
* @vdev: vdev pointer
*
* Return: 0 if succeed
*/
int ucfg_son_disable_cbs(struct wlan_objmgr_vdev *vdev);
#else
static inline int ucfg_son_disable_cbs(struct wlan_objmgr_vdev *vdev)
{
return -EINVAL;
}
#endif
#endif

View File

@ -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;
}

View File

@ -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
@ -91,3 +91,36 @@ QDF_STATUS ucfg_son_register_deliver_smps_cb(struct wlan_objmgr_psoc *psoc,
return wlan_son_register_mlme_deliver_cb(psoc, cb,
SON_MLME_DELIVER_CB_TYPE_SMPS);
}
int ucfg_son_cbs_init(void)
{
return wlan_son_cbs_init();
}
int ucfg_son_cbs_deinit(void)
{
return wlan_son_cbs_deinit();
}
int ucfg_son_set_cbs(struct wlan_objmgr_vdev *vdev,
bool enable)
{
return wlan_son_set_cbs(vdev, enable);
}
int ucfg_son_set_cbs_wait_time(struct wlan_objmgr_vdev *vdev,
uint32_t val)
{
return wlan_son_set_cbs_wait_time(vdev, val);
}
int ucfg_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev,
uint32_t val)
{
return wlan_son_set_cbs_dwell_split_time(vdev, val);
}
int ucfg_son_disable_cbs(struct wlan_objmgr_vdev *vdev)
{
return wlan_son_cbs_disable(vdev);
}

View File

@ -216,6 +216,7 @@
#include <wlan_objmgr_psoc_obj_i.h>
#include <wlan_objmgr_vdev_obj_i.h>
#include "osif_vdev_mgr_util.h"
#include <son_ucfg_api.h>
#ifdef MODULE
#define WLAN_MODULE_NAME module_name(THIS_MODULE)
@ -6428,6 +6429,7 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter)
QDF_VDEV_DELETE_RESPONSE_TIMED_OUT);
}
ucfg_son_disable_cbs(vdev);
hdd_nofl_debug("vdev %d destroyed successfully", vdev_id);
send_status:

View File

@ -1,7 +1,7 @@
/*
* 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
@ -331,6 +331,52 @@ int os_if_son_set_phymode(struct wlan_objmgr_vdev *vdev,
void os_if_son_get_phy_stats(struct wlan_objmgr_vdev *vdev,
struct ol_ath_radiostats *phy_stats);
/**
* os_if_son_cbs_init() - cbs init
* @vdev: vdev
*
* Return: 0 on success, negative errno on failure
*/
int os_if_son_cbs_init(void);
/**
* os_if_son_cbs_deinit() - cbs deinit
* @vdev: vdev
*
* Return: 0 on success, negative errno on failure
*/
int os_if_son_cbs_deinit(void);
/**
* os_if_son_set_cbs() - enable cbs or disable
* @vdev: vdev
* @enable: true or false
*
* Return: 0 on success, negative errno on failure
*/
int os_if_son_set_cbs(struct wlan_objmgr_vdev *vdev,
bool enable);
/**
* os_if_son_set_cbs_wait_time() - set cbs wait time
* @vdev: vdev
* @val: value
*
* Return: 0 on success, negative errno on failure
*/
int os_if_son_set_cbs_wait_time(struct wlan_objmgr_vdev *vdev,
uint32_t val);
/**
* os_if_son_set_cbs_dwell_split_time() - set cbs dwell split time
* @vdev: vdev
* @val: value
*
* Return: 0 on success, negative errno on failure
*/
int os_if_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev,
uint32_t val);
/**
* os_if_son_get_chan_util() - get chan utilization
* @vdev: vdev

View File

@ -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
@ -785,6 +785,64 @@ void os_if_son_get_phy_stats(struct wlan_objmgr_vdev *vdev,
}
qdf_export_symbol(os_if_son_get_phy_stats);
int os_if_son_cbs_init(void)
{
int ret;
ret = ucfg_son_cbs_init();
return ret;
}
qdf_export_symbol(os_if_son_cbs_init);
int os_if_son_cbs_deinit(void)
{
int ret;
ret = ucfg_son_cbs_deinit();
return ret;
}
qdf_export_symbol(os_if_son_cbs_deinit);
int os_if_son_set_cbs(struct wlan_objmgr_vdev *vdev,
bool enable)
{
int ret;
ret = ucfg_son_set_cbs(vdev, enable);
return ret;
}
qdf_export_symbol(os_if_son_set_cbs);
int os_if_son_set_cbs_wait_time(struct wlan_objmgr_vdev *vdev,
uint32_t val)
{
int ret;
ret = ucfg_son_set_cbs_wait_time(vdev, val);
return ret;
}
qdf_export_symbol(os_if_son_set_cbs_wait_time);
int os_if_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev,
uint32_t val)
{
int ret;
ret = ucfg_son_set_cbs_dwell_split_time(vdev, val);
return ret;
}
qdf_export_symbol(os_if_son_set_cbs_dwell_split_time);
int os_if_son_set_phymode(struct wlan_objmgr_vdev *vdev,
enum ieee80211_phymode mode)
{