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