ath9k: add DFS pattern detector
[cascardo/linux.git] / drivers / net / wireless / ath / ath9k / dfs_pattern_detector.c
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
23 /*
24  * tolerated deviation of radar time stamp in usecs on both sides
25  * TODO: this might need to be HW-dependent
26  */
27 #define PRI_TOLERANCE   16
28
29 /**
30  * struct radar_types - contains array of patterns defined for one DFS domain
31  * @domain: DFS regulatory domain
32  * @num_radar_types: number of radar types to follow
33  * @radar_types: radar types array
34  */
35 struct radar_types {
36         enum nl80211_dfs_regions region;
37         u32 num_radar_types;
38         const struct radar_detector_specs *radar_types;
39 };
40
41 /* percentage on ppb threshold to trigger detection */
42 #define MIN_PPB_THRESH  50
43 #define PPB_THRESH(PPB) ((PPB * MIN_PPB_THRESH + 50) / 100)
44 #define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF)
45
46 #define ETSI_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB)      \
47 {                                                               \
48         ID, WMIN, WMAX, (PRF2PRI(PMAX) - PRI_TOLERANCE),        \
49         (PRF2PRI(PMIN) * PRF + PRI_TOLERANCE), PRF, PPB * PRF,  \
50         PPB_THRESH(PPB), PRI_TOLERANCE,                         \
51 }
52
53 /* radar types as defined by ETSI EN-301-893 v1.5.1 */
54 static const struct radar_detector_specs etsi_radar_ref_types_v15[] = {
55         ETSI_PATTERN(0,  0,  1,  700,  700, 1, 18),
56         ETSI_PATTERN(1,  0,  5,  200, 1000, 1, 10),
57         ETSI_PATTERN(2,  0, 15,  200, 1600, 1, 15),
58         ETSI_PATTERN(3,  0, 15, 2300, 4000, 1, 25),
59         ETSI_PATTERN(4, 20, 30, 2000, 4000, 1, 20),
60         ETSI_PATTERN(5,  0,  2,  300,  400, 3, 10),
61         ETSI_PATTERN(6,  0,  2,  400, 1200, 3, 15),
62 };
63
64 static const struct radar_types etsi_radar_types_v15 = {
65         .region                 = NL80211_DFS_ETSI,
66         .num_radar_types        = ARRAY_SIZE(etsi_radar_ref_types_v15),
67         .radar_types            = etsi_radar_ref_types_v15,
68 };
69
70 /* for now, we support ETSI radar types, FCC and JP are TODO */
71 static const struct radar_types *dfs_domains[] = {
72         &etsi_radar_types_v15,
73 };
74
75 /**
76  * get_dfs_domain_radar_types() - get radar types for a given DFS domain
77  * @param domain DFS domain
78  * @return radar_types ptr on success, NULL if DFS domain is not supported
79  */
80 static const struct radar_types *
81 get_dfs_domain_radar_types(enum nl80211_dfs_regions region)
82 {
83         u32 i;
84         for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) {
85                 if (dfs_domains[i]->region == region)
86                         return dfs_domains[i];
87         }
88         return NULL;
89 }
90
91 /**
92  * struct channel_detector - detector elements for a DFS channel
93  * @head: list_head
94  * @freq: frequency for this channel detector in MHz
95  * @detectors: array of dynamically created detector elements for this freq
96  *
97  * Channel detectors are required to provide multi-channel DFS detection, e.g.
98  * to support off-channel scanning. A pattern detector has a list of channels
99  * radar pulses have been reported for in the past.
100  */
101 struct channel_detector {
102         struct list_head head;
103         u16 freq;
104         struct pri_detector **detectors;
105 };
106
107 /* channel_detector_reset() - reset detector lines for a given channel */
108 static void channel_detector_reset(struct dfs_pattern_detector *dpd,
109                                    struct channel_detector *cd)
110 {
111         u32 i;
112         if (cd == NULL)
113                 return;
114         for (i = 0; i < dpd->num_radar_types; i++)
115                 cd->detectors[i]->reset(cd->detectors[i], dpd->last_pulse_ts);
116 }
117
118 /* channel_detector_exit() - destructor */
119 static void channel_detector_exit(struct dfs_pattern_detector *dpd,
120                                   struct channel_detector *cd)
121 {
122         u32 i;
123         if (cd == NULL)
124                 return;
125         list_del(&cd->head);
126         for (i = 0; i < dpd->num_radar_types; i++) {
127                 struct pri_detector *de = cd->detectors[i];
128                 if (de != NULL)
129                         de->exit(de);
130         }
131         kfree(cd->detectors);
132         kfree(cd);
133 }
134
135 static struct channel_detector *
136 channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
137 {
138         u32 sz, i;
139         struct channel_detector *cd;
140
141         cd = kmalloc(sizeof(*cd), GFP_KERNEL);
142         if (cd == NULL)
143                 goto fail;
144
145         INIT_LIST_HEAD(&cd->head);
146         cd->freq = freq;
147         sz = sizeof(cd->detectors) * dpd->num_radar_types;
148         cd->detectors = kzalloc(sz, GFP_KERNEL);
149         if (cd->detectors == NULL)
150                 goto fail;
151
152         for (i = 0; i < dpd->num_radar_types; i++) {
153                 const struct radar_detector_specs *rs = &dpd->radar_spec[i];
154                 struct pri_detector *de = pri_detector_init(rs);
155                 if (de == NULL)
156                         goto fail;
157                 cd->detectors[i] = de;
158         }
159         list_add(&cd->head, &dpd->channel_detectors);
160         return cd;
161
162 fail:
163         pr_err("failed to allocate channel_detector for freq=%d\n", freq);
164         channel_detector_exit(dpd, cd);
165         return NULL;
166 }
167
168 /**
169  * channel_detector_get() - get channel detector for given frequency
170  * @param dpd instance pointer
171  * @param freq frequency in MHz
172  * @return pointer to channel detector on success, NULL otherwise
173  *
174  * Return existing channel detector for the given frequency or return a
175  * newly create one.
176  */
177 static struct channel_detector *
178 channel_detector_get(struct dfs_pattern_detector *dpd, u16 freq)
179 {
180         struct channel_detector *cd;
181         list_for_each_entry(cd, &dpd->channel_detectors, head) {
182                 if (cd->freq == freq)
183                         return cd;
184         }
185         return channel_detector_create(dpd, freq);
186 }
187
188 /*
189  * DFS Pattern Detector
190  */
191
192 /* dpd_reset(): reset all channel detectors */
193 static void dpd_reset(struct dfs_pattern_detector *dpd)
194 {
195         struct channel_detector *cd;
196         if (!list_empty(&dpd->channel_detectors))
197                 list_for_each_entry(cd, &dpd->channel_detectors, head)
198                         channel_detector_reset(dpd, cd);
199
200 }
201 static void dpd_exit(struct dfs_pattern_detector *dpd)
202 {
203         struct channel_detector *cd, *cd0;
204         if (!list_empty(&dpd->channel_detectors))
205                 list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head)
206                         channel_detector_exit(dpd, cd);
207         kfree(dpd);
208 }
209
210 static bool
211 dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
212 {
213         u32 i;
214         bool ts_wraparound;
215         struct channel_detector *cd;
216
217         if (dpd->region == NL80211_DFS_UNSET) {
218                 /*
219                  * pulses received for a non-supported or un-initialized
220                  * domain are treated as detected radars
221                  */
222                 return true;
223         }
224
225         cd = channel_detector_get(dpd, event->freq);
226         if (cd == NULL)
227                 return false;
228
229         ts_wraparound = (event->ts < dpd->last_pulse_ts);
230         dpd->last_pulse_ts = event->ts;
231         if (ts_wraparound) {
232                 /*
233                  * reset detector on time stamp wraparound
234                  * with monotonic time stamps, this should never happen
235                  */
236                 pr_warn("DFS: time stamp wraparound detected, resetting\n");
237                 dpd_reset(dpd);
238         }
239         /* do type individual pattern matching */
240         for (i = 0; i < dpd->num_radar_types; i++) {
241                 if (cd->detectors[i]->add_pulse(cd->detectors[i], event) != 0) {
242                         channel_detector_reset(dpd, cd);
243                         return true;
244                 }
245         }
246         return false;
247 }
248
249 static bool dpd_set_domain(struct dfs_pattern_detector *dpd,
250                            enum nl80211_dfs_regions region)
251 {
252         const struct radar_types *rt;
253         struct channel_detector *cd, *cd0;
254
255         if (dpd->region == region)
256                 return true;
257
258         dpd->region = NL80211_DFS_UNSET;
259
260         rt = get_dfs_domain_radar_types(region);
261         if (rt == NULL)
262                 return false;
263
264         /* delete all channel detectors for previous DFS domain */
265         if (!list_empty(&dpd->channel_detectors))
266                 list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head)
267                         channel_detector_exit(dpd, cd);
268         dpd->radar_spec = rt->radar_types;
269         dpd->num_radar_types = rt->num_radar_types;
270
271         dpd->region = region;
272         return true;
273 }
274
275 static struct dfs_pattern_detector default_dpd = {
276         .exit           = dpd_exit,
277         .set_domain     = dpd_set_domain,
278         .add_pulse      = dpd_add_pulse,
279         .region         = NL80211_DFS_UNSET,
280 };
281
282 struct dfs_pattern_detector *
283 dfs_pattern_detector_init(enum nl80211_dfs_regions region)
284 {
285         struct dfs_pattern_detector *dpd;
286         dpd = kmalloc(sizeof(*dpd), GFP_KERNEL);
287         if (dpd == NULL) {
288                 pr_err("allocation of dfs_pattern_detector failed\n");
289                 return NULL;
290         }
291         *dpd = default_dpd;
292         INIT_LIST_HEAD(&dpd->channel_detectors);
293
294         if (dpd->set_domain(dpd, region))
295                 return dpd;
296
297         pr_err("Could not set DFS domain to %d. ", region);
298         return NULL;
299 }
300 EXPORT_SYMBOL(dfs_pattern_detector_init);