qcacmn: Add support for Agile DFS feature

Agile Dynamic Frequency Selection refers to the mechanism in which DFS
scanning takes place on a separate dedicated synthesizer
(agile DFS sythesizer), while the access point receives data on a
separate channel. Once DFS scanning completes in the aDFS
synthesizer, AP can switch its primary channel to this preCAC done
channel, without Channel Availability Check of 60 seconds.

Hawkeye has native support for A-DFS unlike Cascade, which uses a
dedicated radar detector for background scanning. Each Iron radio has
two synthesizers, one of which can perform A-DFS.
Host driver configures an A-DFS channel along with maintaining
pre-CAC Done list of channels. PreCAC list caching of channels
is currently limited to ETSI domain.

Once off channel CAC completes in the agile channel, HOST receives O-CAC
complete indication. O-CAC status included as a part of event params
has information if the preCAC is successful or not. HOST also receives
indication through radar indication event handler, upon RADAR detect.
The detection is read as agile channel RADAR using the detector id value.

For SBS mode, there can be 2 pdev's which can comprise of DFS channels.
Although the preCAC list is separate for each pdev, preCAC timer is
limited to a single pdev.

The following commands are to set/get preCAC enable. Prerequisite to
enable preCAC includes regdomain to be in ETSI along with agile capability
enabled in the target.

	iwpriv wifiX get_preCACEn
	iwpriv wifiX preCACEn 0/1

Change-Id: Id9f022f885ccd9200167cdbc779a811d622d09da
CRs-Fixed: 2385536
这个提交包含在:
Shaakir Mohamed
2018-12-17 11:22:36 -08:00
提交者 nshrivas
父节点 9ff68da6e5
当前提交 7a71538673
修改 8 个文件,包含 325 行新增19 行删除

查看文件

