Merge "qcacmn: Add dcs component"

Cette révision appartient à :
Linux Build Service Account
2020-02-13 07:38:30 -08:00
révisé par Gerrit - the friendly Code Review server
révision 8f7b57c903
27 fichiers modifiés avec 2693 ajouts et 2 suppressions

Voir le fichier

@@ -33,6 +33,11 @@
#define CFG_GREEN_AP_ALL
#endif
#include <cfg_spectral.h>
#ifdef DCS_INTERFERENCE_DETECTION
#include "wlan_dcs_cfg.h"
#else
#define CFG_DCS_ALL
#endif
#define CFG_CONVERGED_ALL \
CFG_SCAN_ALL \
@@ -40,7 +45,8 @@
CFG_EXTSCAN_ALL \
CFG_GREEN_AP_ALL \
CFG_SPECTRAL_ALL \
CFG_HIF
CFG_HIF \
CFG_DCS_ALL
#endif /* __CFG_CONVERGED_H */

Voir le fichier

@@ -76,6 +76,10 @@
#include <wlan_coex_utils_api.h>
#endif
#ifdef DCS_INTERFERENCE_DETECTION
#include <wlan_dcs_init_deinit_api.h>
#endif
/**
* DOC: This file provides various init/deinit trigger point for new
* components.
@@ -193,6 +197,68 @@ static QDF_STATUS cp_stats_psoc_disable(struct wlan_objmgr_psoc *psoc)
}
#endif
#ifdef DCS_INTERFERENCE_DETECTION
static QDF_STATUS dispatcher_init_dcs(void)
{
return wlan_dcs_init();
}
static QDF_STATUS dispatcher_deinit_dcs(void)
{
return wlan_dcs_deinit();
}
static QDF_STATUS dcs_psoc_enable(struct wlan_objmgr_psoc *psoc)
{
return wlan_dcs_enable(psoc);
}
static QDF_STATUS dcs_psoc_disable(struct wlan_objmgr_psoc *psoc)
{
return wlan_dcs_disable(psoc);
}
static QDF_STATUS dcs_psoc_open(struct wlan_objmgr_psoc *psoc)
{
return wlan_dcs_psoc_open(psoc);
}
static QDF_STATUS dcs_psoc_close(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
#else
static QDF_STATUS dispatcher_init_dcs(void)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dispatcher_deinit_dcs(void)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dcs_psoc_enable(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dcs_psoc_disable(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dcs_psoc_open(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS dcs_psoc_close(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
#endif
#if defined QCA_SUPPORT_SON && QCA_SUPPORT_SON >= 1
static QDF_STATUS dispatcher_init_son(void)
{
@@ -775,6 +841,9 @@ QDF_STATUS dispatcher_init(void)
if (QDF_STATUS_SUCCESS != dispatcher_init_cp_stats())
goto cp_stats_init_fail;
if (QDF_STATUS_SUCCESS != dispatcher_init_dcs())
goto dcs_init_fail;
if (QDF_STATUS_SUCCESS != dispatcher_init_atf())
goto atf_init_fail;
@@ -866,6 +935,8 @@ wifi_pos_init_fail:
sa_api_init_fail:
dispatcher_deinit_atf();
atf_init_fail:
dispatcher_deinit_dcs();
dcs_init_fail:
dispatcher_deinit_cp_stats();
cp_stats_init_fail:
dispatcher_deinit_crypto();
@@ -924,6 +995,8 @@ QDF_STATUS dispatcher_deinit(void)
QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_deinit_cp_stats());
QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_deinit_dcs());
QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_deinit_crypto());
QDF_BUG(QDF_STATUS_SUCCESS == wlan_serialization_deinit());
@@ -982,8 +1055,13 @@ QDF_STATUS dispatcher_psoc_open(struct wlan_objmgr_psoc *psoc)
if (QDF_STATUS_SUCCESS != dispatcher_coex_psoc_open(psoc))
goto coex_psoc_open_fail;
if (QDF_STATUS_SUCCESS != dcs_psoc_open(psoc))
goto dcs_psoc_open_fail;
return QDF_STATUS_SUCCESS;
dcs_psoc_open_fail:
dispatcher_coex_psoc_close(psoc);
coex_psoc_open_fail:
dispatcher_ftm_psoc_close(psoc);
ftm_psoc_open_fail:
@@ -1006,6 +1084,8 @@ qdf_export_symbol(dispatcher_psoc_open);
QDF_STATUS dispatcher_psoc_close(struct wlan_objmgr_psoc *psoc)
{
QDF_BUG(QDF_STATUS_SUCCESS == dcs_psoc_close(psoc));
QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_coex_psoc_close(psoc));
QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_ftm_psoc_close(psoc));
@@ -1040,6 +1120,9 @@ QDF_STATUS dispatcher_psoc_enable(struct wlan_objmgr_psoc *psoc)
if (QDF_STATUS_SUCCESS != cp_stats_psoc_enable(psoc))
goto cp_stats_psoc_enable_fail;
if (QDF_STATUS_SUCCESS != dcs_psoc_enable(psoc))
goto dcs_psoc_enable_fail;
if (QDF_STATUS_SUCCESS != atf_psoc_enable(psoc))
goto atf_psoc_enable_fail;
@@ -1071,6 +1154,8 @@ wifi_dfs_psoc_enable_fail:
wifi_pos_psoc_enable_fail:
atf_psoc_disable(psoc);
atf_psoc_enable_fail:
dcs_psoc_disable(psoc);
dcs_psoc_enable_fail:
cp_stats_psoc_disable(psoc);
cp_stats_psoc_enable_fail:
sa_api_psoc_disable(psoc);
@@ -1126,6 +1211,7 @@ QDF_STATUS dispatcher_pdev_open(struct wlan_objmgr_pdev *pdev)
if (QDF_STATUS_SUCCESS != wlan_mgmt_txrx_pdev_open(pdev))
goto mgmt_txrx_pdev_open_fail;
if (QDF_IS_STATUS_ERROR(dispatcher_green_ap_pdev_open(pdev)))
goto green_ap_pdev_open_fail;

Voir le fichier

@@ -381,6 +381,7 @@ typedef bool (*qdf_irqlocked_func_t)(void *);
* @QDF_MODULE_ID_FTM_TIME_SYNC: FTM Time sync module ID
* @QDF_MODULE_ID_PKT_CAPTURE: PACKET CAPTURE module ID
* @QDF_MODULE_ID_MON_FILTER: Monitor filter related config module ID
* @QDF_MODULE_ID_DCS: DCS module ID
* @QDF_MODULE_ID_ANY: anything
* @QDF_MODULE_ID_MAX: Max place holder module ID
*/
@@ -503,6 +504,7 @@ typedef enum {
QDF_MODULE_ID_FTM_TIME_SYNC,
QDF_MODULE_ID_PKT_CAPTURE,
QDF_MODULE_ID_MON_FILTER,
QDF_MODULE_ID_DCS,
QDF_MODULE_ID_ANY,
QDF_MODULE_ID_MAX,
} QDF_MODULE_ID;

Voir le fichier

@@ -3080,6 +3080,7 @@ struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
[QDF_MODULE_ID_CONFIG] = {"CONFIG"},
[QDF_MODULE_ID_IPA] = {"IPA"},
[QDF_MODULE_ID_CP_STATS] = {"CP_STATS"},
[QDF_MODULE_ID_DCS] = {"DCS"},
[QDF_MODULE_ID_ACTION_OUI] = {"action_oui"},
[QDF_MODULE_ID_TARGET] = {"TARGET"},
[QDF_MODULE_ID_MBSSIE] = {"MBSSIE"},
@@ -3543,6 +3544,7 @@ static void set_default_trace_levels(struct category_info *cinfo)
[QDF_MODULE_ID_IPA] = QDF_TRACE_LEVEL_NONE,
[QDF_MODULE_ID_ACTION_OUI] = QDF_TRACE_LEVEL_NONE,
[QDF_MODULE_ID_CP_STATS] = QDF_TRACE_LEVEL_ERROR,
[QDF_MODULE_ID_DCS] = QDF_TRACE_LEVEL_ERROR,
[QDF_MODULE_ID_MBSSIE] = QDF_TRACE_LEVEL_INFO,
[QDF_MODULE_ID_FWOL] = QDF_TRACE_LEVEL_NONE,
[QDF_MODULE_ID_SM_ENGINE] = QDF_TRACE_LEVEL_ERROR,

Voir le fichier

@@ -84,6 +84,10 @@
#include <target_if_coex.h>
#endif
#ifdef DCS_INTERFERENCE_DETECTION
#include <target_if_dcs.h>
#endif
static struct target_if_ctx *g_target_if_ctx;
struct target_if_ctx *target_if_get_ctx()
@@ -399,6 +403,20 @@ target_if_cp_stats_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
return target_if_cp_stats_register_tx_ops(tx_ops);
}
#ifdef DCS_INTERFERENCE_DETECTION
static QDF_STATUS
target_if_dcs_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
{
return target_if_dcs_register_tx_ops(tx_ops);
}
#else
static QDF_STATUS
target_if_dcs_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
{
return QDF_STATUS_SUCCESS;
}
#endif
static QDF_STATUS
target_if_vdev_mgr_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
{
@@ -455,6 +473,8 @@ QDF_STATUS target_if_register_umac_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
target_if_cp_stats_tx_ops_register(tx_ops);
target_if_dcs_tx_ops_register(tx_ops);
target_if_crypto_tx_ops_register(tx_ops);
target_if_vdev_mgr_tx_ops_register(tx_ops);

Voir le fichier

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: target_if_dcs.h
*
* This header file provide declarations required for Rx and Tx events from
* firmware
*/
#ifndef __TARGET_IF_DCS_H__
#define __TARGET_IF_DCS_H__
#include <target_if.h>
#include <wlan_lmac_if_def.h>
/**
* target_if_dcs_get_rx_ops() - get rx ops
* @tx_ops: pointer to target_if tx ops
*
* API to retrieve the dcs rx ops from the psoc context
*
* Return: pointer to rx ops
*/
static inline struct wlan_target_if_dcs_rx_ops *
target_if_dcs_get_rx_ops(struct wlan_objmgr_psoc *psoc)
{
return &psoc->soc_cb.rx_ops.dcs_rx_ops;
}
/**
* target_if_dcs_get_tx_ops() - get tx ops
* @tx_ops: pointer to target_if tx ops
*
* API to retrieve the dcs tx ops from the psoc context
*
* Return: pointer to tx ops
*/
static inline struct wlan_target_if_dcs_tx_ops *
target_if_dcs_get_tx_ops(struct wlan_objmgr_psoc *psoc)
{
return &psoc->soc_cb.tx_ops.dcs_tx_ops;
}
/**
* target_if_dcs_register_tx_ops() - register dcs target_if tx ops functions
* @tx_ops: pointer to target_if tx ops
*
* API to register dcs tx ops
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
*/
QDF_STATUS
target_if_dcs_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops);
#endif /* __TARGET_IF_DCS_H__ */

Voir le fichier

