blob: 66161db41b8e15a298b1e110577a919fadf02190 [file] [log] [blame]
/*
* Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* 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.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
#include "ath_dfs_structs.h"
#include "_ieee80211_common.h"
#include <vos_lock.h>
#define IEEE80211_CHAN_MAX 255
/* channel attributes */
/* Turbo channel */
#define IEEE80211_CHAN_TURBO 0x00000010
/* CCK channel */
#define IEEE80211_CHAN_CCK 0x00000020
/* OFDM channel */
#define IEEE80211_CHAN_OFDM 0x00000040
/* 2 GHz spectrum channel. */
#define IEEE80211_CHAN_2GHZ 0x00000080
/* 5 GHz spectrum channel */
#define IEEE80211_CHAN_5GHZ 0x00000100
/* Only passive scan allowed */
#define IEEE80211_CHAN_PASSIVE 0x00000200
/* Dynamic CCK-OFDM channel */
#define IEEE80211_CHAN_DYN 0x00000400
/* GFSK channel (FHSS PHY) */
#define IEEE80211_CHAN_GFSK 0x00000800
/* Radar found on channel */
#define IEEE80211_CHAN_RADAR 0x00001000
/* 11a static turbo channel only */
#define IEEE80211_CHAN_STURBO 0x00002000
/* Half rate channel */
#define IEEE80211_CHAN_HALF 0x00004000
/* Quarter rate channel */
#define IEEE80211_CHAN_QUARTER 0x00008000
/* HT 20 channel */
#define IEEE80211_CHAN_HT20 0x00010000
/* HT 40 with extension channel above */
#define IEEE80211_CHAN_HT40PLUS 0x00020000
/* HT 40 with extension channel below */
#define IEEE80211_CHAN_HT40MINUS 0x00040000
/* HT 40 Intolerant */
#define IEEE80211_CHAN_HT40INTOL 0x00080000
/* VHT 20 channel */
#define IEEE80211_CHAN_VHT20 0x00100000
/* VHT 40 with extension channel above */
#define IEEE80211_CHAN_VHT40PLUS 0x00200000
/* VHT 40 with extension channel below */
#define IEEE80211_CHAN_VHT40MINUS 0x00400000
/* VHT 80 channel */
#define IEEE80211_CHAN_VHT80 0x00800000
/* token for ``any channel'' */
#define IEEE80211_CHAN_ANY (-1)
#define IEEE80211_CHAN_ANYC \
((struct ieee80211_channel *) IEEE80211_CHAN_ANY)
#define IEEE80211_IS_CHAN_11N_HT40MINUS(_c) \
(((_c)->ic_flags & IEEE80211_CHAN_HT40MINUS) != 0)
#define IEEE80211_IS_CHAN_11N_HT40PLUS(_c) \
(((_c)->ic_flags & IEEE80211_CHAN_HT40PLUS) != 0)
#define IEEE80211_CHAN_11AC_VHT80 \
(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_VHT80)
#define IEEE80211_IS_CHAN_11AC_VHT80(_c) \
(((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT80) == \
IEEE80211_CHAN_11AC_VHT80)
#define CHANNEL_108G \
(IEEE80211_CHAN_2GHZ|IEEE80211_CHAN_OFDM|IEEE80211_CHAN_TURBO)
/*
* Software use: channel interference
* used for as AR as well as RADAR
* interference detection
*/
#define CHANNEL_INTERFERENCE 0x01
/* In case of VHT160, we can have 8 20Mhz channels */
#define IEE80211_MAX_20M_SUB_CH 8
struct ieee80211_channel
{
u_int32_t ic_freq; /* setting in Mhz */
u_int32_t ic_flags; /* see below */
u_int8_t ic_flagext; /* see below */
u_int8_t ic_ieee; /* IEEE channel number */
/* maximum regulatory tx power in dBm */
int8_t ic_maxregpower;
int8_t ic_maxpower; /* maximum tx power in dBm */
int8_t ic_minpower; /* minimum tx power in dBm */
u_int8_t ic_regClassId; /* regClassId of this channel */
u_int8_t ic_antennamax; /* antenna gain max from regulatory */
u_int32_t ic_vhtop_ch_freq_seg1; /* Channel Center frequency */
/* Channel Center frequency applicable*/
u_int32_t ic_vhtop_ch_freq_seg2;
/*
* spectral separation between pri channel
* and the center frequency in MHz
*/
int ic_pri_freq_center_freq_mhz_separation;
};
struct ieee80211_channel_list
{
int cl_nchans;
struct ieee80211_channel *cl_channels[IEE80211_MAX_20M_SUB_CH];
};
struct ieee80211_dfs_state
{
int nol_event[IEEE80211_CHAN_MAX];
os_timer_t nol_timer; /* NOL list processing */
os_timer_t cac_timer; /* CAC timer */
int cureps; /* current events/second */
const struct ieee80211_channel *lastchan; /* chan w/ last radar event */
struct ieee80211_channel *newchan; /* chan selected next */
/* overridden cac timeout */
int cac_timeout_override;
u_int8_t enable:1,
cac_timer_running:1,
ignore_dfs:1,
ignore_cac:1;
};
typedef struct ieee80211com
{
void (*ic_start_csa)(struct ieee80211com *ic,u_int8_t ieeeChan);
void (*ic_get_ext_chan_info)(struct ieee80211com *ic,
struct ieee80211_channel_list *chan);
enum ieee80211_opmode ic_opmode; /* operation mode */
struct ieee80211_channel *(*ic_find_channel)(struct ieee80211com *ic,
int freq, u_int32_t flags);
u_int64_t (*ic_get_TSF64)(struct ieee80211com *ic);
unsigned int (*ic_ieee2mhz)(u_int chan, u_int flags);
struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];
/* Number of Channels according to the Regulatory domain channels */
int ic_nchans;
struct ieee80211_channel *ic_curchan; /* current channel */
u_int8_t ic_isdfsregdomain; /* operating in DFS domain ? */
int (*ic_get_dfsdomain)(struct ieee80211com *);
u_int16_t (*ic_dfs_usenol)(struct ieee80211com *ic);
u_int16_t (*ic_dfs_isdfsregdomain)(struct ieee80211com *ic);
int (*ic_dfs_attached)(struct ieee80211com *ic);
void *ic_dfs;
struct ieee80211_dfs_state ic_dfs_state;
int (*ic_dfs_attach)(struct ieee80211com *ic,
void *pCap, void *radar_info);
int (*ic_dfs_detach)(struct ieee80211com *ic);
int (*ic_dfs_enable)(struct ieee80211com *ic, int *is_fastclk, void *);
int (*ic_dfs_disable)(struct ieee80211com *ic);
int (*ic_get_ext_busy)(struct ieee80211com *ic);
int (*ic_get_mib_cycle_counts_pct)(struct ieee80211com *ic,
u_int32_t *rxc_pcnt, u_int32_t *rxf_pcnt, u_int32_t *txf_pcnt);
int (*ic_dfs_get_thresholds)(struct ieee80211com *ic,void *pe);
int (*ic_dfs_debug)(struct ieee80211com *ic, int type, void *data);
/*
* Update the channel list with the current set of DFS
* NOL entries.
*
* + 'cmd' indicates what to do; for now it should just
* be DFS_NOL_CLIST_CMD_UPDATE which will update all
* channels, given the _entire_ NOL. (Rather than
* the earlier behaviour with clist_update, which
* was to either add or remove a set of channel
* entries.)
*/
void (*ic_dfs_clist_update)(struct ieee80211com *ic, int cmd,
struct dfs_nol_chan_entry *, int nentries);
void (*ic_dfs_notify_radar)(struct ieee80211com *ic,
struct ieee80211_channel *chan);
void (*ic_dfs_unmark_radar)(struct ieee80211com *ic,
struct ieee80211_channel *chan);
int (*ic_dfs_control)(struct ieee80211com *ic,
u_int id, void *indata, u_int32_t insize,
void *outdata, u_int32_t *outsize);
void (*ic_update_dfs_cac_block_tx)(bool cac_block_tx);
HAL_DFS_DOMAIN current_dfs_regdomain;
u_int8_t vdev_id;
u_int8_t last_radar_found_chan;
int32_t dfs_pri_multiplier;
adf_os_spinlock_t chan_lock;
bool disable_phy_err_processing;
} IEEE80211COM, *PIEEE80211COM;
/*
* Convert channel to frequency value.
*/
static INLINE u_int
ieee80211_chan2freq(struct ieee80211com *ic,
const struct ieee80211_channel *c)
{
if (c == NULL)
{
return 0;
}
return (c == IEEE80211_CHAN_ANYC ? IEEE80211_CHAN_ANY : c->ic_freq);
}