cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dfs_pattern_detector.c (11171B)


      1/*
      2 * Copyright (c) 2012 Neratec Solutions AG
      3 *
      4 * Permission to use, copy, modify, and/or distribute this software for any
      5 * purpose with or without fee is hereby granted, provided that the above
      6 * copyright notice and this permission notice appear in all copies.
      7 *
      8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15 */
     16
     17#include <linux/slab.h>
     18#include <linux/export.h>
     19
     20#include "dfs_pattern_detector.h"
     21#include "dfs_pri_detector.h"
     22#include "ath.h"
     23
     24/**
     25 * struct radar_types - contains array of patterns defined for one DFS domain
     26 * @region: regulatory DFS region
     27 * @num_radar_types: number of radar types to follow
     28 * @radar_types: radar types array
     29 */
     30struct radar_types {
     31	enum nl80211_dfs_regions region;
     32	u32 num_radar_types;
     33	const struct radar_detector_specs *radar_types;
     34};
     35
     36/* percentage on ppb threshold to trigger detection */
     37#define MIN_PPB_THRESH	50
     38#define PPB_THRESH_RATE(PPB, RATE) ((PPB * RATE + 100 - RATE) / 100)
     39#define PPB_THRESH(PPB) PPB_THRESH_RATE(PPB, MIN_PPB_THRESH)
     40#define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF)
     41/* percentage of pulse width tolerance */
     42#define WIDTH_TOLERANCE 5
     43#define WIDTH_LOWER(X) ((X*(100-WIDTH_TOLERANCE)+50)/100)
     44#define WIDTH_UPPER(X) ((X*(100+WIDTH_TOLERANCE)+50)/100)
     45
     46#define ETSI_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB, CHIRP)	\
     47{								\
     48	ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX),		\
     49	(PRF2PRI(PMAX) - PRI_TOLERANCE),			\
     50	(PRF2PRI(PMIN) * PRF + PRI_TOLERANCE), PRF, PPB * PRF,	\
     51	PPB_THRESH(PPB), PRI_TOLERANCE,	CHIRP			\
     52}
     53
     54/* radar types as defined by ETSI EN-301-893 v1.5.1 */
     55static const struct radar_detector_specs etsi_radar_ref_types_v15[] = {
     56	ETSI_PATTERN(0,  0,  1,  700,  700, 1, 18, false),
     57	ETSI_PATTERN(1,  0,  5,  200, 1000, 1, 10, false),
     58	ETSI_PATTERN(2,  0, 15,  200, 1600, 1, 15, false),
     59	ETSI_PATTERN(3,  0, 15, 2300, 4000, 1, 25, false),
     60	ETSI_PATTERN(4, 20, 30, 2000, 4000, 1, 20, false),
     61	ETSI_PATTERN(5,  0,  2,  300,  400, 3, 10, false),
     62	ETSI_PATTERN(6,  0,  2,  400, 1200, 3, 15, false),
     63};
     64
     65static const struct radar_types etsi_radar_types_v15 = {
     66	.region			= NL80211_DFS_ETSI,
     67	.num_radar_types	= ARRAY_SIZE(etsi_radar_ref_types_v15),
     68	.radar_types		= etsi_radar_ref_types_v15,
     69};
     70
     71#define FCC_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB, CHIRP)	\
     72{								\
     73	ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX),		\
     74	PMIN - PRI_TOLERANCE,					\
     75	PMAX * PRF + PRI_TOLERANCE, PRF, PPB * PRF,		\
     76	PPB_THRESH(PPB), PRI_TOLERANCE,	CHIRP			\
     77}
     78
     79/* radar types released on August 14, 2014
     80 * type 1 PRI values randomly selected within the range of 518 and 3066.
     81 * divide it to 3 groups is good enough for both of radar detection and
     82 * avoiding false detection based on practical test results
     83 * collected for more than a year.
     84 */
     85static const struct radar_detector_specs fcc_radar_ref_types[] = {
     86	FCC_PATTERN(0, 0, 1, 1428, 1428, 1, 18, false),
     87	FCC_PATTERN(101, 0, 1, 518, 938, 1, 57, false),
     88	FCC_PATTERN(102, 0, 1, 938, 2000, 1, 27, false),
     89	FCC_PATTERN(103, 0, 1, 2000, 3066, 1, 18, false),
     90	FCC_PATTERN(2, 0, 5, 150, 230, 1, 23, false),
     91	FCC_PATTERN(3, 6, 10, 200, 500, 1, 16, false),
     92	FCC_PATTERN(4, 11, 20, 200, 500, 1, 12, false),
     93	FCC_PATTERN(5, 50, 100, 1000, 2000, 1, 1, true),
     94	FCC_PATTERN(6, 0, 1, 333, 333, 1, 9, false),
     95};
     96
     97static const struct radar_types fcc_radar_types = {
     98	.region			= NL80211_DFS_FCC,
     99	.num_radar_types	= ARRAY_SIZE(fcc_radar_ref_types),
    100	.radar_types		= fcc_radar_ref_types,
    101};
    102
    103#define JP_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB, RATE, CHIRP)	\
    104{								\
    105	ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX),		\
    106	PMIN - PRI_TOLERANCE,					\
    107	PMAX * PRF + PRI_TOLERANCE, PRF, PPB * PRF,		\
    108	PPB_THRESH_RATE(PPB, RATE), PRI_TOLERANCE, CHIRP	\
    109}
    110static const struct radar_detector_specs jp_radar_ref_types[] = {
    111	JP_PATTERN(0, 0, 1, 1428, 1428, 1, 18, 29, false),
    112	JP_PATTERN(1, 2, 3, 3846, 3846, 1, 18, 29, false),
    113	JP_PATTERN(2, 0, 1, 1388, 1388, 1, 18, 50, false),
    114	JP_PATTERN(3, 0, 4, 4000, 4000, 1, 18, 50, false),
    115	JP_PATTERN(4, 0, 5, 150, 230, 1, 23, 50, false),
    116	JP_PATTERN(5, 6, 10, 200, 500, 1, 16, 50, false),
    117	JP_PATTERN(6, 11, 20, 200, 500, 1, 12, 50, false),
    118	JP_PATTERN(7, 50, 100, 1000, 2000, 1, 3, 50, true),
    119	JP_PATTERN(5, 0, 1, 333, 333, 1, 9, 50, false),
    120};
    121
    122static const struct radar_types jp_radar_types = {
    123	.region			= NL80211_DFS_JP,
    124	.num_radar_types	= ARRAY_SIZE(jp_radar_ref_types),
    125	.radar_types		= jp_radar_ref_types,
    126};
    127
    128static const struct radar_types *dfs_domains[] = {
    129	&etsi_radar_types_v15,
    130	&fcc_radar_types,
    131	&jp_radar_types,
    132};
    133
    134/**
    135 * get_dfs_domain_radar_types() - get radar types for a given DFS domain
    136 * @region: regulatory DFS region
    137 *
    138 * Return value: radar_types ptr on success, NULL if DFS domain is not supported
    139 */
    140static const struct radar_types *
    141get_dfs_domain_radar_types(enum nl80211_dfs_regions region)
    142{
    143	u32 i;
    144	for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) {
    145		if (dfs_domains[i]->region == region)
    146			return dfs_domains[i];
    147	}
    148	return NULL;
    149}
    150
    151/**
    152 * struct channel_detector - detector elements for a DFS channel
    153 * @head: list_head
    154 * @freq: frequency for this channel detector in MHz
    155 * @detectors: array of dynamically created detector elements for this freq
    156 *
    157 * Channel detectors are required to provide multi-channel DFS detection, e.g.
    158 * to support off-channel scanning. A pattern detector has a list of channels
    159 * radar pulses have been reported for in the past.
    160 */
    161struct channel_detector {
    162	struct list_head head;
    163	u16 freq;
    164	struct pri_detector **detectors;
    165};
    166
    167/* channel_detector_reset() - reset detector lines for a given channel */
    168static void channel_detector_reset(struct dfs_pattern_detector *dpd,
    169				   struct channel_detector *cd)
    170{
    171	u32 i;
    172	if (cd == NULL)
    173		return;
    174	for (i = 0; i < dpd->num_radar_types; i++)
    175		cd->detectors[i]->reset(cd->detectors[i], dpd->last_pulse_ts);
    176}
    177
    178/* channel_detector_exit() - destructor */
    179static void channel_detector_exit(struct dfs_pattern_detector *dpd,
    180				  struct channel_detector *cd)
    181{
    182	u32 i;
    183	if (cd == NULL)
    184		return;
    185	list_del(&cd->head);
    186	if (cd->detectors) {
    187		for (i = 0; i < dpd->num_radar_types; i++) {
    188			struct pri_detector *de = cd->detectors[i];
    189			if (de != NULL)
    190				de->exit(de);
    191		}
    192	}
    193	kfree(cd->detectors);
    194	kfree(cd);
    195}
    196
    197static struct channel_detector *
    198channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
    199{
    200	u32 i;
    201	struct channel_detector *cd;
    202
    203	cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
    204	if (cd == NULL)
    205		goto fail;
    206
    207	INIT_LIST_HEAD(&cd->head);
    208	cd->freq = freq;
    209	cd->detectors = kmalloc_array(dpd->num_radar_types,
    210				      sizeof(*cd->detectors), GFP_ATOMIC);
    211	if (cd->detectors == NULL)
    212		goto fail;
    213
    214	for (i = 0; i < dpd->num_radar_types; i++) {
    215		const struct radar_detector_specs *rs = &dpd->radar_spec[i];
    216		struct pri_detector *de = pri_detector_init(rs);
    217		if (de == NULL)
    218			goto fail;
    219		cd->detectors[i] = de;
    220	}
    221	list_add(&cd->head, &dpd->channel_detectors);
    222	return cd;
    223
    224fail:
    225	ath_dbg(dpd->common, DFS,
    226		"failed to allocate channel_detector for freq=%d\n", freq);
    227	channel_detector_exit(dpd, cd);
    228	return NULL;
    229}
    230
    231/**
    232 * channel_detector_get() - get channel detector for given frequency
    233 * @dpd: DPD instance pointer
    234 * @freq: freq frequency in MHz
    235 *
    236 * Return value: pointer to channel detector on success, NULL otherwise
    237 *
    238 * Return existing channel detector for the given frequency or return a
    239 * newly create one.
    240 */
    241static struct channel_detector *
    242channel_detector_get(struct dfs_pattern_detector *dpd, u16 freq)
    243{
    244	struct channel_detector *cd;
    245	list_for_each_entry(cd, &dpd->channel_detectors, head) {
    246		if (cd->freq == freq)
    247			return cd;
    248	}
    249	return channel_detector_create(dpd, freq);
    250}
    251
    252/*
    253 * DFS Pattern Detector
    254 */
    255
    256/* dpd_reset(): reset all channel detectors */
    257static void dpd_reset(struct dfs_pattern_detector *dpd)
    258{
    259	struct channel_detector *cd;
    260	list_for_each_entry(cd, &dpd->channel_detectors, head)
    261		channel_detector_reset(dpd, cd);
    262
    263}
    264static void dpd_exit(struct dfs_pattern_detector *dpd)
    265{
    266	struct channel_detector *cd, *cd0;
    267	list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head)
    268		channel_detector_exit(dpd, cd);
    269	kfree(dpd);
    270}
    271
    272static bool
    273dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event,
    274	      struct radar_detector_specs *rs)
    275{
    276	u32 i;
    277	struct channel_detector *cd;
    278
    279	/*
    280	 * pulses received for a non-supported or un-initialized
    281	 * domain are treated as detected radars for fail-safety
    282	 */
    283	if (dpd->region == NL80211_DFS_UNSET)
    284		return true;
    285
    286	cd = channel_detector_get(dpd, event->freq);
    287	if (cd == NULL)
    288		return false;
    289
    290	/* reset detector on time stamp wraparound, caused by TSF reset */
    291	if (event->ts < dpd->last_pulse_ts)
    292		dpd_reset(dpd);
    293	dpd->last_pulse_ts = event->ts;
    294
    295	/* do type individual pattern matching */
    296	for (i = 0; i < dpd->num_radar_types; i++) {
    297		struct pri_detector *pd = cd->detectors[i];
    298		struct pri_sequence *ps = pd->add_pulse(pd, event);
    299		if (ps != NULL) {
    300			if (rs != NULL)
    301				memcpy(rs, pd->rs, sizeof(*rs));
    302			ath_dbg(dpd->common, DFS,
    303				"DFS: radar found on freq=%d: id=%d, pri=%d, "
    304				"count=%d, count_false=%d\n",
    305				event->freq, pd->rs->type_id,
    306				ps->pri, ps->count, ps->count_falses);
    307			pd->reset(pd, dpd->last_pulse_ts);
    308			return true;
    309		}
    310	}
    311	return false;
    312}
    313
    314static struct ath_dfs_pool_stats
    315dpd_get_stats(struct dfs_pattern_detector *dpd)
    316{
    317	return global_dfs_pool_stats;
    318}
    319
    320static bool dpd_set_domain(struct dfs_pattern_detector *dpd,
    321			   enum nl80211_dfs_regions region)
    322{
    323	const struct radar_types *rt;
    324	struct channel_detector *cd, *cd0;
    325
    326	if (dpd->region == region)
    327		return true;
    328
    329	dpd->region = NL80211_DFS_UNSET;
    330
    331	rt = get_dfs_domain_radar_types(region);
    332	if (rt == NULL)
    333		return false;
    334
    335	/* delete all channel detectors for previous DFS domain */
    336	list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head)
    337		channel_detector_exit(dpd, cd);
    338	dpd->radar_spec = rt->radar_types;
    339	dpd->num_radar_types = rt->num_radar_types;
    340
    341	dpd->region = region;
    342	return true;
    343}
    344
    345static const struct dfs_pattern_detector default_dpd = {
    346	.exit		= dpd_exit,
    347	.set_dfs_domain	= dpd_set_domain,
    348	.add_pulse	= dpd_add_pulse,
    349	.get_stats	= dpd_get_stats,
    350	.region		= NL80211_DFS_UNSET,
    351};
    352
    353struct dfs_pattern_detector *
    354dfs_pattern_detector_init(struct ath_common *common,
    355			  enum nl80211_dfs_regions region)
    356{
    357	struct dfs_pattern_detector *dpd;
    358
    359	if (!IS_ENABLED(CONFIG_CFG80211_CERTIFICATION_ONUS))
    360		return NULL;
    361
    362	dpd = kmalloc(sizeof(*dpd), GFP_KERNEL);
    363	if (dpd == NULL)
    364		return NULL;
    365
    366	*dpd = default_dpd;
    367	INIT_LIST_HEAD(&dpd->channel_detectors);
    368
    369	dpd->common = common;
    370	if (dpd->set_dfs_domain(dpd, region))
    371		return dpd;
    372
    373	ath_dbg(common, DFS,"Could not set DFS domain to %d", region);
    374	kfree(dpd);
    375	return NULL;
    376}
    377EXPORT_SYMBOL(dfs_pattern_detector_init);