diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index da971921972e..b5c4a895448b 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -400,6 +400,7 @@ * in host. NOL timer can be configured by user. NOL in FW (for FO) is disabled. */ #define USENOL_ENABLE_NOL_HOST_DISABLE_NOL_FW 2 +#define AGILE_DETECTOR_ID 2 /** * struct dfs_pulseparams - DFS pulse param structure. @@ -933,7 +934,6 @@ struct dfs_event_log { * @dfs_precac_enable: Enable the precac. * @dfs_precac_secondary_freq: Second segment freq for precac. * @dfs_precac_primary_freq: Primary freq. - * @dfs_precac_timer_running: Precac timer running. * @dfs_defer_precac_channel_change: Defer precac channel change. * @dfs_precac_inter_chan: Intermediate non-DFS channel used while * doing precac. @@ -977,7 +977,6 @@ struct dfs_event_log { * @dfs_cac_valid: DFS CAC valid. * @dfs_cac_valid_time: Time for which CAC will be valid and will * not be re-done. - * @dfs_precac_timer: PRECAC timer. * @dfs_precac_timeout_override: Overridden precac timeout. * @dfs_num_precac_freqs: Number of PreCAC VHT80 frequencies. * @dfs_precac_required_list: PreCAC required list. @@ -1082,7 +1081,6 @@ struct wlan_dfs { bool dfs_precac_enable; uint8_t dfs_precac_secondary_freq; uint8_t dfs_precac_primary_freq; - uint8_t dfs_precac_timer_running; uint8_t dfs_defer_precac_channel_change; #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT uint8_t dfs_precac_inter_chan; @@ -1123,7 +1121,6 @@ struct wlan_dfs { dfs_ignore_cac:1, dfs_cac_valid:1; uint32_t dfs_cac_valid_time; - qdf_timer_t dfs_precac_timer; int dfs_precac_timeout_override; uint8_t dfs_num_precac_freqs; #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD) @@ -1141,6 +1138,11 @@ struct wlan_dfs { struct dfs_channel *dfs_curchan; struct dfs_channel dfs_cac_started_chan; struct wlan_objmgr_pdev *dfs_pdev_obj; + struct dfs_soc_priv_obj *dfs_soc_obj; +#if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) + uint8_t dfs_psoc_idx; + uint8_t dfs_agile_precac_freq; +#endif bool dfs_is_offload_enabled; int dfs_use_nol; qdf_spinlock_t dfs_nol_lock; @@ -1173,8 +1175,21 @@ struct wlan_dfs { uint8_t dfs_nol_ie_bitmap; bool dfs_is_rcsa_ie_sent; bool dfs_is_nol_ie_sent; + bool dfs_agile_precac_enable; }; +#if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) +/** + * struct wlan_dfs_priv - dfs private struct with agile capability info + * @wlan_dfs: pointer to wlan_dfs object. + * @agile_precac_active: agile precac active information for wlan_dfs_priv obj + */ +struct wlan_dfs_priv { + struct wlan_dfs *dfs; + bool agile_precac_active; +}; +#endif + /** * struct dfs_soc_priv_obj - dfs private data * @psoc: pointer to PSOC object information @@ -1185,11 +1200,26 @@ struct wlan_dfs { * FW will do the pre-check, filter out some * kinds of invalid phyerrors and indicate * radar detection related information to host. + * @dfs_priv: array of dfs private structs with agile capability info + * @num_dfs_privs: array size of dfs private structs for given psoc. + * @cur_precac_dfs_index: current precac dfs index + * @dfs_precac_timer: agile precac timer + * @dfs_precac_timer_running: precac timer running flag + * @ocac_status: Off channel CAC complete status */ struct dfs_soc_priv_obj { struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_pdev *pdev; bool dfs_is_phyerr_filter_offload; +#if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) + struct wlan_dfs_priv dfs_priv[WLAN_UMAC_MAX_PDEVS]; + uint8_t num_dfs_privs; + uint8_t cur_precac_dfs_index; + qdf_timer_t dfs_precac_timer; + uint8_t dfs_precac_timer_running; + bool precac_state_started; + bool ocac_status; +#endif }; /** diff --git a/umac/dfs/core/src/dfs_zero_cac.h b/umac/dfs/core/src/dfs_zero_cac.h index 70d98482937d..cfeddc3a323b 100644 --- a/umac/dfs/core/src/dfs_zero_cac.h +++ b/umac/dfs/core/src/dfs_zero_cac.h @@ -32,8 +32,12 @@ #define _DFS_ZERO_CAC_H_ #include "dfs.h" +#include #define VHT160_IEEE_FREQ_DIFF 16 +#define OCAC_SUCCESS 0 +#define OCAC_RESET 1 +#define OCAC_CANCEL 2 /** * struct dfs_precac_entry - PreCAC entry. @@ -67,10 +71,16 @@ enum precac_chan_state { /** * dfs_zero_cac_timer_init() - Initialize zero-cac timers - * @dfs: Pointer to DFS structure. + * @dfs_soc_obj: Pointer to DFS SOC object structure. */ -void dfs_zero_cac_timer_init(struct wlan_dfs *dfs); - +#if !defined(QCA_MCL_DFS_SUPPORT) +void dfs_zero_cac_timer_init(struct dfs_soc_priv_obj *dfs_soc_obj); +#else +static inline void +dfs_zero_cac_timer_init(struct dfs_soc_priv_obj *dfs_soc_obj) +{ +} +#endif /** * dfs_print_precaclists() - Print precac list. * @dfs: Pointer to wlan_dfs structure. @@ -186,12 +196,13 @@ static inline void dfs_zero_cac_reset(struct wlan_dfs *dfs) /** * dfs_zero_cac_timer_detach() - Free Zero cac DFS variables. - * @dfs: Pointer to wlan_dfs structure. + * @dfs_soc_obj: Pointer to dfs_soc_priv_obj structure. */ -#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) -void dfs_zero_cac_timer_detach(struct wlan_dfs *dfs); +#if !defined(QCA_MCL_DFS_SUPPORT) +void dfs_zero_cac_timer_detach(struct dfs_soc_priv_obj *dfs_soc_obj); #else -static inline void dfs_zero_cac_timer_detach(struct wlan_dfs *dfs) +static inline void +dfs_zero_cac_timer_detach(struct dfs_soc_priv_obj *dfs_soc_obj) { } #endif @@ -339,6 +350,108 @@ static inline void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, } #endif +#if defined(QCA_SUPPORT_AGILE_DFS) +/** + * dfs_find_pdev_for_agile_precac() - Find pdev to select channel for precac. + * @pdev: Pointer to wlan_objmgr_pdev structure. + * @cur_precac_dfs_index: current precac index + */ +void dfs_find_pdev_for_agile_precac(struct wlan_objmgr_pdev *pdev, + uint8_t *cur_precac_dfs_index); + +/** + * dfs_prepare_agile_precac_chan() - Send Agile set request for given pdev. + * @dfs: Pointer to wlan_dfs structure. + */ +void dfs_prepare_agile_precac_chan(struct wlan_dfs *dfs); + +/** + * dfs_process_ocac_complete() - Process Off-Channel CAC complete indication. + * @pdev :Pointer to wlan_objmgr_pdev structure. + * @ocac_status: Off channel CAC complete status + * @center_freq : Center Frequency of O-CAC done indication. + */ +void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev, + uint32_t ocac_status, + uint32_t center_freq); + +/** + * dfs_find_vht80_chan_for_agile_precac() - . + * @pdev :Pointer to wlan_objmgr_pdev structure. + * @*ch_freq: Pointer to channel number for agile set request. + * @ch_freq_seg1 : Current primary beaconing channel number. + * @ch_freq_seg2 : Current secondary segment channel number. + */ +void dfs_find_vht80_chan_for_agile_precac(struct wlan_dfs *dfs, + uint8_t *ch_freq, + uint8_t ch_freq_seg1, + uint8_t ch_freq_seg2); +/** + * dfs_agile_precac_start() - Start agile precac. + * @dfs: Pointer to wlan_dfs structure. + */ +void dfs_agile_precac_start(struct wlan_dfs *dfs); + +/** + * dfs_start_agile_precac_timer() - Start precac timer. + * @dfs: Pointer to wlan_dfs structure. + * @precac_chan: Start thr precac timer in this channel. + * @ocac_status: Status of the off channel CAC. + */ +void dfs_start_agile_precac_timer(struct wlan_dfs *dfs, + uint8_t precac_chan, + uint8_t ocac_status); +#else +static inline void dfs_find_pdev_for_agile_precac(struct wlan_objmgr_pdev *pdev, + uint8_t *cur_precac_dfs_index) +{ +} + +static inline void dfs_prepare_agile_precac_chan(struct wlan_dfs *dfs) +{ +} + +static inline void +dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev, + uint32_t ocac_status, + uint32_t center_freq) +{ +} + +static inline void dfs_find_vht80_chan_for_agile_precac(struct wlan_dfs *dfs, + uint8_t *ch_freq, + uint8_t ch_freq_seg1, + uint8_t ch_freq_seg2) +{ +} + +static inline void dfs_agile_precac_start(struct wlan_dfs *dfs) +{ +} + +static inline void dfs_start_agile_precac_timer(struct wlan_dfs *dfs, + uint8_t precac_chan, + uint8_t ocac_status) +{ +} +#endif + +#if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) +/** + * dfs_agile_soc_obj_init() - Initialize soc obj for agile precac. + * @dfs: Pointer to wlan_dfs structure. + * @precac_chan: Start thr precac timer in this channel. + * @ocac_status: Status of the off channel CAC. + */ +void dfs_agile_soc_obj_init(struct wlan_dfs *dfs, + struct wlan_objmgr_psoc *psoc); +#else +static inline void dfs_agile_soc_obj_init(struct wlan_dfs *dfs, + struct wlan_objmgr_psoc *psoc) +{ +} +#endif + /** * dfs_set_precac_enable() - Set precac enable flag. * @dfs: Pointer to wlan_dfs structure. @@ -464,13 +577,17 @@ bool dfs_is_ht8080_ht160_chan_in_precac_done_list(struct wlan_dfs *dfs, /** * dfs_mark_precac_dfs() - Mark the precac channel as radar. * @dfs: Pointer to wlan_dfs structure. + * @is_radar_found_on_secondary_seg: Radar found on secondary seg for Cascade. + * @detector_id: detector id which found RADAR in HW. */ #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) void dfs_mark_precac_dfs(struct wlan_dfs *dfs, - uint8_t is_radar_found_on_secondary_seg); + uint8_t is_radar_found_on_secondary_seg, + uint8_t detector_id); #else static inline void dfs_mark_precac_dfs(struct wlan_dfs *dfs, - uint8_t is_radar_found_on_secondary_seg) + uint8_t is_radar_found_on_secondary_seg, + uint8_t detector_id) { } #endif diff --git a/umac/dfs/core/src/misc/dfs.c b/umac/dfs/core/src/misc/dfs.c index 24094d9679dd..fa0ea7c5e5db 100644 --- a/umac/dfs/core/src/misc/dfs.c +++ b/umac/dfs/core/src/misc/dfs.c @@ -239,7 +239,7 @@ void dfs_reset(struct wlan_dfs *dfs) void dfs_timer_detach(struct wlan_dfs *dfs) { dfs_cac_timer_detach(dfs); - dfs_zero_cac_timer_detach(dfs); + dfs_zero_cac_timer_detach(dfs->dfs_soc_obj); if (!dfs->dfs_is_offload_enabled) { dfs_main_timer_detach(dfs); diff --git a/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c b/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c index d531df8567db..41e53e1c6409 100644 --- a/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c +++ b/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c @@ -770,6 +770,17 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, channels); dfs_reset_bangradar(dfs); + + if (dfs->dfs_agile_precac_enable && radar_found->detector_id == + AGILE_DETECTOR_ID) { + dfs_debug(dfs, WLAN_DEBUG_DFS, + "%s: %d Radar found on agile detector:%d , STAY in Same operating Channel", + __func__, __LINE__, radar_found->detector_id); + dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg, + radar_found->detector_id); + return QDF_STATUS_SUCCESS; + } + status = dfs_radar_add_channel_list_to_nol(dfs, channels, num_channels); if (QDF_IS_STATUS_ERROR(status)) { dfs_err(dfs, WLAN_DEBUG_DFS, @@ -802,8 +813,14 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, * precac-nol-list. */ - if (dfs->dfs_precac_enable) - dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg); + if (dfs->dfs_precac_enable || dfs->dfs_agile_precac_enable) { + dfs_debug(dfs, WLAN_DEBUG_DFS, + "%s: %d Radar found on dfs detector:%d", + __func__, __LINE__, radar_found->detector_id); + dfs_mark_precac_dfs(dfs, + dfs->is_radar_found_on_secondary_seg, + radar_found->detector_id); + } if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) { /* Remove chan from ETSI Pre-CAC Cleared List*/ diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h index c5cf7b579ffb..ea96b9542e24 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h @@ -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. diff --git a/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c b/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c index 07a055b59b77..57fcba8dc82e 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c @@ -37,6 +37,7 @@ #include #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); diff --git a/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c b/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c index 664b179955c3..3f6c7635714d 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c @@ -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 #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, diff --git a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index 5f4aaa5b4065..7a759bcb1443 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -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; }