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