xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/dfs_zero_cac.h (revision a175314c51a4ce5cec2835cc8a8c7dc0c1810915)
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 void dfs_start_precac_timer(struct wlan_dfs *dfs,
142 		uint8_t precac_chan);
143 
144 /**
145  * dfs_cancel_precac_timer() - Cancel the precac timer.
146  * @dfs: Pointer to wlan_dfs structure.
147  */
148 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
149 void dfs_cancel_precac_timer(struct wlan_dfs *dfs);
150 #else
151 static inline void dfs_cancel_precac_timer(struct wlan_dfs *dfs)
152 {
153 }
154 #endif
155 
156 /**
157  * dfs_zero_cac_attach() - Initialize dfs zerocac variables.
158  * @dfs: Pointer to DFS structure.
159  */
160 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
161 void dfs_zero_cac_attach(struct wlan_dfs *dfs);
162 #else
163 static inline void dfs_zero_cac_attach(struct wlan_dfs *dfs)
164 {
165 }
166 #endif
167 
168 /**
169  * dfs_zero_cac_reset() - Reset Zero cac DFS variables.
170  * @dfs: Pointer to wlan_dfs structure.
171  */
172 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
173 void dfs_zero_cac_reset(struct wlan_dfs *dfs);
174 #else
175 static inline void dfs_zero_cac_reset(struct wlan_dfs *dfs)
176 {
177 }
178 #endif
179 
180 /**
181  * dfs_is_precac_done() - Is precac done.
182  * @dfs: Pointer to wlan_dfs structure.
183  * @chan: Pointer to dfs_channel for which preCAC done is checked.
184  *
185  * Return:
186  * * True:  If precac is done on channel.
187  * * False: If precac is not done on channel.
188  */
189 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
190 bool dfs_is_precac_done(struct wlan_dfs *dfs, struct dfs_channel *chan);
191 #else
192 static inline bool dfs_is_precac_done(struct wlan_dfs *dfs,
193 				      struct dfs_channel *chan)
194 {
195 	return false;
196 }
197 #endif
198 
199 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
200 /**
201  * dfs_decide_precac_preferred_chan() - Choose operating channel among
202  *                                      configured DFS channel and
203  *                                      intermediate channel based on
204  *                                      precac status of configured
205  *                                      DFS channel.
206  * @dfs: Pointer to wlan_dfs structure.
207  * @pref_chan: Congigired DFS channel.
208  *
209  * Return: void.
210  */
211 void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs, uint8_t *pref_chan);
212 #else
213 static inline void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs,
214 						    uint8_t *pref_chan)
215 {
216 }
217 #endif
218 
219 /**
220  * dfs_get_freq_from_precac_required_list() - Get VHT80 freq from
221  *                                            precac_required_list.
222  * @dfs: Pointer to wlan_dfs structure.
223  * @exclude_ieee_freq: Find a VHT80 freqency that is not equal to
224  *                     exclude_ieee_freq.
225  */
226 uint8_t dfs_get_freq_from_precac_required_list(struct wlan_dfs *dfs,
227 		uint8_t exclude_ieee_freq);
228 
229 /**
230  * dfs_override_precac_timeout() - Override the default precac timeout.
231  * @dfs: Pointer to wlan_dfs structure.
232  * @precac_timeout: Precac timeout value.
233  */
234 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
235 int dfs_override_precac_timeout(struct wlan_dfs *dfs,
236 		int precac_timeout);
237 #else
238 static inline int dfs_override_precac_timeout(struct wlan_dfs *dfs,
239 		int precac_timeout)
240 {
241 	return 0;
242 }
243 #endif
244 
245 /**
246  * dfs_get_override_precac_timeout() - Get precac timeout.
247  * @dfs: Pointer wlan_dfs structure.
248  * @precac_timeout: Get precac timeout value in this variable.
249  */
250 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
251 int dfs_get_override_precac_timeout(struct wlan_dfs *dfs,
252 		int *precac_timeout);
253 #else
254 static inline int dfs_get_override_precac_timeout(struct wlan_dfs *dfs,
255 		int *precac_timeout)
256 {
257 	return 0;
258 }
259 #endif
260 
261 /**
262  * dfs_find_vht80_chan_for_precac() - Find VHT80 channel for precac.
263  * @dfs: Pointer to wlan_dfs structure.
264  * @chan_mode: Channel mode.
265  * @ch_freq_seg1: Segment1 channel freq.
266  * @cfreq1: cfreq1.
267  * @cfreq2: cfreq2.
268  * @phy_mode: Precac phymode.
269  * @dfs_set_cfreq2: Precac cfreq2
270  * @set_agile: Agile mode flag.
271  *
272  * Zero-CAC-DFS algorithm:-
273  * Zero-CAC-DFS algorithm works in stealth mode.
274  * 1) When any channel change happens in VHT80 mode the algorithm
275  * changes the HW channel mode to VHT80_80/VHT160 mode and adds a
276  * new channel in the secondary VHT80 to perform precac and a
277  * precac timer is started. However the upper layer/UMAC is unaware
278  * of this change.
279  * 2) When the precac timer expires without being interrupted by
280  * any channel change the secondary VHT80 channel is moved from
281  * precac-required-list to precac-done-list.
282  * 3) If there is a radar detect at any time in any segment
283  * (segment-1 is preimary VHT80 and segment-2 is VHT80)then the
284  * channel is searched in both precac-reuired-list and precac-done-list
285  * and moved to precac-nol-list.
286  * 4) Whenever channel change happens if the new channel is a DFS
287  * channel then precac-done-list is searched and if the channel is
288  * found in the precac-done-list then the CAC is skipped.
289  * 5) The precac expiry timer makes a vedv_restart(channel change
290  * with current-upper-layer-channel-mode which is VHT80). In channel
291  * change the algorithm tries to pick a new channel from the
292  * precac-required list. If none found then channel mode remains same.
293  * Which means when all the channels in precac-required-list are
294  * exhausted the VHT80_80/VHT160 comes back to VHT80 mode.
295  */
296 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
297 void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs,
298 		uint32_t chan_mode,
299 		uint8_t ch_freq_seg1,
300 		uint32_t *cfreq1,
301 		uint32_t *cfreq2,
302 		uint32_t *phy_mode,
303 		bool *dfs_set_cfreq2,
304 		bool *set_agile);
305 #else
306 static inline void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs,
307 		uint32_t chan_mode,
308 		uint8_t ch_freq_seg1,
309 		uint32_t *cfreq1,
310 		uint32_t *cfreq2,
311 		uint32_t *phy_mode,
312 		bool *dfs_set_cfreq2,
313 		bool *set_agile)
314 {
315 }
316 #endif
317 
318 /**
319  * dfs_set_precac_enable() - Set precac enable flag.
320  * @dfs: Pointer to wlan_dfs structure.
321  * @value: input value for dfs_precac_enable flag.
322  */
323 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
324 void dfs_set_precac_enable(struct wlan_dfs *dfs,
325 		uint32_t value);
326 #else
327 static inline void dfs_set_precac_enable(struct wlan_dfs *dfs,
328 		uint32_t value)
329 {
330 }
331 #endif
332 
333 /**
334  * dfs_get_precac_enable() - Get precac enable flag.
335  * @dfs: Pointer to wlan_dfs structure.
336  */
337 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
338 uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs);
339 #else
340 static inline uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs)
341 {
342 	return 0;
343 }
344 #endif
345 
346 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
347 /**
348  * dfs_set_precac_intermediate_chan() - Set intermediate chan to be used while
349  *                                      doing precac.
350  * @dfs: Pointer to wlan_dfs structure.
351  * @value: input value for dfs_precac_enable flag.
352  *
353  * Return:
354  * * 0       - Successfully set intermediate channel.
355  * * -EINVAL - Invalid channel.
356  */
357 int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs,
358 					 uint32_t value);
359 #else
360 static inline int32_t dfs_set_precac_intermediate_chan(struct wlan_dfs *dfs,
361 						       uint32_t value)
362 {
363 	return 0;
364 }
365 #endif
366 
367 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
368 /**
369  * dfs_get_precac_intermediate_chan() - Get configured precac
370  *					intermediate channel.
371  * @dfs: Pointer to wlan_dfs structure.
372  *
373  * Return: Configured intermediate channel number.
374  */
375 uint32_t dfs_get_precac_intermediate_chan(struct wlan_dfs *dfs);
376 #else
377 static inline uint32_t dfs_get_intermediate_chan(struct wlan_dfs *dfs)
378 {
379 	return 0;
380 }
381 #endif
382 
383 #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT
384 /**
385  * dfs_get_precac_chan_state() - Get precac status of a given channel.
386  * @dfs:         Pointer to wlan_dfs structure.
387  * @precac_chan: Channel number for which precac state need to be checked.
388  *
389  * Return:
390  * * PRECAC_REQUIRED: Precac has not done on precac_chan.
391  * * PRECAC_NOW     : Precac is running on precac_chan.
392  * * PRECAC_DONE    : precac_chan is in precac done list.
393  * * PRECAC_NOL     : precac_chan is in precac NOL list.
394  * * PRECAC_ERR     : Invalid precac state.
395  */
396 enum precac_chan_state
397 dfs_get_precac_chan_state(struct wlan_dfs *dfs, uint8_t precac_chan);
398 #else
399 static inline enum precac_chan_state
400 dfs_get_precac_chan_state(struct wlan_dfs *dfs,
401 			  uint8_t precac_chan)
402 {
403 	return PRECAC_REQUIRED;
404 }
405 #endif
406 
407 /**
408  * dfs_zero_cac_reset() - Reset Zero cac DFS variables.
409  * @dfs: Pointer to wlan_dfs structure.
410  */
411 void dfs_zero_cac_reset(struct wlan_dfs *dfs);
412 
413 /**
414  * dfs_is_ht20_40_80_chan_in_precac_done_list() - Is precac done on a
415  *                                                VHT20/40/80 channel.
416  *@dfs: Pointer to wlan_dfs structure.
417  *@chan: Pointer to dfs_channel for which preCAC done is checked.
418  *
419  * Return:
420  * * True:  If channel is present in precac-done list.
421  * * False: If channel is not present in precac-done list.
422  */
423 bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs,
424 						struct dfs_channel *chan);
425 
426 /**
427  * dfs_is_ht80_80_chan_in_precac_done_list() - Is precac done on a VHT80+80
428  *                                             channel.
429  *@dfs: Pointer to wlan_dfs structure.
430  *@chan: Pointer to dfs_channel for which preCAC done is checked.
431  *
432  * Return:
433  * * True:  If channel is present in precac-done list.
434  * * False: If channel is not present in precac-done list.
435  */
436 bool dfs_is_ht80_80_chan_in_precac_done_list(struct wlan_dfs *dfs,
437 					     struct dfs_channel *chan);
438 
439 /**
440  * dfs_mark_precac_dfs() - Mark the precac channel as radar.
441  * @dfs: Pointer to wlan_dfs structure.
442  */
443 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
444 void dfs_mark_precac_dfs(struct wlan_dfs *dfs,
445 		uint8_t is_radar_found_on_secondary_seg);
446 #else
447 static inline void dfs_mark_precac_dfs(struct wlan_dfs *dfs,
448 		uint8_t is_radar_found_on_secondary_seg)
449 {
450 }
451 #endif
452 
453 /**
454  * dfs_is_precac_timer_running() - Check whether precac timer is running.
455  * @dfs: Pointer to wlan_dfs structure.
456  */
457 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
458 bool dfs_is_precac_timer_running(struct wlan_dfs *dfs);
459 #else
460 static inline bool dfs_is_precac_timer_running(struct wlan_dfs *dfs)
461 {
462 	return false;
463 }
464 #endif
465 #endif /* _DFS_ZERO_CAC_H_ */
466