blob: e708abdf519f7618b9cc3e9bfea0479cc206ec48 [file] [log] [blame]
/*
* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* DOC: This file has Zero CAC DFS APIs.
*/
#ifndef _DFS_ZERO_CAC_H_
#define _DFS_ZERO_CAC_H_
#include "dfs.h"
#define VHT160_IEEE_FREQ_DIFF 16
/**
* struct dfs_precac_entry - PreCAC entry.
* @pe_list: PreCAC entry.
* @vht80_freq: VHT80 freq.
* @precac_nol_timer: Per element precac NOL timer.
* @dfs: Pointer to wlan_dfs structure.
*/
struct dfs_precac_entry {
TAILQ_ENTRY(dfs_precac_entry) pe_list;
uint8_t vht80_freq;
os_timer_t precac_nol_timer;
struct wlan_dfs *dfs;
};
/**
* enum precac_chan_state - Enum for PreCAC state of a channel.
* @PRECAC_ERR: Invalid preCAC state.
* @PRECAC_REQUIRED: preCAC need to be done on the channel.
* @PRECAC_NOW: preCAC is running on the channel.
* @PRECAC_DONE: preCAC is done and channel is clear.
* @PRECAC_NOL: preCAC is done and radar is detected.
*/
enum precac_chan_state {
PRECAC_ERR = -1,
PRECAC_REQUIRED,
PRECAC_NOW,
PRECAC_DONE,
PRECAC_NOL,
};
/**
* dfs_zero_cac_timer_init() - Initialize zero-cac timers
* @dfs: Pointer to DFS structure.
*/
void dfs_zero_cac_timer_init(struct wlan_dfs *dfs);
/**
* dfs_print_precaclists() - Print precac list.
* @dfs: Pointer to wlan_dfs structure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_print_precaclists(struct wlan_dfs *dfs);
#else
static inline void dfs_print_precaclists(struct wlan_dfs *dfs)
{
}
#endif
/**
* dfs_reset_precac_lists() - Resets the precac lists.
* @dfs: Pointer to wlan_dfs structure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_reset_precac_lists(struct wlan_dfs *dfs);
#else
static inline void dfs_reset_precac_lists(struct wlan_dfs *dfs)
{
}
#endif
/**
* dfs_reset_precaclists() - Clears and initiakizes precac_required_list,
* precac_done_list and precac_nol_list.
*
* @dfs: Pointer to wlan_dfs structure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_reset_precaclists(struct wlan_dfs *dfs);
#else
static inline void dfs_reset_precaclists(struct wlan_dfs *dfs)
{
}
#endif
/**
* dfs_deinit_precac_list() - Clears the precac list.
* @dfs: Pointer to wlan_dfs dtructure.
*/
void dfs_deinit_precac_list(struct wlan_dfs *dfs);
/**
* dfs_zero_cac_detach() - Free zero_cac memory.
* @dfs: Pointer to wlan_dfs dtructure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_zero_cac_detach(struct wlan_dfs *dfs);
#else
static inline void dfs_zero_cac_detach(struct wlan_dfs *dfs)
{
}
#endif
/**
* dfs_init_precac_list() - Init precac list.
* @dfs: Pointer to wlan_dfs dtructure.
*/
void dfs_init_precac_list(struct wlan_dfs *dfs);
/**
* dfs_start_precac_timer() - Start precac timer.
* @dfs: Pointer to wlan_dfs structure.
* @precac_chan: Start thr precac timer in this channel.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_start_precac_timer(struct wlan_dfs *dfs,
uint8_t precac_chan);
#else
static inline void dfs_start_precac_timer(struct wlan_dfs *dfs,
uint8_t precac_chan)
{
}
#endif
/**
* dfs_cancel_precac_timer() - Cancel the precac timer.
* @dfs: Pointer to wlan_dfs structure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_cancel_precac_timer(struct wlan_dfs *dfs);
#else
static inline void dfs_cancel_precac_timer(struct wlan_dfs *dfs)
{
}
#endif
/**
* dfs_zero_cac_attach() - Initialize dfs zerocac variables.
* @dfs: Pointer to DFS structure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_zero_cac_attach(struct wlan_dfs *dfs);
#else
static inline void dfs_zero_cac_attach(struct wlan_dfs *dfs)
{
}
#endif
/**
* dfs_zero_cac_reset() - Reset Zero cac DFS variables.
* @dfs: Pointer to wlan_dfs structure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_zero_cac_reset(struct wlan_dfs *dfs);
#else
static inline void dfs_zero_cac_reset(struct wlan_dfs *dfs)
{
}
#endif
/**
* dfs_is_precac_done() - Is precac done.
* @dfs: Pointer to wlan_dfs structure.
* @chan: Pointer to dfs_channel for which preCAC done is checked.
*
* Return:
* * True: If precac is done on channel.
* * False: If precac is not done on channel.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
bool dfs_is_precac_done(struct wlan_dfs *dfs, struct dfs_channel *chan);
#else
static inline bool dfs_is_precac_done(struct wlan_dfs *dfs,
struct dfs_channel *chan)
{
return false;
}
#endif
#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
/**
* dfs_decide_precac_preferred_chan() - Choose operating channel among
* configured DFS channel and
* intermediate channel based on
* precac status of configured
* DFS channel.
* @dfs: Pointer to wlan_dfs structure.
* @pref_chan: Congigired DFS channel.
*
* Return: void.
*/
void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs, uint8_t *pref_chan);
#else
static inline void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs,
uint8_t *pref_chan)
{
}
#endif
/**
* dfs_get_freq_from_precac_required_list() - Get VHT80 freq from
* precac_required_list.
* @dfs: Pointer to wlan_dfs structure.
* @exclude_ieee_freq: Find a VHT80 freqency that is not equal to
* exclude_ieee_freq.
*/
uint8_t dfs_get_freq_from_precac_required_list(struct wlan_dfs *dfs,
uint8_t exclude_ieee_freq);
/**
* dfs_override_precac_timeout() - Override the default precac timeout.
* @dfs: Pointer to wlan_dfs structure.
* @precac_timeout: Precac timeout value.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
int dfs_override_precac_timeout(struct wlan_dfs *dfs,
int precac_timeout);
#else
static inline int dfs_override_precac_timeout(struct wlan_dfs *dfs,
int precac_timeout)
{
return 0;
}
#endif
/**
* dfs_get_override_precac_timeout() - Get precac timeout.
* @dfs: Pointer wlan_dfs structure.
* @precac_timeout: Get precac timeout value in this variable.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
int dfs_get_override_precac_timeout(struct wlan_dfs *dfs,
int *precac_timeout);
#else
static inline int dfs_get_override_precac_timeout(struct wlan_dfs *dfs,
int *precac_timeout)
{
return 0;
}
#endif
/**
* dfs_find_vht80_chan_for_precac() - Find VHT80 channel for precac.
* @dfs: Pointer to wlan_dfs structure.
* @chan_mode: Channel mode.
* @ch_freq_seg1: Segment1 channel freq.
* @cfreq1: cfreq1.
* @cfreq2: cfreq2.
* @phy_mode: Precac phymode.
* @dfs_set_cfreq2: Precac cfreq2
* @set_agile: Agile mode flag.
*
* Zero-CAC-DFS algorithm:-
* Zero-CAC-DFS algorithm works in stealth mode.
* 1) When any channel change happens in VHT80 mode the algorithm
* changes the HW channel mode to VHT80_80/VHT160 mode and adds a
* new channel in the secondary VHT80 to perform precac and a
* precac timer is started. However the upper layer/UMAC is unaware
* of this change.
* 2) When the precac timer expires without being interrupted by
* any channel change the secondary VHT80 channel is moved from
* precac-required-list to precac-done-list.
* 3) If there is a radar detect at any time in any segment
* (segment-1 is preimary VHT80 and segment-2 is VHT80)then the
* channel is searched in both precac-reuired-list and precac-done-list
* and moved to precac-nol-list.
* 4) Whenever channel change happens if the new channel is a DFS
* channel then precac-done-list is searched and if the channel is
* found in the precac-done-list then the CAC is skipped.
* 5) The precac expiry timer makes a vedv_restart(channel change
* with current-upper-layer-channel-mode which is VHT80). In channel
* change the algorithm tries to pick a new channel from the
* precac-required list. If none found then channel mode remains same.
* Which means when all the channels in precac-required-list are
* exhausted the VHT80_80/VHT160 comes back to VHT80 mode.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs,
uint32_t chan_mode,
uint8_t ch_freq_seg1,
uint32_t *cfreq1,
uint32_t *cfreq2,
uint32_t *phy_mode,
bool *dfs_set_cfreq2,
bool *set_agile);
#else
static inline void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs,
uint32_t chan_mode,
uint8_t ch_freq_seg1,
uint32_t *cfreq1,
uint32_t *cfreq2,
uint32_t *phy_mode,
bool *dfs_set_cfreq2,
bool *set_agile)
{
}
#endif
/**
* dfs_set_precac_enable() - Set precac enable flag.
* @dfs: Pointer to wlan_dfs structure.
* @value: input value for dfs_precac_enable flag.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_set_precac_enable(struct wlan_dfs *dfs,
uint32_t value);
#else
static inline void dfs_set_precac_enable(struct wlan_dfs *dfs,
uint32_t value)
{
}
#endif
/**
* dfs_get_precac_enable() - Get precac enable flag.
* @dfs: Pointer to wlan_dfs structure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs);
#else
static inline uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs)
{
return 0;
}
#endif
#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
/**
* dfs_set_precac_intermediate_chan() - Set intermediate chan to be used while
* doing precac.
* @dfs: Pointer to wlan_dfs structure.
* @value: input value for dfs_precac_enable flag.
*
* Return:
* * 0 - Successfully set intermediate channel.
* * -EINVAL - Invalid channel.
*/
int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs,
uint32_t value);
#else
static inline int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs,
uint32_t value)
{
return 0;
}
#endif
#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
/**
* dfs_get_precac_intermediate_chan() - Get configured precac
* intermediate channel.
* @dfs: Pointer to wlan_dfs structure.
*
* Return: Configured intermediate channel number.
*/
uint32_t dfs_get_precac_intermediate_chan(struct wlan_dfs *dfs);
#else
static inline uint32_t dfs_get_intermediate_chan(struct wlan_dfs *dfs)
{
return 0;
}
#endif
#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
/**
* dfs_get_precac_chan_state() - Get precac status of a given channel.
* @dfs: Pointer to wlan_dfs structure.
* @precac_chan: Channel number for which precac state need to be checked.
*
* Return:
* * PRECAC_REQUIRED: Precac has not done on precac_chan.
* * PRECAC_NOW : Precac is running on precac_chan.
* * PRECAC_DONE : precac_chan is in precac done list.
* * PRECAC_NOL : precac_chan is in precac NOL list.
* * PRECAC_ERR : Invalid precac state.
*/
enum precac_chan_state
dfs_get_precac_chan_state(struct wlan_dfs *dfs, uint8_t precac_chan);
#else
static inline enum precac_chan_state
dfs_get_precac_chan_state(struct wlan_dfs *dfs,
uint8_t precac_chan)
{
return PRECAC_REQUIRED;
}
#endif
/**
* dfs_zero_cac_reset() - Reset Zero cac DFS variables.
* @dfs: Pointer to wlan_dfs structure.
*/
void dfs_zero_cac_reset(struct wlan_dfs *dfs);
/**
* dfs_is_ht20_40_80_chan_in_precac_done_list() - Is precac done on a
* VHT20/40/80 channel.
*@dfs: Pointer to wlan_dfs structure.
*@chan: Pointer to dfs_channel for which preCAC done is checked.
*
* Return:
* * True: If channel is present in precac-done list.
* * False: If channel is not present in precac-done list.
*/
bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs,
struct dfs_channel *chan);
/**
* dfs_is_ht80_80_chan_in_precac_done_list() - Is precac done on a VHT80+80
* channel.
*@dfs: Pointer to wlan_dfs structure.
*@chan: Pointer to dfs_channel for which preCAC done is checked.
*
* Return:
* * True: If channel is present in precac-done list.
* * False: If channel is not present in precac-done list.
*/
bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs,
struct dfs_channel *chan);
/**
* dfs_mark_precac_dfs() - Mark the precac channel as radar.
* @dfs: Pointer to wlan_dfs structure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
void dfs_mark_precac_dfs(struct wlan_dfs *dfs,
uint8_t is_radar_found_on_secondary_seg);
#else
static inline void dfs_mark_precac_dfs(struct wlan_dfs *dfs,
uint8_t is_radar_found_on_secondary_seg)
{
}
#endif
/**
* dfs_is_precac_timer_running() - Check whether precac timer is running.
* @dfs: Pointer to wlan_dfs structure.
*/
#if defined(WLAN_DFS_PARTIAL_OFFLOAD)
bool dfs_is_precac_timer_running(struct wlan_dfs *dfs);
#else
static inline bool dfs_is_precac_timer_running(struct wlan_dfs *dfs)
{
return false;
}
#endif
#endif /* _DFS_ZERO_CAC_H_ */