@@ -0,0 +1,197 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: target_if_dcs.c
*
* This file provide definition for APIs registered through lmac Tx Ops
*/
#include <wmi_unified_api.h>
#include <wmi_unified_priv.h>
#include <wmi_unified_dcs_api.h>
#include <init_deinit_lmac.h>
#include "wlan_dcs_tgt_api.h"
#include "target_if_dcs.h"
/**
* target_if_dcs_interference_event_handler() - function to handle dcs event
* from firmware.
* @scn: scn handle
* @data: data buffer for event
* @datalen: data length
*
* Return: status of operation.
*/
static int target_if_dcs_interference_event_handler(ol_scn_t scn,
uint8_t *data,
uint32_t datalen)
{
QDF_STATUS status;
struct dcs_stats_event ev;
struct wlan_objmgr_psoc *psoc;
struct wmi_unified *wmi_handle;
struct wlan_target_if_dcs_rx_ops *rx_ops;
if (!scn || !data) {
target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
return -EINVAL;
}
psoc = target_if_get_psoc_from_scn_hdl(scn);
if (!psoc) {
target_if_err("null psoc");
return -EINVAL;
}
rx_ops = target_if_dcs_get_rx_ops(psoc);
if (!rx_ops || !rx_ops->process_dcs_event) {
target_if_err("callback not registered");
return -EINVAL;
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("wmi_handle is null");
return -EINVAL;
}
if (wmi_extract_dcs_interference_type(wmi_handle, data,
&ev.dcs_param) !=
QDF_STATUS_SUCCESS) {
target_if_err("Unable to extract dcs interference type");
return -EINVAL;
}
if (wmi_extract_dcs_im_tgt_stats(wmi_handle, data, &ev.wlan_stat) !=
QDF_STATUS_SUCCESS) {
target_if_err("Unable to extract WLAN IM stats");
return -EINVAL;
}
status = rx_ops->process_dcs_event(psoc, &ev);
return qdf_status_to_os_return(status);
}
static QDF_STATUS
target_if_dcs_register_event_handler(struct wlan_objmgr_psoc *psoc)
{
int ret_val;
struct wmi_unified *wmi_handle;
if (!psoc) {
target_if_err("PSOC is NULL!");
return QDF_STATUS_E_NULL_VALUE;
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("wmi_handle is null");
return QDF_STATUS_E_INVAL;
}
ret_val = wmi_unified_register_event_handler(
wmi_handle,
wmi_dcs_interference_event_id,
target_if_dcs_interference_event_handler,
WMI_RX_WORK_CTX);
if (ret_val)
target_if_err("Failed to register dcs interference event cb");
return qdf_status_from_os_return(ret_val);
}
static QDF_STATUS
target_if_dcs_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
{
struct wmi_unified *wmi_handle;
if (!psoc) {
target_if_err("PSOC is NULL!");
return QDF_STATUS_E_INVAL;
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("wmi_handle is null");
return QDF_STATUS_E_INVAL;
}
wmi_unified_unregister_event_handler(wmi_handle,
wmi_dcs_interference_event_id);
return QDF_STATUS_SUCCESS;
}
/**
* target_if_dcs_cmd_send() - Send WMI command for dcs requests
* @psoc: psoc pointer
* @pdev_id: pdev_id
* @is_target_pdev_id: pdev_id is target pdev_id or not
* @dcs_enable: dcs enable or not
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
*/
static QDF_STATUS
target_if_dcs_cmd_send(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id,
bool is_target_pdev_id, uint32_t dcs_enable)
{
QDF_STATUS ret;
struct wmi_unified *wmi_handle;
if (!psoc) {
target_if_err("null psoc");
return QDF_STATUS_E_FAILURE;
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("null handle");
return QDF_STATUS_E_FAILURE;
}
ret = wmi_send_dcs_pdev_param(wmi_handle, pdev_id,
is_target_pdev_id, dcs_enable);
if (QDF_IS_STATUS_ERROR(ret))
target_if_err("wmi dcs cmd send failed, ret: %d", ret);
return ret;
}
QDF_STATUS
target_if_dcs_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
{
struct wlan_target_if_dcs_tx_ops *dcs_tx_ops;
if (!tx_ops) {
target_if_err("lmac tx ops is NULL!");
return QDF_STATUS_E_INVAL;
}
dcs_tx_ops = &tx_ops->dcs_tx_ops;
if (!dcs_tx_ops) {
target_if_err("lmac tx ops is NULL!");
return QDF_STATUS_E_FAILURE;
}
dcs_tx_ops->dcs_attach =
target_if_dcs_register_event_handler;
dcs_tx_ops->dcs_detach =
target_if_dcs_unregister_event_handler;
dcs_tx_ops->dcs_cmd_send = target_if_dcs_cmd_send;
return QDF_STATUS_SUCCESS;
}

Voir le fichier

@@ -275,6 +275,7 @@
* @WLAN_UMAC_COMP_COEX: Coex config component
* @WLAN_UMAC_COMP_FTM_TIME_SYNC: WLAN FTM TIMESYNC
* @WLAN_UMAC_COMP_PKT_CAPTURE: Packet capture component
* @WLAN_UMAC_COMP_DCS: DCS
* @WLAN_UMAC_COMP_ID_MAX: Maximum components in UMAC
*
* This id is static.
@@ -317,6 +318,7 @@ enum wlan_umac_comp_id {
WLAN_UMAC_COMP_COEX = 33,
WLAN_UMAC_COMP_FTM_TIME_SYNC = 34,
WLAN_UMAC_COMP_PKT_CAPTURE = 35,
WLAN_UMAC_COMP_DCS = 36,
WLAN_UMAC_COMP_ID_MAX,
};

Voir le fichier

