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