xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/dfs_zero_cac.h (revision 8ddef7dd9a290d4a9b1efd5d3efacf51d78a1a0d)
1 /*
2  * Copyright (c) 2016-2019 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 	qdf_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) && !defined(QCA_MCL_DFS_SUPPORT)
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) && !defined(QCA_MCL_DFS_SUPPORT)
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) && !defined(QCA_MCL_DFS_SUPPORT)
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) && !defined(QCA_MCL_DFS_SUPPORT)
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) && !defined(QCA_MCL_DFS_SUPPORT)
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) && !defined(QCA_MCL_DFS_SUPPORT)
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) && !defined(QCA_MCL_DFS_SUPPORT)
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) && !defined(QCA_MCL_DFS_SUPPORT)
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_detach() - Free Zero cac DFS variables.
189  * @dfs: Pointer to wlan_dfs structure.
190  */
191 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT)
192 void dfs_zero_cac_timer_detach(struct wlan_dfs *dfs);
193 #else
194 static inline void dfs_zero_cac_timer_detach(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) && !defined(QCA_MCL_DFS_SUPPORT)
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: Configured DFS channel.
227  * @mode: Configured PHY mode.
228  *
229  * Return: True if intermediate channel needs to configure. False otherwise.
230  */
231 bool
232 dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs,
233 				  uint8_t *pref_chan,
234 				  enum wlan_phymode mode);
235 #else
236 static inline void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs,
237 						    uint8_t *pref_chan,
238 						    enum wlan_phymode mode)
239 {
240 }
241 #endif
242 
243 /**
244  * dfs_get_freq_from_precac_required_list() - Get VHT80 freq from
245  *                                            precac_required_list.
246  * @dfs: Pointer to wlan_dfs structure.
247  * @exclude_ieee_freq: Find a VHT80 freqency that is not equal to
248  *                     exclude_ieee_freq.
249  */
250 uint8_t dfs_get_freq_from_precac_required_list(struct wlan_dfs *dfs,
251 		uint8_t exclude_ieee_freq);
252 
253 /**
254  * dfs_override_precac_timeout() - Override the default precac timeout.
255  * @dfs: Pointer to wlan_dfs structure.
256  * @precac_timeout: Precac timeout value.
257  */
258 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT)
259 int dfs_override_precac_timeout(struct wlan_dfs *dfs,
260 		int precac_timeout);
261 #else
262 static inline int dfs_override_precac_timeout(struct wlan_dfs *dfs,
263 		int precac_timeout)
264 {
265 	return 0;
266 }
267 #endif
268 
269 /**
270  * dfs_get_override_precac_timeout() - Get precac timeout.
271  * @dfs: Pointer wlan_dfs structure.
272  * @precac_timeout: Get precac timeout value in this variable.
273  */
274 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT)
275 int dfs_get_override_precac_timeout(struct wlan_dfs *dfs,
276 		int *precac_timeout);
277 #else
278 static inline int dfs_get_override_precac_timeout(struct wlan_dfs *dfs,
279 		int *precac_timeout)
280 {
281 	return 0;
282 }
283 #endif
284 
285 /**
286  * dfs_find_vht80_chan_for_precac() - Find VHT80 channel for precac.
287  * @dfs: Pointer to wlan_dfs structure.
288  * @chan_mode: Channel mode.
289  * @ch_freq_seg1: Segment1 channel freq.
290  * @cfreq1: cfreq1.
291  * @cfreq2: cfreq2.
292  * @phy_mode: Precac phymode.
293  * @dfs_set_cfreq2: Precac cfreq2
294  * @set_agile: Agile mode flag.
295  *
296  * Zero-CAC-DFS algorithm:-
297  * Zero-CAC-DFS algorithm works in stealth mode.
298  * 1) When any channel change happens in VHT80 mode the algorithm
299  * changes the HW channel mode to VHT80_80/VHT160 mode and adds a
300  * new channel in the secondary VHT80 to perform precac and a
301  * precac timer is started. However the upper layer/UMAC is unaware
302  * of this change.
303  * 2) When the precac timer expires without being interrupted by
304  * any channel change the secondary VHT80 channel is moved from
305  * precac-required-list to precac-done-list.
306  * 3) If there is a radar detect at any time in any segment
307  * (segment-1 is preimary VHT80 and segment-2 is VHT80)then the
308  * channel is searched in both precac-reuired-list and precac-done-list
309  * and moved to precac-nol-list.
310  * 4) Whenever channel change happens if the new channel is a DFS
311  * channel then precac-done-list is searched and if the channel is
312  * found in the precac-done-list then the CAC is skipped.
313  * 5) The precac expiry timer makes a vedv_restart(channel change
314  * with current-upper-layer-channel-mode which is VHT80). In channel
315  * change the algorithm tries to pick a new channel from the
316  * precac-required list. If none found then channel mode remains same.
317  * Which means when all the channels in precac-required-list are
318  * exhausted the VHT80_80/VHT160 comes back to VHT80 mode.
319  */
320 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT)
321 void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs,
322 		uint32_t chan_mode,
323 		uint8_t ch_freq_seg1,
324 		uint32_t *cfreq1,
325 		uint32_t *cfreq2,
326 		uint32_t *phy_mode,
327 		bool *dfs_set_cfreq2,
328 		bool *set_agile);
329 #else
330 static inline void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs,
331 		uint32_t chan_mode,
332 		uint8_t ch_freq_seg1,
333 		uint32_t *cfreq1,
334 		uint32_t *cfreq2,
335 		uint32_t *phy_mode,
336 		bool *dfs_set_cfreq2,
337 		bool *set_agile)
338 {
339 }
340 #endif
341 
342 /**
343  * dfs_set_precac_enable() - Set precac enable flag.
344  * @dfs: Pointer to wlan_dfs structure.
345  * @value: input value for dfs_precac_enable flag.
346  */
347 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT)
348 void dfs_set_precac_enable(struct wlan_dfs *dfs,
349 		uint32_t value);
350 #else
351 static inline void dfs_set_precac_enable(struct wlan_dfs *dfs,
352 		uint32_t value)
353 {
354 }
355 #endif
356 
357 /**
358  * dfs_get_precac_enable() - Get precac enable flag.
359  * @dfs: Pointer to wlan_dfs structure.
360  */
361 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT)
362 uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs);
363 #else
364 static inline uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs)
365 {
366 	return 0;
367 }
368 #endif
369 
370 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
371 /**
372  * dfs_set_precac_intermediate_chan() - Set intermediate chan to be used while
373  *                                      doing precac.
374  * @dfs: Pointer to wlan_dfs structure.
375  * @value: input value for dfs_precac_enable flag.
376  *
377  * Return:
378  * * 0       - Successfully set intermediate channel.
379  * * -EINVAL - Invalid channel.
380  */
381 int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs,
382 					 uint32_t value);
383 #else
384 static inline int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs,
385 						       uint32_t value)
386 {
387 	return 0;
388 }
389 #endif
390 
391 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
392 /**
393  * dfs_get_precac_intermediate_chan() - Get configured precac
394  *					intermediate channel.
395  * @dfs: Pointer to wlan_dfs structure.
396  *
397  * Return: Configured intermediate channel number.
398  */
399 uint32_t dfs_get_precac_intermediate_chan(struct wlan_dfs *dfs);
400 #else
401 static inline uint32_t dfs_get_intermediate_chan(struct wlan_dfs *dfs)
402 {
403 	return 0;
404 }
405 #endif
406 
407 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
408 /**
409  * dfs_get_precac_chan_state() - Get precac status of a given channel.
410  * @dfs:         Pointer to wlan_dfs structure.
411  * @precac_chan: Channel number for which precac state need to be checked.
412  *
413  * Return:
414  * * PRECAC_REQUIRED: Precac has not done on precac_chan.
415  * * PRECAC_NOW     : Precac is running on precac_chan.
416  * * PRECAC_DONE    : precac_chan is in precac done list.
417  * * PRECAC_NOL     : precac_chan is in precac NOL list.
418  * * PRECAC_ERR     : Invalid precac state.
419  */
420 enum precac_chan_state
421 dfs_get_precac_chan_state(struct wlan_dfs *dfs, uint8_t precac_chan);
422 #else
423 static inline enum precac_chan_state
424 dfs_get_precac_chan_state(struct wlan_dfs *dfs,
425 			  uint8_t precac_chan)
426 {
427 	return PRECAC_REQUIRED;
428 }
429 #endif
430 
431 /**
432  * dfs_zero_cac_reset() - Reset Zero cac DFS variables.
433  * @dfs: Pointer to wlan_dfs structure.
434  */
435 void dfs_zero_cac_reset(struct wlan_dfs *dfs);
436 
437 /**
438  * dfs_is_ht20_40_80_chan_in_precac_done_list() - Is precac done on a
439  *                                                VHT20/40/80 channel.
440  *@dfs: Pointer to wlan_dfs structure.
441  *@chan: Pointer to dfs_channel for which preCAC done is checked.
442  *
443  * Return:
444  * * True:  If channel is present in precac-done list.
445  * * False: If channel is not present in precac-done list.
446  */
447 bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs,
448 						struct dfs_channel *chan);
449 
450 /**
451  * dfs_is_ht8080_ht160_chan_in_precac_done_list() - Is precac done on
452  *                                                  VHT80+80 or VHT160
453  *                                                  channel.
454  * @dfs: Pointer to wlan_dfs structure.
455  * @chan: Pointer to dfs_channel for which preCAC done is checked.
456  *
457  * Return:
458  * * True:  If channel is present in precac-done list.
459  * * False: If channel is not present in precac-done list.
460  */
461 bool dfs_is_ht8080_ht160_chan_in_precac_done_list(struct wlan_dfs *dfs,
462 						  struct dfs_channel *chan);
463 
464 /**
465  * dfs_mark_precac_dfs() - Mark the precac channel as radar.
466  * @dfs: Pointer to wlan_dfs structure.
467  */
468 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT)
469 void dfs_mark_precac_dfs(struct wlan_dfs *dfs,
470 		uint8_t is_radar_found_on_secondary_seg);
471 #else
472 static inline void dfs_mark_precac_dfs(struct wlan_dfs *dfs,
473 		uint8_t is_radar_found_on_secondary_seg)
474 {
475 }
476 #endif
477 
478 /**
479  * dfs_is_precac_timer_running() - Check whether precac timer is running.
480  * @dfs: Pointer to wlan_dfs structure.
481  */
482 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT)
483 bool dfs_is_precac_timer_running(struct wlan_dfs *dfs);
484 #else
485 static inline bool dfs_is_precac_timer_running(struct wlan_dfs *dfs)
486 {
487 	return false;
488 }
489 #endif
490 #endif /* _DFS_ZERO_CAC_H_ */
491