@@ -262,6 +262,7 @@ typedef void (*wlan_objmgr_peer_status_handler)(
* @WLAN_PSOC_TARGET_IF_ID PSOC related target_if operations
* @FTM_TIME_SYNC_ID: ftm time sync operations
* @WLAN_PKT_CAPTURE_ID Packet capture operations
* @WLAN_DCS_ID: DCS operations
* @WLAN_REF_ID_MAX: Max id used to generate ref count tracking array
*/
/* New value added to the enum must also be reflected in function
@@ -343,6 +344,7 @@ typedef enum {
WLAN_PSOC_TARGET_IF_ID = 72,
FTM_TIME_SYNC_ID = 73,
WLAN_PKT_CAPTURE_ID = 74,
WLAN_DCS_ID = 75,
WLAN_REF_ID_MAX,
} wlan_objmgr_ref_dbgid;
@@ -428,6 +430,7 @@ static inline char *string_from_dbgid(wlan_objmgr_ref_dbgid id)
"WLAN_MISC_ID",
"WLAN_FWOL_NB_ID",
"WLAN_FWOL_SB_ID",
"WLAN_DCS_ID",
"WLAN_REF_ID_MAX"};
return (char *)strings[id];

727
umac/dcs/core/src/wlan_dcs.c Fichier normal
Voir le fichier

@@ -0,0 +1,727 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: wlan_dcs.c
*
* This file provide definitions for following:
* - (de)register to WMI events for psoc enable
* - send dcs wmi command
* - dcs algorithm handling
*/
#include <target_if_dcs.h>
#include "wlan_dcs.h"
struct dcs_pdev_priv_obj *
wlan_dcs_get_pdev_private_obj(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id)
{
struct dcs_psoc_priv_obj *dcs_psoc_obj;
struct dcs_pdev_priv_obj *dcs_pdev_priv = NULL;
if (!psoc) {
dcs_err("psoc is null");
goto end;
}
dcs_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
psoc,
WLAN_UMAC_COMP_DCS);
if (!dcs_psoc_obj) {
dcs_err("dcs psoc object is null");
goto end;
}
if (pdev_id >= WLAN_UMAC_MAX_PDEVS) {
dcs_err("invalid pdev_id: %u", pdev_id);
goto end;
}
dcs_pdev_priv = &dcs_psoc_obj->dcs_pdev_priv[pdev_id];
end:
return dcs_pdev_priv;
}
QDF_STATUS wlan_dcs_attach(struct wlan_objmgr_psoc *psoc)
{
struct wlan_target_if_dcs_tx_ops *dcs_tx_ops;
if (!psoc) {
dcs_err("psoc is null");
return QDF_STATUS_E_NULL_VALUE;
}
dcs_tx_ops = target_if_dcs_get_tx_ops(psoc);
if (!dcs_tx_ops) {
dcs_err("tx_ops is null!");
return QDF_STATUS_E_NULL_VALUE;
}
if (!dcs_tx_ops->dcs_attach) {
dcs_err("dcs_attach function is null!");
return QDF_STATUS_E_NULL_VALUE;
}
return dcs_tx_ops->dcs_attach(psoc);
}
QDF_STATUS wlan_dcs_detach(struct wlan_objmgr_psoc *psoc)
{
struct wlan_target_if_dcs_tx_ops *dcs_tx_ops;
if (!psoc) {
dcs_err("psoc is null");
return QDF_STATUS_E_NULL_VALUE;
}
dcs_tx_ops = target_if_dcs_get_tx_ops(psoc);
if (!dcs_tx_ops) {
dcs_err("tx_ops is null!");
return QDF_STATUS_E_NULL_VALUE;
}
if (!dcs_tx_ops->dcs_detach) {
dcs_err("dcs_detach function is null!");
return QDF_STATUS_E_NULL_VALUE;
}
return dcs_tx_ops->dcs_detach(psoc);
}
QDF_STATUS wlan_dcs_cmd_send(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
bool is_target_pdev_id)
{
struct wlan_target_if_dcs_tx_ops *dcs_tx_ops;
struct dcs_pdev_priv_obj *dcs_pdev_priv;
uint32_t dcs_enable;
if (!psoc) {
dcs_err("psoc is null");
return QDF_STATUS_E_NULL_VALUE;
}
dcs_pdev_priv = wlan_dcs_get_pdev_private_obj(psoc, pdev_id);
if (!dcs_pdev_priv) {
dcs_err("dcs pdev private object is null");
return QDF_STATUS_E_NULL_VALUE;
}
dcs_enable = dcs_pdev_priv->dcs_host_params.dcs_enable &
dcs_pdev_priv->dcs_host_params.dcs_enable_cfg;
dcs_tx_ops = target_if_dcs_get_tx_ops(psoc);
if (dcs_tx_ops->dcs_cmd_send) {
dcs_info("dcs_enable: %u, pdev_id: %u", dcs_enable, pdev_id);
return dcs_tx_ops->dcs_cmd_send(psoc,
pdev_id,
is_target_pdev_id,
dcs_enable);
}
return QDF_STATUS_SUCCESS;
}
/**
* wlan_dcs_disable_cmd_send() - send dcs disable command to target_if layer
* @psoc: psoc pointer
* @pdev_id: pdev_id
* @is_target_pdev_id: pdev_id is target id or not
*
* The function gets called to send dcs disable command to FW
*
* return: QDF_STATUS_SUCCESS for success or error code
*/
static QDF_STATUS wlan_dcs_disable_cmd_send(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
bool is_target_pdev_id)
{
struct wlan_target_if_dcs_tx_ops *dcs_tx_ops;
struct dcs_pdev_priv_obj *dcs_pdev_priv;
if (!psoc) {
dcs_err("psoc is null");
return QDF_STATUS_E_NULL_VALUE;
}
dcs_pdev_priv = wlan_dcs_get_pdev_private_obj(psoc, pdev_id);
if (!dcs_pdev_priv) {
dcs_err("dcs pdev private object is null");
return QDF_STATUS_E_NULL_VALUE;
}
dcs_tx_ops = target_if_dcs_get_tx_ops(psoc);
if (dcs_tx_ops->dcs_cmd_send) {
dcs_info("dcs_enable: %u, pdev_id: %u", 0, pdev_id);
return dcs_tx_ops->dcs_cmd_send(psoc,
pdev_id,
is_target_pdev_id,
0);
}
return QDF_STATUS_SUCCESS;
}
/**
* wlan_dcs_im_copy_stats() - dcs target interference mitigation statistics copy
* @prev_stats: previous statistics pointer
* @curr_stats: current statistics pointer
*
* Return: None
*/
static inline void
wlan_dcs_im_copy_stats(struct wlan_host_dcs_im_tgt_stats *prev_stats,
struct wlan_host_dcs_im_tgt_stats *curr_stats)
{
if (!prev_stats || !curr_stats) {
dcs_err("previous or current stats is null");
return;
}
/*
* Right now no other actions are required beyond memcopy,
* if required the rest of the code would follow.
*/
qdf_mem_copy(prev_stats, curr_stats,
sizeof(struct wlan_host_dcs_im_tgt_stats));
}
/**
* wlan_dcs_im_print_stats() - print current/previous dcs target im statistics
* @prev_stats: previous statistics pointer
* @curr_stats: current statistics pointer
*
* Return: None
*/
static void
wlan_dcs_im_print_stats(struct wlan_host_dcs_im_tgt_stats *prev_stats,
struct wlan_host_dcs_im_tgt_stats *curr_stats)
{
if (!prev_stats || !curr_stats) {
dcs_err("previous or current stats is null");
return;
}
/* Debug, dump all received stats first */
dcs_debug("tgt_curr/tsf: %u", curr_stats->reg_tsf32);
dcs_debug("tgt_curr/last_ack_rssi: %u", curr_stats->last_ack_rssi);
dcs_debug("tgt_curr/tx_waste_time: %u", curr_stats->tx_waste_time);
dcs_debug("tgt_curr/dcs_rx_time: %u", curr_stats->rx_time);
dcs_debug("tgt_curr/listen_time: %u",
curr_stats->mib_stats.listen_time);
dcs_debug("tgt_curr/tx_frame_cnt: %u",
curr_stats->mib_stats.reg_tx_frame_cnt);
dcs_debug("tgt_curr/rx_frame_cnt: %u",
curr_stats->mib_stats.reg_rx_frame_cnt);
dcs_debug("tgt_curr/rxclr_cnt: %u",
curr_stats->mib_stats.reg_rxclr_cnt);
dcs_debug("tgt_curr/reg_cycle_cnt: %u",
curr_stats->mib_stats.reg_cycle_cnt);
dcs_debug("tgt_curr/rxclr_ext_cnt: %u",
curr_stats->mib_stats.reg_rxclr_ext_cnt);
dcs_debug("tgt_curr/ofdm_phyerr_cnt: %u",
curr_stats->mib_stats.reg_ofdm_phyerr_cnt);
dcs_debug("tgt_curr/cck_phyerr_cnt: %u",
curr_stats->mib_stats.reg_cck_phyerr_cnt);
dcs_debug("tgt_prev/tsf: %u", prev_stats->reg_tsf32);
dcs_debug("tgt_prev/last_ack_rssi: %u", prev_stats->last_ack_rssi);
dcs_debug("tgt_prev/tx_waste_time: %u", prev_stats->tx_waste_time);
dcs_debug("tgt_prev/rx_time: %u", prev_stats->rx_time);
dcs_debug("tgt_prev/listen_time: %u",
prev_stats->mib_stats.listen_time);
dcs_debug("tgt_prev/tx_frame_cnt: %u",
prev_stats->mib_stats.reg_tx_frame_cnt);
dcs_debug("tgt_prev/rx_frame_cnt: %u",
prev_stats->mib_stats.reg_rx_frame_cnt);
dcs_debug("tgt_prev/rxclr_cnt: %u",
prev_stats->mib_stats.reg_rxclr_cnt);
dcs_debug("tgt_prev/reg_cycle_cnt: %u",
prev_stats->mib_stats.reg_cycle_cnt);
dcs_debug("tgt_prev/rxclr_ext_cnt: %u",
prev_stats->mib_stats.reg_rxclr_ext_cnt);
dcs_debug("tgt_prev/ofdm_phyerr_cnt: %u",
prev_stats->mib_stats.reg_ofdm_phyerr_cnt);
dcs_debug("tgt_prev/cck_phyerr_cnt: %u",
prev_stats->mib_stats.reg_cck_phyerr_cnt);
}
/**
* wlan_dcs_wlan_interference_process() - dcs detection algorithm handling
* @curr_stats: current target im stats pointer
* @dcs_pdev_priv: dcs pdev priv pointer
*
* Return: true or false means start dcs callback handler or not
*/
static bool
wlan_dcs_wlan_interference_process(
struct wlan_host_dcs_im_tgt_stats *curr_stats,
struct dcs_pdev_priv_obj *dcs_pdev_priv)
{
struct wlan_host_dcs_im_tgt_stats *prev_stats;
struct pdev_dcs_params dcs_host_params;
struct pdev_dcs_im_stats dcs_im_stats;
bool start_dcs_cbk_handler = false;
uint32_t reg_tsf_delta = 0;
uint32_t rxclr_delta = 0;
uint32_t rxclr_ext_delta = 0;
uint32_t cycle_count_delta = 0;
uint32_t tx_frame_delta = 0;
uint32_t rx_frame_delta = 0;
uint32_t reg_total_cu = 0;
uint32_t reg_tx_cu = 0;
uint32_t reg_rx_cu = 0;
uint32_t reg_unused_cu = 0;
uint32_t rx_time_cu = 0;
uint32_t reg_ofdm_phyerr_delta = 0;
uint32_t reg_cck_phyerr_delta = 0;
uint32_t reg_ofdm_phyerr_cu = 0;
uint32_t ofdm_phy_err_rate = 0;
uint32_t cck_phy_err_rate = 0;
uint32_t max_phy_err_rate = 0;
uint32_t max_phy_err_count = 0;
uint32_t total_wasted_cu = 0;
uint32_t wasted_tx_cu = 0;
uint32_t tx_err = 0;
uint32_t too_many_phy_errors = 0;
if (!curr_stats) {
dcs_err("curr_stats is NULL");
goto end;
}
if (!dcs_pdev_priv) {
dcs_err("dcs pdev private object is NULL");
goto end;
}
dcs_host_params = dcs_pdev_priv->dcs_host_params;
dcs_im_stats = dcs_pdev_priv->dcs_im_stats;
prev_stats = &dcs_pdev_priv->dcs_im_stats.prev_dcs_im_stats;
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_VERBOSE))
wlan_dcs_im_print_stats(prev_stats, curr_stats);
/*
* Counters would have wrapped. Ideally we should be able to figure this
* out, but we never know how many times counters wrapped, just ignore.
*/
if ((curr_stats->mib_stats.listen_time <= 0) ||
(curr_stats->reg_tsf32 <= prev_stats->reg_tsf32)) {
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_VERBOSE))
dcs_debug("ignoring due to negative TSF value");
/* Copy the current stats to previous stats for next run */
wlan_dcs_im_copy_stats(prev_stats, curr_stats);
goto end;
}
reg_tsf_delta = curr_stats->reg_tsf32 - prev_stats->reg_tsf32;
/*
* Do nothing if current stats are not seeming good, probably
* a reset happened on chip, force cleared
*/
if (prev_stats->mib_stats.reg_rxclr_cnt >
curr_stats->mib_stats.reg_rxclr_cnt) {
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_VERBOSE))
dcs_debug("ignoring due to negative rxclr count");
/* Copy the current stats to previous stats for next run */
wlan_dcs_im_copy_stats(prev_stats, curr_stats);
goto end;
}
rxclr_delta = curr_stats->mib_stats.reg_rxclr_cnt -
prev_stats->mib_stats.reg_rxclr_cnt;
rxclr_ext_delta = curr_stats->mib_stats.reg_rxclr_ext_cnt -
prev_stats->mib_stats.reg_rxclr_ext_cnt;
tx_frame_delta = curr_stats->mib_stats.reg_tx_frame_cnt -
prev_stats->mib_stats.reg_tx_frame_cnt;
rx_frame_delta = curr_stats->mib_stats.reg_rx_frame_cnt -
prev_stats->mib_stats.reg_rx_frame_cnt;
cycle_count_delta = curr_stats->mib_stats.reg_cycle_cnt -
prev_stats->mib_stats.reg_cycle_cnt;
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_VERBOSE))
dcs_debug("rxclr_delta: %u, rxclr_ext_delta: %u, tx_frame_delta: %u, rx_frame_delta: %u, cycle_count_delta: %u",
rxclr_delta, rxclr_ext_delta,
tx_frame_delta, rx_frame_delta, cycle_count_delta);
if (0 == (cycle_count_delta >> 8)) {
wlan_dcs_im_copy_stats(prev_stats, curr_stats);
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_VERBOSE))
dcs_debug("cycle count NULL --Investigate--");
goto end;
}
/*
* Total channel utiliztaion is the amount of time RXCLR is
* counted. RXCLR is counted, when 'RX is NOT clear', please
* refer to mac documentation. It means either TX or RX is ON
*
* Why shift by 8 ? after multiplication it could overflow. At one
* second rate, neither cycle_count_celta nor the tsf_delta would be
* zero after shift by 8 bits
*/
reg_total_cu = ((rxclr_delta >> 8) * 100) / (cycle_count_delta >> 8);
reg_tx_cu = ((tx_frame_delta >> 8) * 100) / (cycle_count_delta >> 8);
reg_rx_cu = ((rx_frame_delta >> 8) * 100) / (cycle_count_delta >> 8);
rx_time_cu = ((curr_stats->rx_time >> 8) * 100) / (reg_tsf_delta >> 8);
/*
* Amount of the time AP received cannot go higher than the receive
* cycle count delta. If at all it is, there should have been a
* computation error, ceil it to receive_cycle_count_diff
*/
if (rx_time_cu > reg_rx_cu)
rx_time_cu = reg_rx_cu;
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_VERBOSE))
dcs_debug("reg_total_cu: %u, reg_tx_cu: %u, reg_rx_cu: %u, rx_time_cu: %u",
reg_total_cu, reg_tx_cu, reg_rx_cu, rx_time_cu);
/*
* Unusable channel utilization is amount of time that we
* spent in backoff or waiting for other transmit/receive to
* complete. If there is interference it is more likely that
* we overshoot the limit. In case of multiple stations, we
* still see increased channel utilization. This assumption may
* not be true for the VOW scenario where either multicast or
* unicast-UDP is used ( mixed traffic would still cause high
* channel utilization).
*/
wasted_tx_cu = ((curr_stats->tx_waste_time >> 8) * 100) /
(reg_tsf_delta >> 8);
/*
* Transmit channel utilization cannot go higher than the amount of time
* wasted, if so cap the wastage to transmit channel utillzation. This
* could happen to compution error.
*/
if (reg_tx_cu < wasted_tx_cu)
wasted_tx_cu = reg_tx_cu;
tx_err = (reg_tx_cu && wasted_tx_cu) ?
(wasted_tx_cu * 100) / reg_tx_cu : 0;
/*
* The below actually gives amount of time we are not using, or the
* interferer is active.
* rx_time_cu is what computed receive time *NOT* rx_cycle_count
* rx_cycle_count is our receive+interferer's transmit
* un-used is really total_cycle_counts -
* (our_rx_time(rx_time_cu) + our_receive_time)
*/
reg_unused_cu = (reg_total_cu >= (reg_tx_cu + rx_time_cu)) ?
(reg_total_cu - (reg_tx_cu + rx_time_cu)) : 0;
/* If any retransmissions are there, count them as wastage */
total_wasted_cu = reg_unused_cu + wasted_tx_cu;
/* Check ofdm and cck errors */
if (unlikely(curr_stats->mib_stats.reg_ofdm_phyerr_cnt <
prev_stats->mib_stats.reg_ofdm_phyerr_cnt))
reg_ofdm_phyerr_delta =
curr_stats->mib_stats.reg_ofdm_phyerr_cnt;
else
reg_ofdm_phyerr_delta =
curr_stats->mib_stats.reg_ofdm_phyerr_cnt -
prev_stats->mib_stats.reg_ofdm_phyerr_cnt;
if (unlikely(curr_stats->mib_stats.reg_cck_phyerr_cnt <
prev_stats->mib_stats.reg_cck_phyerr_cnt))
reg_cck_phyerr_delta = curr_stats->mib_stats.reg_cck_phyerr_cnt;
else
reg_cck_phyerr_delta =
curr_stats->mib_stats.reg_cck_phyerr_cnt -
prev_stats->mib_stats.reg_cck_phyerr_cnt;
/*
* Add the influence of ofdm phy errors to the wasted channel
* utillization, this computed through time wasted in errors
*/
reg_ofdm_phyerr_cu = reg_ofdm_phyerr_delta *
dcs_host_params.phy_err_penalty;
total_wasted_cu +=
(reg_ofdm_phyerr_cu > 0) ?
(((reg_ofdm_phyerr_cu >> 8) * 100) / (reg_tsf_delta >> 8)) : 0;
ofdm_phy_err_rate = (curr_stats->mib_stats.reg_ofdm_phyerr_cnt * 1000) /
curr_stats->mib_stats.listen_time;
cck_phy_err_rate = (curr_stats->mib_stats.reg_cck_phyerr_cnt * 1000) /
curr_stats->mib_stats.listen_time;
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_VERBOSE)) {
dcs_debug("reg_unused_cu: %u, reg_ofdm_phyerr_delta: %u, reg_cck_phyerr_delta: %u, reg_ofdm_phyerr_cu: %u",
reg_unused_cu, reg_ofdm_phyerr_delta,
reg_cck_phyerr_delta, reg_ofdm_phyerr_cu);
dcs_debug("total_wasted_cu: %u, ofdm_phy_err_rate: %u, cck_phy_err_rate: %u",
total_wasted_cu, ofdm_phy_err_rate, cck_phy_err_rate);
dcs_debug("new_unused_cu: %u, reg_ofdm_phy_error_cu: %u",
reg_unused_cu,
(curr_stats->mib_stats.reg_ofdm_phyerr_cnt * 100) /
curr_stats->mib_stats.listen_time);
}
/* Check if the error rates are higher than the thresholds */
max_phy_err_rate = QDF_MAX(ofdm_phy_err_rate, cck_phy_err_rate);
max_phy_err_count = QDF_MAX(curr_stats->mib_stats.reg_ofdm_phyerr_cnt,
curr_stats->mib_stats.reg_cck_phyerr_cnt);
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_VERBOSE))
dcs_debug("max_phy_err_rate: %u, max_phy_err_count: %u",
max_phy_err_rate, max_phy_err_count);
if (((max_phy_err_rate >= dcs_host_params.phy_err_threshold) &&
(max_phy_err_count > dcs_host_params.phy_err_threshold)) ||
(curr_stats->phyerr_cnt > dcs_host_params.radar_err_threshold))
too_many_phy_errors = 1;
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_CRITICAL)) {
dcs_debug("total_cu: %u, tx_cu: %u, rx_cu: %u, rx_time_cu: %u, unused cu: %u",
reg_total_cu, reg_tx_cu,
reg_rx_cu, rx_time_cu, reg_unused_cu);
dcs_debug("phyerr: %u, total_wasted_cu: %u, phyerror_cu: %u, wasted_cu: %u, reg_tx_cu: %u, reg_rx_cu: %u",
too_many_phy_errors, total_wasted_cu,
reg_ofdm_phyerr_cu, wasted_tx_cu,
reg_tx_cu, reg_rx_cu);
dcs_debug("tx_err: %u", tx_err);
}
if (reg_unused_cu >= dcs_host_params.coch_intfr_threshold)
/* Quickly reach to decision */
dcs_im_stats.im_intfr_cnt += 2;
else if (too_many_phy_errors &&
(((total_wasted_cu >
(dcs_host_params.coch_intfr_threshold + 10)) &&
((reg_tx_cu + reg_rx_cu) > dcs_host_params.user_max_cu)) ||
((reg_tx_cu > DCS_TX_MAX_CU) &&
(tx_err >= dcs_host_params.tx_err_threshold))))
dcs_im_stats.im_intfr_cnt++;
if (dcs_im_stats.im_intfr_cnt >=
dcs_host_params.intfr_detection_threshold) {
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_CRITICAL)) {
dcs_debug("interference threshold exceeded");
dcs_debug("unused_cu: %u, too_any_phy_errors: %u, total_wasted_cu: %u, reg_tx_cu: %u, reg_rx_cu: %u",
reg_unused_cu, too_many_phy_errors,
total_wasted_cu, reg_tx_cu, reg_rx_cu);
}
dcs_im_stats.im_intfr_cnt = 0;
dcs_im_stats.im_samp_cnt = 0;
/*
* Once the interference is detected, change the channel, as on
* today this is common routine for wirelesslan and
* non-wirelesslan interference. Name as such kept the same
* because of the DA code, which is using the same function.
*/
start_dcs_cbk_handler = true;
} else if (!dcs_im_stats.im_intfr_cnt ||
dcs_im_stats.im_samp_cnt >=
dcs_host_params.intfr_detection_window) {
dcs_im_stats.im_intfr_cnt = 0;
dcs_im_stats.im_samp_cnt = 0;
}
/* Count the current run too */
dcs_im_stats.im_samp_cnt++;
/* Copy the stats for next cycle */
wlan_dcs_im_copy_stats(prev_stats, curr_stats);
if (unlikely(dcs_host_params.dcs_debug >= DCS_DEBUG_VERBOSE))
dcs_debug("intfr_count: %u, sample_count: %u",
dcs_im_stats.im_intfr_cnt, dcs_im_stats.im_samp_cnt);
end:
return start_dcs_cbk_handler;
}
void wlan_dcs_disable_timer_fn(void *dcs_timer_args)
{
struct pdev_dcs_timer_args *dcs_timer_args_ctx;
struct wlan_objmgr_psoc *psoc;
uint32_t pdev_id;
struct dcs_psoc_priv_obj *dcs_psoc_priv;
struct dcs_pdev_priv_obj *dcs_pdev_priv;
if (!dcs_timer_args) {
dcs_err("dcs timer args is null");
return;
}
dcs_timer_args_ctx = (struct pdev_dcs_timer_args *)dcs_timer_args;
psoc = dcs_timer_args_ctx->psoc;
pdev_id = dcs_timer_args_ctx->pdev_id;
dcs_psoc_priv =
wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_DCS);
if (!dcs_psoc_priv) {
dcs_err("dcs psoc private object is null");
return;
}
dcs_pdev_priv = &dcs_psoc_priv->dcs_pdev_priv[pdev_id];
qdf_mem_set(&dcs_pdev_priv->dcs_im_stats,
sizeof(dcs_pdev_priv->dcs_im_stats), 0);
dcs_pdev_priv->dcs_freq_ctrl_params.disable_delay_process = false;
dcs_info("dcs disable timeout, enable dcs detection again");
wlan_dcs_cmd_send(psoc, pdev_id, true);
}
/**
* wlan_dcs_frequency_control() - dcs frequency control handling
* @psoc: psoc pointer
* @dcs_pdev_priv: dcs pdev priv pointer
* @event: dcs stats event pointer
*
* Return: none
*/
static void wlan_dcs_frequency_control(struct wlan_objmgr_psoc *psoc,
struct dcs_pdev_priv_obj *dcs_pdev_priv,
struct dcs_stats_event *event)
{
struct dcs_psoc_priv_obj *dcs_psoc_priv;
struct pdev_dcs_freq_ctrl_params *dcs_freq_ctrl_params;
uint8_t timestamp_pos;
unsigned long current_time;
uint8_t delta_pos;
unsigned long delta_time;
bool disable_dcs_sometime = false;
if (!psoc || !dcs_pdev_priv || !event) {
dcs_err("psoc or dcs_pdev_priv or event is null");
return;
}
dcs_freq_ctrl_params = &dcs_pdev_priv->dcs_freq_ctrl_params;
if (dcs_freq_ctrl_params->disable_delay_process) {
dcs_err("In the process of dcs disable, shouldn't go to here");
return;
}
current_time = qdf_get_system_timestamp();
if (dcs_freq_ctrl_params->dcs_happened_count >=
dcs_freq_ctrl_params->disable_threshold_per_5mins) {
delta_pos =
dcs_freq_ctrl_params->dcs_happened_count -
dcs_freq_ctrl_params->disable_threshold_per_5mins;
delta_pos = delta_pos % MAX_DCS_TIME_RECORD;
delta_time = current_time -
dcs_freq_ctrl_params->timestamp[delta_pos];
if (delta_time < DCS_FREQ_CONTROL_TIME)
disable_dcs_sometime = true;
}
if (!disable_dcs_sometime) {
timestamp_pos = dcs_freq_ctrl_params->dcs_happened_count %
MAX_DCS_TIME_RECORD;
dcs_freq_ctrl_params->timestamp[timestamp_pos] = current_time;
dcs_freq_ctrl_params->dcs_happened_count++;
}
/*
* Before start dcs callback handler or disable dcs for some time,
* need to send dcs command to disable dcs detection firstly.
*/
wlan_dcs_disable_cmd_send(psoc, event->dcs_param.pdev_id, true);
if (disable_dcs_sometime) {
dcs_freq_ctrl_params->disable_delay_process = true;
dcs_pdev_priv->dcs_timer_args.psoc = psoc;
dcs_pdev_priv->dcs_timer_args.pdev_id =
event->dcs_param.pdev_id;
qdf_timer_start(&dcs_pdev_priv->dcs_disable_timer,
dcs_pdev_priv->dcs_freq_ctrl_params.
restart_delay * 60 * 1000);
dcs_info("start dcs disable timer");
} else {
dcs_psoc_priv = wlan_objmgr_psoc_get_comp_private_obj(
psoc,
WLAN_UMAC_COMP_DCS);
if (!dcs_psoc_priv) {
dcs_err("dcs private psoc object is null");
return;
}
dcs_info("start dcs callback handler");
dcs_psoc_priv->dcs_cbk.cbk(psoc, event->dcs_param.pdev_id,
event->dcs_param.interference_type,
dcs_psoc_priv->dcs_cbk.arg);
}
}
QDF_STATUS
wlan_dcs_process(struct wlan_objmgr_psoc *psoc, struct dcs_stats_event *event)
{
struct dcs_pdev_priv_obj *dcs_pdev_priv;
bool start_dcs_cbk_handler = false;
if (!psoc || !event) {
dcs_err("psoc or event is NULL");
return QDF_STATUS_E_INVAL;
}
dcs_pdev_priv = wlan_dcs_get_pdev_private_obj(psoc,
event->dcs_param.pdev_id);
if (!dcs_pdev_priv) {
dcs_err("dcs pdev private object is null");
return QDF_STATUS_E_INVAL;
}
if (unlikely(dcs_pdev_priv->dcs_host_params.dcs_debug
>= DCS_DEBUG_VERBOSE))
dcs_debug("dcs_enable: %u, interference_type: %u",
dcs_pdev_priv->dcs_host_params.dcs_enable,
event->dcs_param.interference_type);
if (!dcs_pdev_priv->dcs_host_params.dcs_enable)
return QDF_STATUS_SUCCESS;
switch (event->dcs_param.interference_type) {
case CAP_DCS_CWIM:
break;
case CAP_DCS_WLANIM:
if (dcs_pdev_priv->dcs_host_params.dcs_enable & CAP_DCS_WLANIM)
start_dcs_cbk_handler =
wlan_dcs_wlan_interference_process(
&event->wlan_stat,
dcs_pdev_priv);
if (start_dcs_cbk_handler)
wlan_dcs_frequency_control(psoc,
dcs_pdev_priv,
event);
break;
default:
dcs_err("unidentified interference type reported");
break;
}
return QDF_STATUS_SUCCESS;
}