@@ -92,6 +92,22 @@ struct dfs_emulate_bang_radar_test_cmd {
uint32_t args[DFS_MAX_NUM_UNIT_TEST_ARGS];
};
/**
* struct vdev_adfs_complete_status - OCAC complete status event param
* @vdev_id: Physical device identifier
* @chan_freq: Channel number
* @chan_width: Channel Width
* @center_freq: Center Frequency channel number
* @ocac_status: off channel cac status
*/
struct vdev_adfs_complete_status {
uint32_t vdev_id;
uint32_t chan_freq;
uint32_t chan_width;
uint32_t center_freq;
uint32_t ocac_status;
};
extern struct dfs_to_mlme global_dfs_to_mlme;
/**
@@ -287,6 +303,39 @@ static inline QDF_STATUS tgt_dfs_set_tx_leakage_threshold
QDF_STATUS tgt_dfs_is_precac_timer_running(struct wlan_objmgr_pdev *pdev,
bool *is_precac_timer_running);
/**
* tgt_dfs_set_agile_precac_state() - set state for Agile Precac.
*
* @pdev: Pointer to DFS pdev object.
* @agile_precac_state: Agile Precac state
*
* wrapper function for dfs_set_agile_precac_state.
* This function called from outside of dfs component.
*/
QDF_STATUS tgt_dfs_set_agile_precac_state(struct wlan_objmgr_pdev *pdev,
int agile_precac_state);
/**
* tgt_dfs_agile_precac_start() - Start agile precac
*
* @pdev: Pointer to DFS pdev object.
*
* wrapper function for dfs_set_agile_precac_state.
* This function called from outside of dfs component.
*/
QDF_STATUS tgt_dfs_agile_precac_start(struct wlan_objmgr_pdev *pdev);
/**
* tgt_dfs_ocac_complete() - Process off channel cac complete indication.
* @pdev: Pointer to DFS pdev object.
* @vdev_adfs_complete_status: Off channel CAC complete status.
*
* wrapper function for dfs_set_agile_precac_state.
* This function called from outside of dfs component.
*/
QDF_STATUS tgt_dfs_ocac_complete(struct wlan_objmgr_pdev *pdev,
struct vdev_adfs_complete_status *ocac_status);
/**
* utils_dfs_find_vht80_chan_for_precac() - Find VHT80 channel for precac.
* @pdev: Pointer to DFS pdev object.

查看文件

@@ -37,6 +37,7 @@
#include <qdf_trace.h>
#include "wlan_scan_ucfg_api.h"
#include "wlan_dfs_mlme_api.h"
#include "../../core/src/dfs_zero_cac.h"
struct dfs_to_mlme global_dfs_to_mlme;
@@ -157,6 +158,8 @@ static QDF_STATUS dfs_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc
qdf_mem_free(dfs_soc_obj);
return status;
}
/* Initialize precac timer here*/
dfs_zero_cac_timer_init(dfs_soc_obj);
dfs_debug(NULL, WLAN_DEBUG_DFS1,
"DFS obj attach to psoc successfully");
@@ -185,6 +188,8 @@ static QDF_STATUS dfs_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *pso
return QDF_STATUS_E_FAILURE;
}
dfs_zero_cac_timer_detach(dfs_soc_obj);
status = wlan_objmgr_psoc_component_obj_detach(psoc,
WLAN_UMAC_COMP_DFS,
dfs_soc_obj);
@@ -380,8 +385,8 @@ QDF_STATUS wlan_dfs_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
dfs->dfs_is_offload_enabled = dfs_tx_ops->dfs_is_tgt_offload(psoc);
dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_offload %d",
dfs->dfs_is_offload_enabled);
dfs_agile_soc_obj_init(dfs, psoc);
dfs = wlan_pdev_get_dfs_obj(pdev);
if (dfs_attach(dfs) == 1) {
dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_attch failed");
dfs_destroy_object(dfs);

查看文件

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
*
*
* Permission to use, copy, modify, and/or distribute this software for
@@ -23,6 +23,7 @@
*/
#include <wlan_objmgr_pdev_obj.h>
#include "wlan_dfs_tgt_api.h"
#include "wlan_dfs_utils_api.h"
#include "wlan_dfs_init_deinit_api.h"
#include "wlan_lmac_if_def.h"
#include "wlan_lmac_if_api.h"
@@ -340,6 +341,91 @@ QDF_STATUS tgt_dfs_control(struct wlan_objmgr_pdev *pdev,
}
qdf_export_symbol(tgt_dfs_control);
#ifdef QCA_SUPPORT_AGILE_DFS
QDF_STATUS tgt_dfs_agile_precac_start(struct wlan_objmgr_pdev *pdev)
{
struct wlan_dfs *dfs;
dfs = wlan_pdev_get_dfs_obj(pdev);
if (!dfs) {
dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
return QDF_STATUS_E_FAILURE;
}
dfs_agile_precac_start(dfs);
return QDF_STATUS_SUCCESS;
}
#else
QDF_STATUS tgt_dfs_agile_precac_start(struct wlan_objmgr_pdev *pdev)
{
return QDF_STATUS_SUCCESS;
}
#endif
qdf_export_symbol(tgt_dfs_agile_precac_start);
#ifdef QCA_SUPPORT_AGILE_DFS
QDF_STATUS tgt_dfs_set_agile_precac_state(struct wlan_objmgr_pdev *pdev,
int agile_precac_state)
{
struct wlan_dfs *dfs;
int i;
dfs = wlan_pdev_get_dfs_obj(pdev);
if (!dfs) {
dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
return QDF_STATUS_E_FAILURE;
}
dfs->dfs_soc_obj->precac_state_started = agile_precac_state;
if (!dfs->dfs_soc_obj->precac_state_started) {
for (i = 0; i < dfs->dfs_soc_obj->num_dfs_privs; i++)
dfs->dfs_soc_obj->dfs_priv[i].agile_precac_active = 0;
}
return QDF_STATUS_SUCCESS;
}
#else
QDF_STATUS tgt_dfs_set_agile_precac_state(struct wlan_objmgr_pdev *pdev,
int agile_precac_state)
{
return QDF_STATUS_SUCCESS;
}
#endif
qdf_export_symbol(tgt_dfs_set_agile_precac_state);
#ifdef QCA_SUPPORT_AGILE_DFS
QDF_STATUS tgt_dfs_ocac_complete(struct wlan_objmgr_pdev *pdev,
struct vdev_adfs_complete_status *adfs_status)
{
struct wlan_dfs *dfs;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
if (!pdev) {
dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null pdev");
return status;
}
dfs = wlan_pdev_get_dfs_obj(pdev);
if (!dfs) {
dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "dfs is null");
return status;
}
dfs_process_ocac_complete(pdev, adfs_status->ocac_status,
adfs_status->center_freq);
return QDF_STATUS_SUCCESS;
}
#else
QDF_STATUS tgt_dfs_ocac_complete(struct wlan_objmgr_pdev *pdev,
struct vdev_adfs_complete_status *adfs_status)
{
return QDF_STATUS_SUCCESS;
}
#endif
qdf_export_symbol(tgt_dfs_ocac_complete);
QDF_STATUS tgt_dfs_find_vht80_chan_for_precac(struct wlan_objmgr_pdev *pdev,
uint32_t chan_mode,
uint8_t ch_freq_seg1,

查看文件

@@ -140,9 +140,11 @@ QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev)
dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "NULL dfs");
return QDF_STATUS_E_FAILURE;
}
if (!dfs->dfs_precac_secondary_freq)
return QDF_STATUS_E_FAILURE;
dfs_start_precac_timer(dfs, dfs->dfs_precac_secondary_freq);
dfs_start_precac_timer(dfs,
dfs->dfs_precac_secondary_freq);
return QDF_STATUS_SUCCESS;
}