xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/dfs_zero_cac.h (revision 1b9674e21e24478fba4530f5ae7396b9555e9c6a)
1 /*
2  * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 /**
28  * DOC: This file has Zero CAC DFS APIs.
29  */
30 
31 #ifndef _DFS_ZERO_CAC_H_
32 #define _DFS_ZERO_CAC_H_
33 
34 #include "dfs.h"
35 
36 #define VHT160_IEEE_FREQ_DIFF 16
37 
38 /**
39  * struct dfs_precac_entry - PreCAC entry.
40  * @pe_list:           PreCAC entry.
41  * @vht80_freq:        VHT80 freq.
42  * @precac_nol_timer:  Per element precac NOL timer.
43  * @dfs:               Pointer to wlan_dfs structure.
44  */
45 struct dfs_precac_entry {
46 	TAILQ_ENTRY(dfs_precac_entry) pe_list;
47 	uint8_t             vht80_freq;
48 	os_timer_t          precac_nol_timer;
49 	struct wlan_dfs      *dfs;
50 };
51 
52 /**
53  * enum precac_chan_state - Enum for PreCAC state of a channel.
54  * @PRECAC_ERR:            Invalid preCAC state.
55  * @PRECAC_REQUIRED:       preCAC need to be done on the channel.
56  * @PRECAC_NOW:            preCAC is running on the channel.
57  * @PRECAC_DONE:           preCAC is done and channel is clear.
58  * @PRECAC_NOL:            preCAC is done and radar is detected.
59  */
60 enum precac_chan_state {
61 	PRECAC_ERR      = -1,
62 	PRECAC_REQUIRED,
63 	PRECAC_NOW,
64 	PRECAC_DONE,
65 	PRECAC_NOL,
66 };
67 
68 /**
69  * dfs_zero_cac_timer_init() - Initialize zero-cac timers
70  * @dfs: Pointer to DFS structure.
71  */
72 void dfs_zero_cac_timer_init(struct wlan_dfs *dfs);
73 
74 /**
75  * dfs_print_precaclists() - Print precac list.
76  * @dfs: Pointer to wlan_dfs structure.
77  */
78 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
79 void dfs_print_precaclists(struct wlan_dfs *dfs);
80 #else
81 static inline void dfs_print_precaclists(struct wlan_dfs *dfs)
82 {
83 }
84 #endif
85 
86 /**
87  * dfs_reset_precac_lists() - Resets the precac lists.
88  * @dfs: Pointer to wlan_dfs structure.
89  */
90 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
91 void dfs_reset_precac_lists(struct wlan_dfs *dfs);
92 #else
93 static inline void dfs_reset_precac_lists(struct wlan_dfs *dfs)
94 {
95 }
96 #endif
97 
98 /**
99  * dfs_reset_precaclists() - Clears and initiakizes precac_required_list,
100  *                           precac_done_list and precac_nol_list.
101  *
102  * @dfs: Pointer to wlan_dfs structure.
103  */
104 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
105 void dfs_reset_precaclists(struct wlan_dfs *dfs);
106 #else
107 static inline void dfs_reset_precaclists(struct wlan_dfs *dfs)
108 {
109 }
110 #endif
111 
112 /**
113  * dfs_deinit_precac_list() - Clears the precac list.
114  * @dfs: Pointer to wlan_dfs dtructure.
115  */
116 void dfs_deinit_precac_list(struct wlan_dfs *dfs);
117 
118 /**
119  * dfs_zero_cac_detach() - Free zero_cac memory.
120  * @dfs: Pointer to wlan_dfs dtructure.
121  */
122 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
123 void dfs_zero_cac_detach(struct wlan_dfs *dfs);
124 #else
125 static inline void dfs_zero_cac_detach(struct wlan_dfs *dfs)
126 {
127 }
128 #endif
129 
130 /**
131  * dfs_init_precac_list() - Init precac list.
132  * @dfs: Pointer to wlan_dfs dtructure.
133  */
134 void dfs_init_precac_list(struct wlan_dfs *dfs);
135 
136 /**
137  * dfs_start_precac_timer() - Start precac timer.
138  * @dfs: Pointer to wlan_dfs structure.
139  * @precac_chan: Start thr precac timer in this channel.
140  */
141 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
142 void dfs_start_precac_timer(struct wlan_dfs *dfs,
143 			    uint8_t precac_chan);
144 #else
145 static inline void dfs_start_precac_timer(struct wlan_dfs *dfs,
146 					  uint8_t precac_chan)
147 {
148 }
149 #endif
150 
151 /**
152  * dfs_cancel_precac_timer() - Cancel the precac timer.
153  * @dfs: Pointer to wlan_dfs structure.
154  */
155 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
156 void dfs_cancel_precac_timer(struct wlan_dfs *dfs);
157 #else
158 static inline void dfs_cancel_precac_timer(struct wlan_dfs *dfs)
159 {
160 }
161 #endif
162 
163 /**
164  * dfs_zero_cac_attach() - Initialize dfs zerocac variables.
165  * @dfs: Pointer to DFS structure.
166  */
167 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
168 void dfs_zero_cac_attach(struct wlan_dfs *dfs);
169 #else
170 static inline void dfs_zero_cac_attach(struct wlan_dfs *dfs)
171 {
172 }
173 #endif
174 
175 /**
176  * dfs_zero_cac_reset() - Reset Zero cac DFS variables.
177  * @dfs: Pointer to wlan_dfs structure.
178  */
179 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
180 void dfs_zero_cac_reset(struct wlan_dfs *dfs);
181 #else
182 static inline void dfs_zero_cac_reset(struct wlan_dfs *dfs)
183 {
184 }
185 #endif
186 
187 /**
188  * dfs_zero_cac_timer_free() - Free Zero cac DFS variables.
189  * @dfs: Pointer to wlan_dfs structure.
190  */
191 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
192 void dfs_zero_cac_timer_free(struct wlan_dfs *dfs);
193 #else
194 static inline void dfs_zero_cac_timer_free(struct wlan_dfs *dfs)
195 {
196 }
197 #endif
198 
199 /**
200  * dfs_is_precac_done() - Is precac done.
201  * @dfs: Pointer to wlan_dfs structure.
202  * @chan: Pointer to dfs_channel for which preCAC done is checked.
203  *
204  * Return:
205  * * True:  If precac is done on channel.
206  * * False: If precac is not done on channel.
207  */
208 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
209 bool dfs_is_precac_done(struct wlan_dfs *dfs, struct dfs_channel *chan);
210 #else
211 static inline bool dfs_is_precac_done(struct wlan_dfs *dfs,
212 				      struct dfs_channel *chan)
213 {
214 	return false;
215 }
216 #endif
217 
218 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
219 /**
220  * dfs_decide_precac_preferred_chan() - Choose operating channel among
221  *                                      configured DFS channel and
222  *                                      intermediate channel based on
223  *                                      precac status of configured
224  *                                      DFS channel.
225  * @dfs: Pointer to wlan_dfs structure.
226  * @pref_chan: Congigired DFS channel.
227  *
228  * Return: void.
229  */
230 void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs, uint8_t *pref_chan);
231 #else
232 static inline void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs,
233 						    uint8_t *pref_chan)
234 {
235 }
236 #endif
237 
238 /**
239  * dfs_get_freq_from_precac_required_list() - Get VHT80 freq from
240  *                                            precac_required_list.
241  * @dfs: Pointer to wlan_dfs structure.
242  * @exclude_ieee_freq: Find a VHT80 freqency that is not equal to
243  *                     exclude_ieee_freq.
244  */
245 uint8_t dfs_get_freq_from_precac_required_list(struct wlan_dfs *dfs,
246 		uint8_t exclude_ieee_freq);
247 
248 /**
249  * dfs_override_precac_timeout() - Override the default precac timeout.
250  * @dfs: Pointer to wlan_dfs structure.
251  * @precac_timeout: Precac timeout value.
252  */
253 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
254 int dfs_override_precac_timeout(struct wlan_dfs *dfs,
255 		int precac_timeout);
256 #else
257 static inline int dfs_override_precac_timeout(struct wlan_dfs *dfs,
258 		int precac_timeout)
259 {
260 	return 0;
261 }
262 #endif
263 
264 /**
265  * dfs_get_override_precac_timeout() - Get precac timeout.
266  * @dfs: Pointer wlan_dfs structure.
267  * @precac_timeout: Get precac timeout value in this variable.
268  */
269 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
270 int dfs_get_override_precac_timeout(struct wlan_dfs *dfs,
271 		int *precac_timeout);
272 #else
273 static inline int dfs_get_override_precac_timeout(struct wlan_dfs *dfs,
274 		int *precac_timeout)
275 {
276 	return 0;
277 }
278 #endif
279 
280 /**
281  * dfs_find_vht80_chan_for_precac() - Find VHT80 channel for precac.
282  * @dfs: Pointer to wlan_dfs structure.
283  * @chan_mode: Channel mode.
284  * @ch_freq_seg1: Segment1 channel freq.
285  * @cfreq1: cfreq1.
286  * @cfreq2: cfreq2.
287  * @phy_mode: Precac phymode.
288  * @dfs_set_cfreq2: Precac cfreq2
289  * @set_agile: Agile mode flag.
290  *
291  * Zero-CAC-DFS algorithm:-
292  * Zero-CAC-DFS algorithm works in stealth mode.
293  * 1) When any channel change happens in VHT80 mode the algorithm
294  * changes the HW channel mode to VHT80_80/VHT160 mode and adds a
295  * new channel in the secondary VHT80 to perform precac and a
296  * precac timer is started. However the upper layer/UMAC is unaware
297  * of this change.
298  * 2) When the precac timer expires without being interrupted by
299  * any channel change the secondary VHT80 channel is moved from
300  * precac-required-list to precac-done-list.
301  * 3) If there is a radar detect at any time in any segment
302  * (segment-1 is preimary VHT80 and segment-2 is VHT80)then the
303  * channel is searched in both precac-reuired-list and precac-done-list
304  * and moved to precac-nol-list.
305  * 4) Whenever channel change happens if the new channel is a DFS
306  * channel then precac-done-list is searched and if the channel is
307  * found in the precac-done-list then the CAC is skipped.
308  * 5) The precac expiry timer makes a vedv_restart(channel change
309  * with current-upper-layer-channel-mode which is VHT80). In channel
310  * change the algorithm tries to pick a new channel from the
311  * precac-required list. If none found then channel mode remains same.
312  * Which means when all the channels in precac-required-list are
313  * exhausted the VHT80_80/VHT160 comes back to VHT80 mode.
314  */
315 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
316 void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs,
317 		uint32_t chan_mode,
318 		uint8_t ch_freq_seg1,
319 		uint32_t *cfreq1,
320 		uint32_t *cfreq2,
321 		uint32_t *phy_mode,
322 		bool *dfs_set_cfreq2,
323 		bool *set_agile);
324 #else
325 static inline void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs,
326 		uint32_t chan_mode,
327 		uint8_t ch_freq_seg1,
328 		uint32_t *cfreq1,
329 		uint32_t *cfreq2,
330 		uint32_t *phy_mode,
331 		bool *dfs_set_cfreq2,
332 		bool *set_agile)
333 {
334 }
335 #endif
336 
337 /**
338  * dfs_set_precac_enable() - Set precac enable flag.
339  * @dfs: Pointer to wlan_dfs structure.
340  * @value: input value for dfs_precac_enable flag.
341  */
342 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
343 void dfs_set_precac_enable(struct wlan_dfs *dfs,
344 		uint32_t value);
345 #else
346 static inline void dfs_set_precac_enable(struct wlan_dfs *dfs,
347 		uint32_t value)
348 {
349 }
350 #endif
351 
352 /**
353  * dfs_get_precac_enable() - Get precac enable flag.
354  * @dfs: Pointer to wlan_dfs structure.
355  */
356 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
357 uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs);
358 #else
359 static inline uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs)
360 {
361 	return 0;
362 }
363 #endif
364 
365 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
366 /**
367  * dfs_set_precac_intermediate_chan() - Set intermediate chan to be used while
368  *                                      doing precac.
369  * @dfs: Pointer to wlan_dfs structure.
370  * @value: input value for dfs_precac_enable flag.
371  *
372  * Return:
373  * * 0       - Successfully set intermediate channel.
374  * * -EINVAL - Invalid channel.
375  */
376 int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs,
377 					 uint32_t value);
378 #else
379 static inline int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs,
380 						       uint32_t value)
381 {
382 	return 0;
383 }
384 #endif
385 
386 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
387 /**
388  * dfs_get_precac_intermediate_chan() - Get configured precac
389  *					intermediate channel.
390  * @dfs: Pointer to wlan_dfs structure.
391  *
392  * Return: Configured intermediate channel number.
393  */
394 uint32_t dfs_get_precac_intermediate_chan(struct wlan_dfs *dfs);
395 #else
396 static inline uint32_t dfs_get_intermediate_chan(struct wlan_dfs *dfs)
397 {
398 	return 0;
399 }
400 #endif
401 
402 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
403 /**
404  * dfs_get_precac_chan_state() - Get precac status of a given channel.
405  * @dfs:         Pointer to wlan_dfs structure.
406  * @precac_chan: Channel number for which precac state need to be checked.
407  *
408  * Return:
409  * * PRECAC_REQUIRED: Precac has not done on precac_chan.
410  * * PRECAC_NOW     : Precac is running on precac_chan.
411  * * PRECAC_DONE    : precac_chan is in precac done list.
412  * * PRECAC_NOL     : precac_chan is in precac NOL list.
413  * * PRECAC_ERR     : Invalid precac state.
414  */
415 enum precac_chan_state
416 dfs_get_precac_chan_state(struct wlan_dfs *dfs, uint8_t precac_chan);
417 #else
418 static inline enum precac_chan_state
419 dfs_get_precac_chan_state(struct wlan_dfs *dfs,
420 			  uint8_t precac_chan)
421 {
422 	return PRECAC_REQUIRED;
423 }
424 #endif
425 
426 /**
427  * dfs_zero_cac_reset() - Reset Zero cac DFS variables.
428  * @dfs: Pointer to wlan_dfs structure.
429  */
430 void dfs_zero_cac_reset(struct wlan_dfs *dfs);
431 
432 /**
433  * dfs_is_ht20_40_80_chan_in_precac_done_list() - Is precac done on a
434  *                                                VHT20/40/80 channel.
435  *@dfs: Pointer to wlan_dfs structure.
436  *@chan: Pointer to dfs_channel for which preCAC done is checked.
437  *
438  * Return:
439  * * True:  If channel is present in precac-done list.
440  * * False: If channel is not present in precac-done list.
441  */
442 bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs,
443 						struct dfs_channel *chan);
444 
445 /**
446  * dfs_is_ht80_80_chan_in_precac_done_list() - Is precac done on a VHT80+80
447  *                                             channel.
448  *@dfs: Pointer to wlan_dfs structure.
449  *@chan: Pointer to dfs_channel for which preCAC done is checked.
450  *
451  * Return:
452  * * True:  If channel is present in precac-done list.
453  * * False: If channel is not present in precac-done list.
454  */
455 bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs,
456 					     struct dfs_channel *chan);
457 
458 /**
459  * dfs_mark_precac_dfs() - Mark the precac channel as radar.
460  * @dfs: Pointer to wlan_dfs structure.
461  */
462 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
463 void dfs_mark_precac_dfs(struct wlan_dfs *dfs,
464 		uint8_t is_radar_found_on_secondary_seg);
465 #else
466 static inline void dfs_mark_precac_dfs(struct wlan_dfs *dfs,
467 		uint8_t is_radar_found_on_secondary_seg)
468 {
469 }
470 #endif
471 
472 /**
473  * dfs_is_precac_timer_running() - Check whether precac timer is running.
474  * @dfs: Pointer to wlan_dfs structure.
475  */
476 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
477 bool dfs_is_precac_timer_running(struct wlan_dfs *dfs);
478 #else
479 static inline bool dfs_is_precac_timer_running(struct wlan_dfs *dfs)
480 {
481 	return false;
482 }
483 #endif
484 #endif /* _DFS_ZERO_CAC_H_ */
485