227
umac/dcs/core/src/wlan_dcs.h Fichier normal
Voir le fichier

@@ -0,0 +1,227 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: This file has main dcs structures definition.
*/
#ifndef _WLAN_DCS_H_
#define _WLAN_DCS_H_
#include <wmi_unified_param.h>
#include "wlan_dcs_tgt_api.h"
#include "wlan_dcs_ucfg_api.h"
#define dcs_debug(args ...) \
QDF_TRACE_DEBUG(QDF_MODULE_ID_DCS, ## args)
#define dcs_info(args ...) \
QDF_TRACE_INFO(QDF_MODULE_ID_DCS, ## args)
#define dcs_err(args ...) \
QDF_TRACE_ERROR(QDF_MODULE_ID_DCS, ## args)
#define DCS_TX_MAX_CU 30
#define MAX_DCS_TIME_RECORD 10
#define DCS_FREQ_CONTROL_TIME (5 * 60 * 1000)
/**
* enum wlan_dcs_debug_level - dcs debug trace level
* @DCS_DEBUG_DISABLE: disable debug trace
* @DCS_DEBUG_CRITICAL: critical debug trace level
* @DCS_DEBUG_VERBOSE: verbose debug trace level
*/
enum wlan_dcs_debug_level {
DCS_DEBUG_DISABLE = 0,
DCS_DEBUG_CRITICAL = 1,
DCS_DEBUG_VERBOSE = 2
};
/**
* struct pdev_dcs_im_stats - define dcs interference mitigation
* stats in pdev object
* @prev_dcs_im_stats: previous statistics at last time
* @im_intfr_cnt: number of times the interference is
* detected within detection window
* @im_sample_cnt: sample counter
*/
struct pdev_dcs_im_stats {
struct wlan_host_dcs_im_tgt_stats prev_dcs_im_stats;
uint8_t im_intfr_cnt;
uint8_t im_samp_cnt;
};
/**
* struct pdev_dcs_params - define dcs configuration parameter in pdev object
* @dcs_enable_cfg: dcs enable from ini config
* @dcs_enable: dcs enable from ucfg config
* @dcs_debug: dcs debug trace level
* @phy_err_penalty: phy error penalty
* @phy_err_threshold: phy error threshold
* @radar_err_threshold: radar error threshold
* @coch_intfr_threshold: co-channel interference threshold
* @user_max_cu: tx channel utilization due to AP's tx and rx
* @intfr_detection_threshold: interference detection threshold
* @intfr_detection_window: interference sampling window
* @tx_err_threshold: transmission failure rate threshold
*/
struct pdev_dcs_params {
uint8_t dcs_enable_cfg;
uint8_t dcs_enable;
enum wlan_dcs_debug_level dcs_debug;
uint32_t phy_err_penalty;
uint32_t phy_err_threshold;
uint32_t radar_err_threshold;
uint32_t coch_intfr_threshold;
uint32_t user_max_cu;
uint32_t intfr_detection_threshold;
uint32_t intfr_detection_window;
uint32_t tx_err_threshold;
};
/**
* struct pdev_dcs_freq_ctrl_params - define dcs frequency control parameter
* in pdebv object
* @disable_threshold_per_5mins: in five minutes, if dcs happen more than
* threshold, then disable dcs for some time
* @restart_delay: when dcs happen more than threshold in five minutes,
* then start to disable dcs for restart_delay minutes
* @timestamp: record dcs happened timestamp
* @dcs_happened_count: dcs happened count
* @disable_delay_process: in dcs disable delay process or not
*/
struct pdev_dcs_freq_ctrl_params {
uint8_t disable_threshold_per_5mins;
uint32_t restart_delay;
unsigned long timestamp[MAX_DCS_TIME_RECORD];
unsigned long dcs_happened_count;
bool disable_delay_process;
};
/**
* struct pdev_dcs_timer_args - define pdev dcs timer args
* @psoc: psoc pointer
* @pdev_id: pdev id
*/
struct pdev_dcs_timer_args {
struct wlan_objmgr_psoc *psoc;
uint32_t pdev_id;
};
/**
* struct psoc_dcs_cbk - define dcs callback in psoc oject
* @cbk: callback
* @arg: arguments
*/
struct psoc_dcs_cbk {
dcs_callback cbk;
void *arg;
};
/**
* struct dcs_pdev_priv_obj - define dcs pdev priv
* @dcs_host_params: dcs host configuration parameter
* @dcs_im_stats: dcs im statistics
* @dcs_freq_ctrl_params: dcs frequency control parameter
* @dcs_disable_timer: dcs disable timer
* @dcs_timer_args: dcs disable timer args
*/
struct dcs_pdev_priv_obj {
struct pdev_dcs_params dcs_host_params;
struct pdev_dcs_im_stats dcs_im_stats;
struct pdev_dcs_freq_ctrl_params dcs_freq_ctrl_params;
qdf_timer_t dcs_disable_timer;
struct pdev_dcs_timer_args dcs_timer_args;
};
/**
* struct dcs_psoc_priv_obj - define dcs psoc priv
* @dcs_pdev_priv: dcs pdev priv
* @dcs_cbk: dcs callback
*/
struct dcs_psoc_priv_obj {
struct dcs_pdev_priv_obj dcs_pdev_priv[WLAN_UMAC_MAX_PDEVS];
struct psoc_dcs_cbk dcs_cbk;
};
/**
* wlan_dcs_get_pdev_private_obj() - get dcs pdev private object
* @psoc: psoc pointer
* @pdev_id: pdev_id
*
* API to retrieve the pdev private object from the psoc context
*
* Return: pdev private object pointer on success, NULL on error
*/
struct dcs_pdev_priv_obj *
wlan_dcs_get_pdev_private_obj(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id);
/**
* wlan_dcs_attach() - Attach dcs handler
* @psoc: psoc pointer
*
* This function gets called to register dcs FW events handler
*
* Return: QDF_STATUS
*/
QDF_STATUS wlan_dcs_attach(struct wlan_objmgr_psoc *psoc);
/**
* wlan_dcs_detach() - Detach dcs handler
* @psoc: psoc pointer
*
* This function gets called to unregister dcs FW events handler
*
* Return: QDF_STATUS
*/
QDF_STATUS wlan_dcs_detach(struct wlan_objmgr_psoc *psoc);
/**
* wlan_dcs_cmd_send() - Send dcs command to target_if layer
* @psoc: psoc pointer
* @pdev_id: pdev_id
* @is_target_pdev_id: pdev_id is target id or not
*
* The function gets called to send dcs command to FW
*
* return: QDF_STATUS_SUCCESS for success or error code
*/
QDF_STATUS wlan_dcs_cmd_send(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
bool is_target_pdev_id);
/**
* wlan_dcs_process() - dcs process main entry
* @psoc: psoc pointer
* @event: dcs stats event pointer
*
* This function is the main entry to do dcs related operation
* such as algorithm handling and dcs frequency control.
*
* Return: QDF_STATUS
*/
QDF_STATUS wlan_dcs_process(struct wlan_objmgr_psoc *psoc,
struct dcs_stats_event *event);
/**
* wlan_dcs_disable_timer_fn() - dcs disable timer callback
* @dcs_timer_args: dcs timer argument pointer
*
* This function gets called when dcs disable timer timeout
*
* Return: None
*/
void wlan_dcs_disable_timer_fn(void *dcs_timer_args);
#endif /* _WLAN_DCS_H_ */

Voir le fichier

@@ -0,0 +1,309 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: This file contains centralized definitions of DCS component
*/
#ifndef __CONFIG_DCS_H
#define __CONFIG_DCS_H
#include "cfg_define.h"
/*
* <ini>
* gEnableDcs - Enable/Disable DCS
* @Min: 0
* @Max: 3
* @Default: 0
*
* This ini is used to enable/disable DCS. Configurations are as follows:
* 0 - Disable DCS.
* 1 - Enable DCS for CW interference mitigation(CW_IM).
* 2 - Enable DCS for WLAN interference mitigation(WLAN_IM).
* 3 - Enable both DCS for CW_IM and DCS for WLAN_IM.
*
* Related: None
*
* Supported Feature: DCS
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_ENABLE CFG_INI_UINT(\
"gEnableDcs",\
0, 3, 0,\
CFG_VALUE_OR_DEFAULT, "Enable DCS")
/*
* <ini>
* dcs_debug - Configure dcs debug trace level for debug purpose
* @Min: 0
* @Max: 2
* @Default: 0
*
* This ini is used to configure dcs debug trace level for debug purpose
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_DEBUG CFG_INI_UINT(\
"dcs_debug",\
0, 2, 0,\
CFG_VALUE_OR_DEFAULT,\
"dcs debug trace level")
/*
* <ini>
* dcs_coch_intfr_threshold - Configure co-channel interference threshold
* @Min: 0
* @Max: 0xFFFFFFFF
* @Default: 30
*
* This ini is used to configure co-channel interference threshold
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_COCH_INTFR_THRESHOLD CFG_INI_UINT(\
"dcs_coch_intfr_threshold",\
0, 0xFFFFFFFF, 30,\
CFG_VALUE_OR_DEFAULT,\
"dcs co-channel interference threshold level")
/*
* <ini>
* dcs_tx_err_threshold - Configure transmission failure rate threshold
* @Min: 0
* @Max: 0xFFFFFFFF
* @Default: 30
*
* This ini is used to configure transmission failure rate threshold
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_TX_ERR_THRESHOLD CFG_INI_UINT(\
"dcs_tx_err_threshold",\
0, 0xFFFFFFFF, 30,\
CFG_VALUE_OR_DEFAULT,\
"dcs transmission failure rate threshold")
/*
* <ini>
* dcs_phy_err_penalty - Configure channel time wasted due to each Phy
* error(phy error penalty)
* @Min: 0
* @Max: 0xFFFFFFFF
* @Default: 500
*
* This ini is used to configure phy error penalty
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_PHY_ERR_PENALTY CFG_INI_UINT(\
"dcs_phy_err_penalty",\
0, 0xFFFFFFFF, 500,\
CFG_VALUE_OR_DEFAULT,\
"dcs phy error penalty")
/*
* <ini>
* dcs_phy_err_threshold - Configure phy err threshold
* @Min: 0
* @Max: 0xFFFFFFFF
* @Default: 300
*
* This ini is used to configure phy error threshold
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_PHY_ERR_THRESHOLD CFG_INI_UINT(\
"dcs_phy_err_threshold",\
0, 0xFFFFFFFF, 300,\
CFG_VALUE_OR_DEFAULT,\
"dcs phy error threshold")
/*
* <ini>
* dcs_user_max_cu - Configure tx channel utilization due to AP's tx and rx
* @Min: 0
* @Max: 0xFFFFFFFF
* @Default: 50
*
* This ini is used to configure tx channel utilization due to AP's tx and rx
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_USER_MAX_CU CFG_INI_UINT(\
"user_max_cu",\
0, 0xFFFFFFFF, 50,\
CFG_VALUE_OR_DEFAULT,\
"dcs tx channel utilization")
/*
* <ini>
* dcs_radar_err_threshold - Configure radar error threshold
* @Min: 0
* @Max: 0xFFFFFFFF
* @Default: 1000
*
* This ini is used to configure radar error threshold
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_RADAR_ERR_THRESHOLD CFG_INI_UINT(\
"dcs_radar_err_threshold",\
0, 0xFFFFFFFF, 1000,\
CFG_VALUE_OR_DEFAULT,\
"dcs radar error threshold")
/*
* <ini>
* dcs_intfr_detection_threshold - Configure interference detection threshold
* @Min: 0
* @Max: 0xFFFFFFFF
* @Default: 6
*
* This ini is used to configure interference detection threshold
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_INTFR_DETECTION_THRESHOLD CFG_INI_UINT(\
"dcs_intfr_detection_threshold",\
0, 0xFFFFFFFF, 6,\
CFG_VALUE_OR_DEFAULT,\
"dcs interference detection threshold")
/*
* <ini>
* dcs_intfr_detection_window - Configure interference sampling window
* @Min: 0
* @Max: 0xFFFFFFFF
* @Default: 10
*
* This ini is used to configure interference sampling window
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_INTFR_DETECTION_WINDOW CFG_INI_UINT(\
"dcs_intfr_detection_window",\
0, 0xFFFFFFFF, 10,\
CFG_VALUE_OR_DEFAULT,\
"dcs interference sampling window")
/*
* <ini>
* dcs_disable_threshold_per_5mins - In five minutes, if dcs happen
* more than threshold, then disable dcs for some time
* @Min: 0
* @Max: 10
* @Default: 3
*
* This ini is used to dcs happen times threshold in five minutes
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_DISABLE_THRESHOLD_PER_5MINS CFG_INI_UINT(\
"dcs_disable_thresh_per_5mins",\
0, 10, 3,\
CFG_VALUE_OR_DEFAULT,\
"dcs happen times threshold in five minutes")
/*
* <ini>
* dcs_restart_delay - When dcs happen more than threshold in five minutes,
* then start to disable dcs for some minutes, then enable dcs again.
* @Min: 0
* @Max: 0xFFFFFFFF
* @Default: 30
*
* This ini is used to configure dcs disable time length in minute unit
*
*
* Related: None
*
* Usage: External
*
* </ini>
*/
#define CFG_DCS_RESTART_DELAY CFG_INI_UINT(\
"dcs_restart_delay",\
0, 0xFFFFFFFF, 30,\
CFG_VALUE_OR_DEFAULT, "dcs restart delay")
#define CFG_DCS_ALL \
CFG(CFG_DCS_ENABLE) \
CFG(CFG_DCS_DEBUG) \
CFG(CFG_DCS_COCH_INTFR_THRESHOLD) \
CFG(CFG_DCS_TX_ERR_THRESHOLD) \
CFG(CFG_DCS_PHY_ERR_PENALTY) \
CFG(CFG_DCS_PHY_ERR_THRESHOLD) \
CFG(CFG_DCS_USER_MAX_CU) \
CFG(CFG_DCS_RADAR_ERR_THRESHOLD) \
CFG(CFG_DCS_INTFR_DETECTION_THRESHOLD) \
CFG(CFG_DCS_INTFR_DETECTION_WINDOW) \
CFG(CFG_DCS_DISABLE_THRESHOLD_PER_5MINS) \
CFG(CFG_DCS_RESTART_DELAY)
#endif /* __CONFIG_DCS_H */

Voir le fichier

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: wlan_dcs_init_deinit_api.h
*
* This header file provide declaration to public APIs exposed for other UMAC
* components to init/deinit, (de)register to required WMI events on
* soc enable/disable
*/
#ifndef __WLAN_DCS_INIT_DEINIT_API_H__
#define __WLAN_DCS_INIT_DEINIT_API_H__
#ifdef DCS_INTERFERENCE_DETECTION
#include <qdf_types.h>
#include <qdf_status.h>
#include <wlan_objmgr_cmn.h>
/**
* wlan_dcs_init(): API to init dcs component
*
* This API is invoked from dispatcher init during all component init.
* This API will register all required handlers for pdev object
* create/delete notification.
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
*/
QDF_STATUS wlan_dcs_init(void);
/**
* wlan_dcs_deinit(): API to deinit dcs component
*
* This API is invoked from dispatcher deinit during all component deinit.
* This API will unregister all required handlers for pdev object
* create/delete notification.
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
*/
QDF_STATUS wlan_dcs_deinit(void);
/**
* wlan_dcs_enable(): API to enable dcs component
* @psoc: pointer to psoc
*
* This API is invoked from dispatcher psoc enable.
* This API will register dcs WMI event handlers.
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
*/
QDF_STATUS wlan_dcs_enable(struct wlan_objmgr_psoc *psoc);
/**
* wlan_dcs_disable(): API to disable dcs component
* @psoc: pointer to psoc
*
* This API is invoked from dispatcher psoc disable.
* This API will unregister dcs WMI event handlers.
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
*/
QDF_STATUS wlan_dcs_disable(struct wlan_objmgr_psoc *psoc);
/**
* wlan_dcs_psoc_open() - Dcs psoc open handler
* @psoc: pointer to psoc object
*
* API to execute operations on psoc open
*
* Return: QDF_STATUS_SUCCESS upon successful registration,
* QDF_STATUS_E_FAILURE upon failure
*/
QDF_STATUS wlan_dcs_psoc_open(struct wlan_objmgr_psoc *psoc);
#endif /* DCS_INTERFERENCE_DETECTION */
#endif /* __WLAN_DCS_INIT_DEINIT_API_H__ */

Voir le fichier

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: contains dcs structure definations
*/
#ifndef _WLAN_DCS_PUBLIC_STRUCTS_H_
#define _WLAN_DCS_PUBLIC_STRUCTS_H_
/**
* struct wlan_host_dcs_interference_param - dcs interference parameters
* @interference_type: type of DCS interference
* @uint32_t pdev_id: pdev id
*/
struct wlan_host_dcs_interference_param {
uint32_t interference_type;
uint32_t pdev_id;
};
/**
* struct wlan_host_dcs_mib_stats - WLAN IM stats from target to host
* @listen_time:
* @reg_tx_frame_cnt:
* @reg_rx_frame_cnt:
* @reg_rxclr_cnt:
* @reg_cycle_cnt: delta cycle count
* @reg_rxclr_ext_cnt:
* @reg_ofdm_phyerr_cnt:
* @reg_cck_phyerr_cnt: CCK err count since last reset, read from register
*/
struct wlan_host_dcs_mib_stats {
int32_t listen_time;
uint32_t reg_tx_frame_cnt;
uint32_t reg_rx_frame_cnt;
uint32_t reg_rxclr_cnt;
uint32_t reg_cycle_cnt;
uint32_t reg_rxclr_ext_cnt;
uint32_t reg_ofdm_phyerr_cnt;
uint32_t reg_cck_phyerr_cnt;
};
/**
* struct wlan_host_dcs_im_tgt_stats - DCS IM target stats
* @reg_tsf32: current running TSF from the TSF-1
* @last_ack_rssi: known last frame rssi, in case of multiple stations, if
* and at different ranges, this would not gaurantee that
* this is the least rssi.
* @tx_waste_time: sum of all the failed durations in the last
* one second interval.
* @rx_time: count how many times the hal_rxerr_phy is marked, in this
* time period
* @phyerr_cnt:
* @mib_stats: collected mib stats as explained in mib structure
* @chan_nf: Channel noise floor (units are in dBm)
* @my_bss_rx_cycle_count: BSS rx cycle count
* @reg_rxclr_ext40_cnt: extension channel 40Mhz rxclear count
* @reg_rxclr_ext80_cnt: extension channel 80Mhz rxclear count
*/
struct wlan_host_dcs_im_tgt_stats {
uint32_t reg_tsf32;
uint32_t last_ack_rssi;
uint32_t tx_waste_time;
uint32_t rx_time;
uint32_t phyerr_cnt;
struct wlan_host_dcs_mib_stats mib_stats;
uint32_t chan_nf;
uint32_t my_bss_rx_cycle_count;
uint32_t reg_rxclr_ext40_cnt;
uint32_t reg_rxclr_ext80_cnt;
};
#endif

Voir le fichier

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: wlan_dcs_tgt_api.h
*
* This header file provide with API declarations to interface with Southbound
*/
#ifndef __WLAN_DCS_TGT_API_H__
#define __WLAN_DCS_TGT_API_H__
#include <wlan_objmgr_cmn.h>
#include <wlan_dcs_public_structs.h>
/**
* struct dcs_stats_event - define dcs stats event
* @wlan_stat: wlan interference target statistics
* @dcs_param: dcs event param
*/
struct dcs_stats_event {
struct wlan_host_dcs_im_tgt_stats wlan_stat;
struct wlan_host_dcs_interference_param dcs_param;
};
/**
* tgt_dcs_process_event(): dcs FW event process
* @psoc: pointer to psoc object
* @event: pointer to dcs stats event
*
* This function gets called to process dcs FW event
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_dcs_process_event(struct wlan_objmgr_psoc *psoc,
struct dcs_stats_event *event);
#endif /* __WLAN_DCS_TGT_API_H__ */

Voir le fichier

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: This file has the dcs dispatcher API which is exposed to outside of dcs
* component.
*/
#ifndef _WLAN_DCS_UCFG_API_H_
#define _WLAN_DCS_UCFG_API_H_
#include <qdf_status.h>
#include <wlan_objmgr_pdev_obj.h>
/**
* @brief List of DCS capabilities that can be set or unset
* dynamically
* @see UMAC auto channel selection document for details on each feature
*
*/
#define CAP_DCS_CWIM 0x1
#define CAP_DCS_WLANIM 0x2
#define CAP_DCS_MASK (CAP_DCS_CWIM | CAP_DCS_WLANIM)
/**
* typedef dcs_callback() - DCS callback
* @psoc: Pointer to psoc
* @pdev_id: pdev id
* @interference_type: interference type
* @arg: list of arguments
*/
typedef void (*dcs_callback)(
struct wlan_objmgr_psoc *psoc,
uint8_t pdev_id,
uint8_t interference_type,
void *arg);
/**
* ucfg_dcs_register_cb() - API to register dcs callback
* @psoc: pointer to psoc object
* @cbk: dcs callback to be registered
* @arg: argument
*
* This function gets called to register dcs callback function
*
* Return: None
*/
void ucfg_dcs_register_cb(
struct wlan_objmgr_psoc *psoc,
dcs_callback cbk,
void *arg);
/**
* ucfg_wlan_dcs_cmd(): API to send dcs command
* @psoc: pointer to psoc object
* @pdev_id: pdev_id
* @is_target_pdev_id: pdev_id is target id or not
*
* This function gets called to send dcs command
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
*/
QDF_STATUS
ucfg_wlan_dcs_cmd(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
bool is_target_pdev_id);
/**
* ucfg_config_dcs_enable() - API to config dcs enable
* @psoc: pointer to psoc object
* @pdev_id: pdev id
* @interference_type: CAP_DCS_CWIM, CAP_DCS_WLANIM, CAP_DCS_MASK
*
* This function gets called to config dcs enable
*
* Return: None
*/
void ucfg_config_dcs_enable(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
uint8_t interference_type);
/**
* ucfg_config_dcs_disable() - API to config dcs disable
* @psoc: pointer to psoc object
* @pdev_id: pdev id
* @interference_type: CAP_DCS_CWIM, CAP_DCS_WLANIM, CAP_DCS_MASK
*
* This function gets called to config dcs disable
*
* Return: None
*/
void ucfg_config_dcs_disable(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
uint8_t interference_type);
/**
* ucfg_get_dcs_enable() - API to get dcs enable
* @psoc: pointer to psoc object
* @pdev_id: pdev id
*
* This function gets called to get current host
* config dcs enable/disable status
*
* Return: WLANIM/CWIM enable status
*/
uint8_t ucfg_get_dcs_enable(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id);
#endif /* _WLAN_DCS_UCFG_API_H_ */

Voir le fichier

@@ -0,0 +1,210 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: This file init/deint functions for dcs module.
*/
#include "wlan_dcs_init_deinit_api.h"
#include "../../core/src/wlan_dcs.h"
#include "wlan_dcs_cfg.h"
#include "cfg_ucfg_api.h"
/**
* wlan_dcs_psoc_obj_create_notification() - dcs psoc cretae handler
* @psoc: psoc object
* @arg_list: Argument list
*
* return: QDF_STATUS_SUCCESS for success or error code
*/
static QDF_STATUS
wlan_dcs_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc,
void *arg_list)
{
QDF_STATUS status;
struct dcs_psoc_priv_obj *dcs_psoc_obj;
dcs_psoc_obj = qdf_mem_malloc(sizeof(*dcs_psoc_obj));
if (!dcs_psoc_obj)
return QDF_STATUS_E_NOMEM;
status = wlan_objmgr_psoc_component_obj_attach(psoc,
WLAN_UMAC_COMP_DCS,
dcs_psoc_obj,
QDF_STATUS_SUCCESS);
if (QDF_IS_STATUS_ERROR(status)) {
dcs_err("dcs pdev obj attach failed");
qdf_mem_free(dcs_psoc_obj);
return status;
}
dcs_info("dcs psoc object attached");
return status;
}
/**
* wlan_dcs_psoc_obj_destroy_notification() - dcs psoc destroy handler
* @psoc: psoc object
* @arg_list: Argument list
*
* return: QDF_STATUS_SUCCESS for success or error code
*/
static QDF_STATUS
wlan_dcs_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc,
void *arg_list)
{
QDF_STATUS status;
uint8_t loop;
struct dcs_psoc_priv_obj *dcs_psoc_obj =
wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_DCS);
if (!dcs_psoc_obj) {
dcs_err("invalid wifi dcs obj");
return QDF_STATUS_E_FAULT;
}
status = wlan_objmgr_psoc_component_obj_detach(psoc,
WLAN_UMAC_COMP_DCS,
dcs_psoc_obj);
for (loop = 0; loop < WLAN_UMAC_MAX_PDEVS; loop++)
qdf_timer_free(&dcs_psoc_obj->dcs_pdev_priv[loop].
dcs_disable_timer);
qdf_mem_free(dcs_psoc_obj);
return status;
}
QDF_STATUS wlan_dcs_init(void)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = wlan_objmgr_register_psoc_create_handler(
WLAN_UMAC_COMP_DCS,
wlan_dcs_psoc_obj_create_notification,
NULL);
if (QDF_IS_STATUS_ERROR(status))
goto err_psoc_create;
status = wlan_objmgr_register_psoc_destroy_handler(
WLAN_UMAC_COMP_DCS,
wlan_dcs_psoc_obj_destroy_notification,
NULL);
if (QDF_IS_STATUS_ERROR(status))
goto err_psoc_delete;
return QDF_STATUS_SUCCESS;
err_psoc_delete:
wlan_objmgr_unregister_psoc_create_handler(
WLAN_UMAC_COMP_DCS,
wlan_dcs_psoc_obj_create_notification,
NULL);
err_psoc_create:
return status;
}
QDF_STATUS wlan_dcs_deinit(void)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = wlan_objmgr_unregister_psoc_create_handler(
WLAN_UMAC_COMP_DCS,
wlan_dcs_psoc_obj_create_notification,
NULL);
if (QDF_IS_STATUS_ERROR(status))
return QDF_STATUS_E_FAILURE;
status = wlan_objmgr_unregister_psoc_destroy_handler(
WLAN_UMAC_COMP_DCS,
wlan_dcs_psoc_obj_destroy_notification,
NULL);
if (QDF_IS_STATUS_ERROR(status))
return QDF_STATUS_E_FAILURE;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS wlan_dcs_enable(struct wlan_objmgr_psoc *psoc)
{
return wlan_dcs_attach(psoc);
}
QDF_STATUS wlan_dcs_disable(struct wlan_objmgr_psoc *psoc)
{
return wlan_dcs_detach(psoc);
}
QDF_STATUS wlan_dcs_psoc_open(struct wlan_objmgr_psoc *psoc)
{
struct dcs_psoc_priv_obj *dcs_psoc_obj;
struct dcs_pdev_priv_obj *dcs_pdev_priv;
uint8_t loop;
if (!psoc) {
dcs_err("psoc is NULL");
return QDF_STATUS_E_INVAL;
}
dcs_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
psoc, WLAN_UMAC_COMP_DCS);
if (!dcs_psoc_obj) {
dcs_err("dcs psoc private object is NULL");
return QDF_STATUS_E_FAILURE;
}
for (loop = 0; loop < WLAN_UMAC_MAX_PDEVS; loop++) {
dcs_pdev_priv = &dcs_psoc_obj->dcs_pdev_priv[loop];
dcs_pdev_priv->dcs_host_params.dcs_enable_cfg =
cfg_get(psoc, CFG_DCS_ENABLE);
dcs_pdev_priv->dcs_host_params.dcs_debug =
cfg_get(psoc, CFG_DCS_DEBUG);
dcs_pdev_priv->dcs_host_params.phy_err_penalty =
cfg_get(psoc, CFG_DCS_PHY_ERR_PENALTY);
dcs_pdev_priv->dcs_host_params.phy_err_threshold =
cfg_get(psoc, CFG_DCS_PHY_ERR_THRESHOLD);
dcs_pdev_priv->dcs_host_params.radar_err_threshold =
cfg_get(psoc, CFG_DCS_RADAR_ERR_THRESHOLD);
dcs_pdev_priv->dcs_host_params.coch_intfr_threshold =
cfg_get(psoc, CFG_DCS_COCH_INTFR_THRESHOLD);
dcs_pdev_priv->dcs_host_params.user_max_cu =
cfg_get(psoc, CFG_DCS_USER_MAX_CU);
dcs_pdev_priv->dcs_host_params.intfr_detection_threshold =
cfg_get(psoc, CFG_DCS_INTFR_DETECTION_THRESHOLD);
dcs_pdev_priv->dcs_host_params.intfr_detection_window =
cfg_get(psoc, CFG_DCS_INTFR_DETECTION_WINDOW);
dcs_pdev_priv->dcs_host_params.tx_err_threshold =
cfg_get(psoc, CFG_DCS_TX_ERR_THRESHOLD);
dcs_pdev_priv->dcs_freq_ctrl_params.
disable_threshold_per_5mins =
cfg_get(psoc, CFG_DCS_DISABLE_THRESHOLD_PER_5MINS);
dcs_pdev_priv->dcs_freq_ctrl_params.restart_delay =
cfg_get(psoc, CFG_DCS_RESTART_DELAY);
qdf_timer_init(NULL, &dcs_pdev_priv->dcs_disable_timer,
wlan_dcs_disable_timer_fn,
&dcs_pdev_priv->dcs_timer_args,
QDF_TIMER_TYPE_WAKE_APPS);
}
return QDF_STATUS_SUCCESS;
}

Voir le fichier

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC:wlan_dcs_tgt_api.c
*
* This file provide API definitions to update dcs from southbound interface
*/
#include "wlan_dcs_tgt_api.h"
#include "../../core/src/wlan_dcs.h"
QDF_STATUS tgt_dcs_process_event(struct wlan_objmgr_psoc *psoc,
struct dcs_stats_event *event)
{
return wlan_dcs_process(psoc, event);
}

Voir le fichier

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: This file has the dcs dispatcher API implementation which is exposed
* to outside of dcs component.
*/
#include "wlan_dcs_ucfg_api.h"
#include "../../core/src/wlan_dcs.h"
void ucfg_dcs_register_cb(
struct wlan_objmgr_psoc *psoc,
dcs_callback cbk,
void *arg)
{
struct dcs_psoc_priv_obj *dcs_psoc_priv;
dcs_psoc_priv = wlan_objmgr_psoc_get_comp_private_obj(
psoc,
WLAN_UMAC_COMP_DCS);
if (!dcs_psoc_priv) {
dcs_err("dcs psoc private object is null");
return;
}
dcs_psoc_priv->dcs_cbk.cbk = cbk;
dcs_psoc_priv->dcs_cbk.arg = arg;
}
QDF_STATUS
ucfg_wlan_dcs_cmd(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
bool is_target_pdev_id)
{
return wlan_dcs_cmd_send(psoc, pdev_id, is_target_pdev_id);
}
void ucfg_config_dcs_enable(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
uint8_t interference_type)
{
struct dcs_pdev_priv_obj *dcs_pdev_priv;
dcs_pdev_priv = wlan_dcs_get_pdev_private_obj(psoc, pdev_id);
if (!dcs_pdev_priv) {
dcs_err("dcs pdev private object is null");
return;
}
dcs_pdev_priv->dcs_host_params.dcs_enable |= interference_type;
}
void ucfg_config_dcs_disable(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
uint8_t interference_type)
{
struct dcs_pdev_priv_obj *dcs_pdev_priv;
dcs_pdev_priv = wlan_dcs_get_pdev_private_obj(psoc, pdev_id);
if (!dcs_pdev_priv) {
dcs_err("dcs pdev private object is null");
return;
}
dcs_pdev_priv->dcs_host_params.dcs_enable &= (~interference_type);
}
uint8_t ucfg_get_dcs_enable(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id)
{
struct dcs_pdev_priv_obj *dcs_pdev_priv;
dcs_pdev_priv = wlan_dcs_get_pdev_private_obj(psoc, pdev_id);
if (!dcs_pdev_priv) {
dcs_err("dcs pdev private object is null");
return 0;
}
return dcs_pdev_priv->dcs_host_params.dcs_enable;
}

Voir le fichier

@@ -82,6 +82,10 @@ struct dbr_module_config;
#include <wlan_vdev_mgr_tgt_if_tx_defs.h>
#include <wlan_vdev_mgr_tgt_if_rx_defs.h>
#ifdef DCS_INTERFERENCE_DETECTION
#include <wlan_dcs_tgt_api.h>
#endif
#ifdef QCA_SUPPORT_CP_STATS
/**
* struct wlan_lmac_if_cp_stats_tx_ops - defines southbound tx callbacks for
@@ -116,6 +120,33 @@ struct wlan_lmac_if_cp_stats_rx_ops {
};
#endif
#ifdef DCS_INTERFERENCE_DETECTION
/**
* struct wlan_target_if_dcs_tx_ops - south bound tx function pointers for dcs
* @dcs_attach: function to register event handlers with FW
* @dcs_detach: function to de-register event handlers with FW
* @dcs_cmd_send: function to send dcs commands to FW
*/
struct wlan_target_if_dcs_tx_ops {
QDF_STATUS (*dcs_attach)(struct wlan_objmgr_psoc *psoc);
QDF_STATUS (*dcs_detach)(struct wlan_objmgr_psoc *psoc);
QDF_STATUS (*dcs_cmd_send)(struct wlan_objmgr_psoc *psoc,
uint32_t pdev_id,
bool is_target_pdev_id,
uint32_t dcs_enable);
};
/**
* struct wlan_target_if_dcs_rx_ops - defines southbound rx callbacks for
* dcs component
* @process_dcs_event: function pointer to rx FW events
*/
struct wlan_target_if_dcs_rx_ops {
QDF_STATUS (*process_dcs_event)(struct wlan_objmgr_psoc *psoc,
struct dcs_stats_event *event);
};
#endif
/**
* struct wlan_lmac_if_mgmt_txrx_tx_ops - structure of tx function
* pointers for mgmt txrx component
@@ -963,6 +994,9 @@ struct wlan_lmac_if_tx_ops {
#ifdef QCA_SUPPORT_CP_STATS
struct wlan_lmac_if_cp_stats_tx_ops cp_stats_tx_ops;
#endif
#ifdef DCS_INTERFERENCE_DETECTION
struct wlan_target_if_dcs_tx_ops dcs_tx_ops;
#endif
#ifdef WLAN_SA_API_ENABLE
struct wlan_lmac_if_sa_api_tx_ops sa_api_tx_ops;
#endif
@@ -1652,6 +1686,9 @@ struct wlan_lmac_if_rx_ops {
#ifdef QCA_SUPPORT_CP_STATS
struct wlan_lmac_if_cp_stats_rx_ops cp_stats_rx_ops;
#endif
#ifdef DCS_INTERFERENCE_DETECTION
struct wlan_target_if_dcs_rx_ops dcs_rx_ops;
#endif
#ifdef WLAN_SA_API_ENABLE
struct wlan_lmac_if_sa_api_rx_ops sa_api_rx_ops;
#endif

Voir le fichier

@@ -108,6 +108,27 @@ wlan_lmac_if_cp_stats_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
}
#endif /* QCA_SUPPORT_CP_STATS */
#ifdef DCS_INTERFERENCE_DETECTION
/**
* wlan_target_if_dcs_rx_ops_register() - API to register dcs Rx Ops
* @rx_ops: pointer to lmac rx ops
*
* This API will be used to register function pointers for FW events
*
* Return: void
*/
static void
wlan_target_if_dcs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
{
rx_ops->dcs_rx_ops.process_dcs_event = tgt_dcs_process_event;
}
#else
static void
wlan_target_if_dcs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
{
}
#endif /* DCS_INTERFERENCE_DETECTION */
#ifdef WLAN_ATF_ENABLE
/**
* wlan_lmac_if_atf_rx_ops_register() - Function to register ATF RX ops.
@@ -653,6 +674,8 @@ wlan_lmac_if_umac_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
wlan_lmac_if_cp_stats_rx_ops_register(rx_ops);
wlan_target_if_dcs_rx_ops_register(rx_ops);
wlan_lmac_if_sa_api_rx_ops_register(rx_ops);
wlan_lmac_if_cfr_rx_ops_register(rx_ops);

75
wmi/inc/wmi_unified_dcs_api.h Fichier normal
Voir le fichier

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: This file contains the API definitions for the Unified Wireless Module
* Interface (WMI) which are specific to DFS module.
*/
#ifndef _WMI_UNIFIED_DCS_API_H_
#define _WMI_UNIFIED_DCS_API_H_
#include <qdf_status.h>
#include <wmi_unified_api.h>
#include <wmi_unified_priv.h>
#include <wlan_objmgr_vdev_obj.h>
/**
* wmi_extract_dcs_interference_type() - extract dcs interference type
* @wmi_handle: wmi handle
* @evt_buf: pointer to event buffer
* @param: Pointer to hold dcs interference param
*
* This function gets called to extract dcs interference type from dcs FW event
*
* Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
*/
QDF_STATUS wmi_extract_dcs_interference_type(
void *wmi_hdl,
void *evt_buf,
struct wlan_host_dcs_interference_param *param);
/**
* wmi_extract_dcs_im_tgt_stats() - extract dcs im target stats
* @wmi_handle: wmi handle
* @evt_buf: pointer to event buffer
* @wlan_stat: Pointer to hold wlan stats
*
* This function gets called to extract dcs im target stats from event
*
* Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
*/
QDF_STATUS wmi_extract_dcs_im_tgt_stats(
void *wmi_hdl,
void *evt_buf,
struct wlan_host_dcs_im_tgt_stats *wlan_stat);
/**
* wmi_send_dcs_pdev_param() - send dcs pdev param
* @wmi_handle: wmi handle
* @pdev_idx: pdev id
* @is_target_pdev_id: target pdev_id or not
* @dcs_enable: value of dcs enable
*
* This functions gets called to send dcs pdev param
*
* Return: QDF_STATUS
*/
QDF_STATUS wmi_send_dcs_pdev_param(wmi_unified_t wmi_handle,
uint32_t pdev_idx,
bool is_target_pdev_id,
uint32_t dcs_enable);
#endif /* _WMI_UNIFIED_DCS_API_H_ */

Voir le fichier

@@ -878,10 +878,12 @@ struct suspend_params {
* struct pdev_params - pdev set cmd parameter
* @param_id: parameter id
* @param_value: parameter value
* @is_target_pdev_id: indicate whether pdev_id is target pdev_id or not
*/
struct pdev_params {
uint32_t param_id;
uint32_t param_value;
bool is_target_pdev_id;
};
/**

Voir le fichier

@@ -69,6 +69,10 @@
#include <wmi_unified_cfr_param.h>
#endif
#ifdef DCS_INTERFERENCE_DETECTION
#include <wlan_dcs_public_structs.h>
#endif
#define WMI_UNIFIED_MAX_EVENT 0x100
#ifdef WMI_EXT_DBG
@@ -1433,6 +1437,17 @@ QDF_STATUS
QDF_STATUS (*extract_wds_addr_event)(wmi_unified_t wmi_handle,
void *evt_buf, uint16_t len, wds_addr_event_t *wds_ev);
#ifdef DCS_INTERFERENCE_DETECTION
QDF_STATUS (*extract_dcs_interference_type)(
wmi_unified_t wmi_handle,
void *evt_buf,
struct wlan_host_dcs_interference_param *param);
QDF_STATUS (*extract_dcs_im_tgt_stats)(
wmi_unified_t wmi_handle,
void *evt_buf,
struct wlan_host_dcs_im_tgt_stats *wlan_stat);
#else
QDF_STATUS (*extract_dcs_interference_type)(wmi_unified_t wmi_handle,
void *evt_buf, struct wmi_host_dcs_interference_param *param);
@@ -1441,6 +1456,7 @@ QDF_STATUS (*extract_dcs_cw_int)(wmi_unified_t wmi_handle, void *evt_buf,
QDF_STATUS (*extract_dcs_im_tgt_stats)(wmi_unified_t wmi_handle, void *evt_buf,
wmi_host_dcs_im_tgt_stats_t *wlan_stat);
#endif
QDF_STATUS (*extract_fips_event_data)(wmi_unified_t wmi_handle,
void *evt_buf, struct wmi_host_fips_event_param *param);
@@ -2477,6 +2493,15 @@ wmi_interop_issues_ap_attach_tlv(struct wmi_unified *wmi_handle)
}
#endif
#ifdef DCS_INTERFERENCE_DETECTION
void wmi_dcs_attach_tlv(wmi_unified_t wmi_handle);
#else
static inline void
wmi_dcs_attach_tlv(struct wmi_unified *wmi_handle)
{
}
#endif
#ifdef FEATURE_LFR_SUBNET_DETECTION
void wmi_lfr_subnet_detection_attach_tlv(wmi_unified_t wmi_handle);
#else

82
wmi/src/wmi_unified_dcs_api.c Fichier normal
Voir le fichier

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: Implement API's specific to DCS component.
*/
#include <wmi_unified_dcs_api.h>
QDF_STATUS wmi_extract_dcs_interference_type(
void *wmi_hdl,
void *evt_buf,
struct wlan_host_dcs_interference_param *param)
{
wmi_unified_t wmi = (wmi_unified_t)wmi_hdl;
if (wmi->ops->extract_dcs_interference_type) {
return wmi->ops->extract_dcs_interference_type(wmi,
evt_buf,
param);
}
return QDF_STATUS_E_FAILURE;
}
QDF_STATUS wmi_extract_dcs_im_tgt_stats(
void *wmi_hdl,
void *evt_buf,
struct wlan_host_dcs_im_tgt_stats *wlan_stat)
{
wmi_unified_t wmi_handle = (wmi_unified_t)wmi_hdl;
if (wmi_handle->ops->extract_dcs_im_tgt_stats) {
return wmi_handle->ops->extract_dcs_im_tgt_stats(wmi_handle,
evt_buf,
wlan_stat);
}
return QDF_STATUS_E_FAILURE;
}
#ifdef ENABLE_HOST_TO_TARGET_CONVERSION
QDF_STATUS wmi_send_dcs_pdev_param(wmi_unified_t wmi_handle,
uint32_t pdev_idx,
bool is_target_pdev_id,
uint32_t dcs_enable)
{
struct pdev_params pparam;
qdf_mem_zero(&pparam, sizeof(pparam));
pparam.is_target_pdev_id = is_target_pdev_id;
pparam.param_id = wmi_pdev_param_dcs;
pparam.param_value = dcs_enable;
return wmi_unified_pdev_param_send(wmi_handle, &pparam, pdev_idx);
}
#else
QDF_STATUS wmi_send_dcs_pdev_param(wmi_unified_t wmi_handle,
uint32_t pdev_idx,
bool is_target_pdev_id,
uint32_t dcs_enable)
{
struct pdev_params pparam;
qdf_mem_zero(&pparam, sizeof(pparam));
pparam.is_target_pdev_id = is_target_pdev_id;
pparam.param_id = WMI_PDEV_PARAM_DCS;
pparam.param_value = dcs_enable;
return wmi_unified_pdev_param_send(wmi_handle, &pparam, pdev_idx);
}
#endif

110
wmi/src/wmi_unified_dcs_tlv.c Fichier normal
Voir le fichier

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2020, 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 above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "osdep.h"
#include "wmi.h"
#include "wmi_unified_priv.h"
/**
* extract_dcs_interference_type_tlv() - extract dcs interference type
* from event
* @wmi_handle: wmi handle
* @param evt_buf: pointer to event buffer
* @param param: Pointer to hold dcs interference param
*
* Return: 0 for success or error code
*/
static QDF_STATUS extract_dcs_interference_type_tlv(
wmi_unified_t wmi_handle,
void *evt_buf, struct wlan_host_dcs_interference_param *param)
{
WMI_DCS_INTERFERENCE_EVENTID_param_tlvs *param_buf;
param_buf = (WMI_DCS_INTERFERENCE_EVENTID_param_tlvs *)evt_buf;
if (!param_buf) {
WMI_LOGE("Invalid dcs interference event buffer");
return QDF_STATUS_E_INVAL;
}
if (!param_buf->fixed_param) {
WMI_LOGE("Invalid fixed param");
return QDF_STATUS_E_INVAL;
}
param->interference_type = param_buf->fixed_param->interference_type;
/* Just support tlv currently */
param->pdev_id = wmi_handle->ops->convert_target_pdev_id_to_host(
wmi_handle,
param_buf->fixed_param->pdev_id);
return QDF_STATUS_SUCCESS;
}
/**
* extract_dcs_im_tgt_stats_tlv() - extract dcs im target stats from event
* @wmi_handle: wmi handle
* @param evt_buf: pointer to event buffer
* @param wlan_stat: Pointer to hold wlan stats
*
* Return: 0 for success or error code
*/
static QDF_STATUS extract_dcs_im_tgt_stats_tlv(
wmi_unified_t wmi_handle,
void *evt_buf,
struct wlan_host_dcs_im_tgt_stats *wlan_stat)
{
WMI_DCS_INTERFERENCE_EVENTID_param_tlvs *param_buf;
wlan_dcs_im_tgt_stats_t *ev;
param_buf = (WMI_DCS_INTERFERENCE_EVENTID_param_tlvs *)evt_buf;
if (!param_buf) {
WMI_LOGE("Invalid dcs interference event buffer");
return QDF_STATUS_E_INVAL;
}
ev = param_buf->wlan_stat;
if (!ev) {
WMI_LOGE("Invalid wlan stat");
return QDF_STATUS_E_INVAL;
}
wlan_stat->reg_tsf32 = ev->reg_tsf32;
wlan_stat->last_ack_rssi = ev->last_ack_rssi;
wlan_stat->tx_waste_time = ev->tx_waste_time;
wlan_stat->rx_time = ev->rx_time;
wlan_stat->phyerr_cnt = ev->phyerr_cnt;
wlan_stat->mib_stats.listen_time = ev->listen_time;
wlan_stat->mib_stats.reg_tx_frame_cnt = ev->reg_tx_frame_cnt;
wlan_stat->mib_stats.reg_rx_frame_cnt = ev->reg_rx_frame_cnt;
wlan_stat->mib_stats.reg_rxclr_cnt = ev->reg_rxclr_cnt;
wlan_stat->mib_stats.reg_cycle_cnt = ev->reg_cycle_cnt;
wlan_stat->mib_stats.reg_rxclr_ext_cnt = ev->reg_rxclr_ext_cnt;
wlan_stat->mib_stats.reg_ofdm_phyerr_cnt = ev->reg_ofdm_phyerr_cnt;
wlan_stat->mib_stats.reg_cck_phyerr_cnt = ev->reg_cck_phyerr_cnt;
wlan_stat->chan_nf = ev->chan_nf;
wlan_stat->my_bss_rx_cycle_count = ev->my_bss_rx_cycle_count;
return QDF_STATUS_SUCCESS;
}
void wmi_dcs_attach_tlv(wmi_unified_t wmi_handle)
{
struct wmi_ops *ops = wmi_handle->ops;
ops->extract_dcs_interference_type = extract_dcs_interference_type_tlv;
ops->extract_dcs_im_tgt_stats = extract_dcs_im_tgt_stats_tlv;
}

Voir le fichier

@@ -1626,7 +1626,12 @@ send_pdev_param_cmd_tlv(wmi_unified_t wmi_handle,
WMITLV_TAG_STRUC_wmi_pdev_set_param_cmd_fixed_param,
WMITLV_GET_STRUCT_TLVLEN
(wmi_pdev_set_param_cmd_fixed_param));
cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
if (param->is_target_pdev_id)
cmd->pdev_id = wmi_handle->ops->convert_host_pdev_id_to_target(
wmi_handle,
mac_id);
else
cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
wmi_handle,
mac_id);
cmd->param_id = pdev_param;
@@ -14165,6 +14170,7 @@ void wmi_tlv_attach(wmi_unified_t wmi_handle)
wmi_nan_attach_tlv(wmi_handle);
wmi_p2p_attach_tlv(wmi_handle);
wmi_interop_issues_ap_attach_tlv(wmi_handle);
wmi_dcs_attach_tlv(wmi_handle);
wmi_roam_attach_tlv(wmi_handle);
wmi_concurrency_attach_tlv(wmi_handle);
wmi_pmo_attach_tlv(wmi_handle);