1 /* 2 * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. 3 * 4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc. 5 * 6 * 7 * Permission to use, copy, modify, and/or distribute this software for 8 * any purpose with or without fee is hereby granted, provided that the 9 * above copyright notice and this permission notice appear in all 10 * copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 19 * PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 /* 23 * This file was originally distributed by Qualcomm Atheros, Inc. 24 * under proprietary terms before Copyright ownership was assigned 25 * to the Linux Foundation. 26 */ 27 28 #include "../dfs.h" 29 #include "../dfs_random_chan_sel.h" 30 #include <qdf_mc_timer.h> 31 #include <wlan_utility.h> 32 33 #ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION 34 /* 35 * TODO: At present SAP Channel leakage matrix for ch 144 36 * is not available from system's team. So to play it safe 37 * and avoid crash if channel 144 is request, in following 38 * matix channel 144 is added such that it will cause code 39 * to avoid selecting channel 144. 40 * 41 * THESE ENTRIES SHOULD BE REPLACED WITH CORRECT VALUES AS 42 * PROVIDED BY SYSTEM'S TEAM. 43 */ 44 45 /* channel tx leakage table - ht80 */ 46 struct dfs_matrix_tx_leak_info ht80_chan[] = { 47 {52, 48 {{36, 148}, {40, 199}, 49 {44, 193}, {48, 197}, 50 {52, DFS_TX_LEAKAGE_MIN}, {56, 153}, 51 {60, 137}, {64, 134}, 52 {100, 358}, {104, 350}, 53 {108, 404}, {112, 344}, 54 {116, 424}, {120, 429}, 55 {124, 437}, {128, 435}, 56 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 57 {140, DFS_TX_LEAKAGE_MAX}, 58 {144, DFS_TX_LEAKAGE_MIN} 59 } }, 60 61 62 {56, 63 {{36, 171}, {40, 178}, 64 {44, 171}, {48, 178}, 65 {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, 66 {60, DFS_TX_LEAKAGE_MIN}, {64, 280}, 67 {100, 351}, {104, 376}, 68 {108, 362}, {112, 362}, 69 {116, 403}, {120, 397}, 70 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 71 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 72 {140, DFS_TX_LEAKAGE_MAX}, 73 {144, DFS_TX_LEAKAGE_MIN} 74 } }, 75 76 {60, 77 {{36, 156}, {40, 146}, 78 {44, DFS_TX_LEAKAGE_MIN}, {48, DFS_TX_LEAKAGE_MIN}, 79 {52, 180}, {56, DFS_TX_LEAKAGE_MIN}, 80 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 81 {100, 376}, {104, 360}, 82 {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, 83 {116, 395}, {120, 399}, 84 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 85 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 86 {140, DFS_TX_LEAKAGE_MAX}, 87 {144, DFS_TX_LEAKAGE_MIN} 88 } }, 89 90 {64, 91 {{36, 217}, {40, 221}, 92 {44, DFS_TX_LEAKAGE_MIN}, {48, DFS_TX_LEAKAGE_MIN}, 93 {52, 176}, {56, 176}, 94 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 95 {100, 384}, {104, 390}, 96 {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, 97 {116, 375}, {120, 374}, 98 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 99 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 100 {140, DFS_TX_LEAKAGE_MAX}, 101 {144, DFS_TX_LEAKAGE_MIN} 102 } }, 103 104 {100, 105 {{36, 357}, {40, 326}, 106 {44, 321}, {48, 326}, 107 {52, 378}, {56, 396}, 108 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 109 {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, 110 {108, 196}, {112, 116}, 111 {116, 166}, {120, DFS_TX_LEAKAGE_MIN}, 112 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 113 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 114 {140, DFS_TX_LEAKAGE_MIN}, 115 {144, DFS_TX_LEAKAGE_MIN} 116 } }, 117 118 {104, 119 {{36, 325}, {40, 325}, 120 {44, 305}, {48, 352}, 121 {52, 411}, {56, 411}, 122 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 123 {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, 124 {108, DFS_TX_LEAKAGE_MIN}, {112, 460}, 125 {116, 198}, {120, DFS_TX_LEAKAGE_MIN}, 126 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 127 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 128 {140, DFS_TX_LEAKAGE_MIN}, 129 {144, DFS_TX_LEAKAGE_MIN} 130 } }, 131 132 {108, 133 {{36, 304}, {40, 332}, 134 {44, 310}, {48, 335}, 135 {52, 431}, {56, 391}, 136 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 137 {100, 280}, {104, DFS_TX_LEAKAGE_MIN}, 138 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 139 {116, 185}, {120, DFS_TX_LEAKAGE_MIN}, 140 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 141 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 142 {140, DFS_TX_LEAKAGE_MIN}, 143 {144, DFS_TX_LEAKAGE_MIN} 144 } }, 145 146 {112, 147 {{36, 327}, {40, 335}, 148 {44, 331}, {48, 345}, 149 {52, 367}, {56, 401}, 150 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 151 {100, 131}, {104, 132}, 152 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 153 {116, 189}, {120, DFS_TX_LEAKAGE_MIN}, 154 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 155 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 156 {140, DFS_TX_LEAKAGE_MIN}, 157 {144, DFS_TX_LEAKAGE_MIN} 158 } }, 159 160 {116, 161 {{36, 384}, {40, 372}, 162 {44, 389}, {48, 396}, 163 {52, 348}, {56, 336}, 164 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 165 {100, 172}, {104, 169}, 166 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 167 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 168 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 169 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 170 {140, DFS_TX_LEAKAGE_MIN}, 171 {144, DFS_TX_LEAKAGE_MIN} 172 } }, 173 174 {120, 175 {{36, 395}, {40, 419}, 176 {44, 439}, {48, 407}, 177 {52, 321}, {56, 334}, 178 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 179 {100, 134}, {104, 186}, 180 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 181 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 182 {124, DFS_TX_LEAKAGE_MIN}, {128, 159}, 183 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 184 {140, DFS_TX_LEAKAGE_MIN}, 185 {144, DFS_TX_LEAKAGE_MIN} 186 } }, 187 188 {124, 189 {{36, 469}, {40, 433}, 190 {44, 434}, {48, 435}, 191 {52, 332}, {56, 345}, 192 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 193 {100, 146}, {104, 177}, 194 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 195 {116, 350}, {120, DFS_TX_LEAKAGE_MIN}, 196 {124, DFS_TX_LEAKAGE_MIN}, {128, 138}, 197 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 198 {140, DFS_TX_LEAKAGE_MIN}, 199 {144, DFS_TX_LEAKAGE_MIN} 200 } }, 201 202 {128, 203 {{36, 408}, {40, 434}, 204 {44, 449}, {48, 444}, 205 {52, 341}, {56, 374}, 206 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 207 {100, 205}, {104, 208}, 208 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 209 {116, 142}, {120, DFS_TX_LEAKAGE_MIN}, 210 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 211 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 212 {140, DFS_TX_LEAKAGE_MIN}, 213 {144, DFS_TX_LEAKAGE_MIN} 214 } }, 215 216 {132, 217 {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX}, 218 {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX}, 219 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 220 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 221 {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, 222 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 223 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 224 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 225 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 226 {140, DFS_TX_LEAKAGE_MIN}, 227 {144, DFS_TX_LEAKAGE_MIN} 228 } }, 229 230 {136, 231 {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX}, 232 {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX}, 233 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 234 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 235 {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, 236 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 237 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 238 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 239 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 240 {140, DFS_TX_LEAKAGE_MIN}, 241 {144, DFS_TX_LEAKAGE_MIN} 242 } }, 243 244 {140, 245 {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX}, 246 {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX}, 247 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 248 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 249 {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, 250 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 251 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 252 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 253 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 254 {144, DFS_TX_LEAKAGE_MIN} 255 } }, 256 257 {144, 258 {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX}, 259 {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX}, 260 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 261 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 262 {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, 263 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 264 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 265 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 266 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 267 {144, DFS_TX_LEAKAGE_MIN} 268 } }, 269 }; 270 271 /* channel tx leakage table - ht40 */ 272 struct dfs_matrix_tx_leak_info ht40_chan[] = { 273 {52, 274 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, 275 {44, 230}, {48, 230}, 276 {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, 277 {60, DFS_TX_LEAKAGE_AUTO_MIN}, {64, DFS_TX_LEAKAGE_AUTO_MIN}, 278 {100, 625}, {104, 323}, 279 {108, 646}, {112, 646}, 280 {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, 281 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 282 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 283 {140, DFS_TX_LEAKAGE_MAX}, 284 {144, DFS_TX_LEAKAGE_MIN} 285 } }, 286 287 {56, 288 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, 289 {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, DFS_TX_LEAKAGE_AUTO_MIN}, 290 {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, 291 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 292 {100, 611}, {104, 611}, 293 {108, 617}, {112, 617}, 294 {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, 295 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 296 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 297 {140, DFS_TX_LEAKAGE_MAX}, 298 {144, DFS_TX_LEAKAGE_MIN} 299 } }, 300 301 {60, 302 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, 303 {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, DFS_TX_LEAKAGE_AUTO_MIN}, 304 {52, 190}, {56, 190}, 305 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 306 {100, 608}, {104, 608}, 307 {108, 623}, {112, 623}, 308 {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, 309 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 310 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 311 {140, DFS_TX_LEAKAGE_MAX}, 312 {144, DFS_TX_LEAKAGE_MIN} 313 } }, 314 315 {64, 316 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, 317 {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, DFS_TX_LEAKAGE_AUTO_MIN}, 318 {52, 295}, {56, 295}, 319 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 320 {100, 594}, {104, 594}, 321 {108, 625}, {112, 625}, 322 {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, 323 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 324 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 325 {140, DFS_TX_LEAKAGE_MAX}, 326 {144, DFS_TX_LEAKAGE_MIN} 327 } }, 328 329 {100, 330 {{36, 618}, {40, 618}, 331 {44, 604}, {48, 604}, 332 {52, 596}, {56, 596}, 333 {60, 584}, {64, 584}, 334 {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, 335 {108, 299}, {112, 299}, 336 {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, 337 {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, 338 {132, 538}, {136, 538}, 339 {140, 598}, 340 {144, DFS_TX_LEAKAGE_MIN} 341 } }, 342 343 {104, 344 {{36, 636}, {40, 636}, 345 {44, 601}, {48, 601}, 346 {52, 616}, {56, 616}, 347 {60, 584}, {64, 584}, 348 {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, 349 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 350 {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, 351 {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, 352 {132, 553}, {136, 553}, 353 {140, 568}, 354 {144, DFS_TX_LEAKAGE_MIN} 355 } }, 356 357 {108, 358 {{36, 600}, {40, 600}, 359 {44, 627}, {48, 627}, 360 {52, 611}, {56, 611}, 361 {60, 611}, {64, 611}, 362 {100, 214}, {104, 214}, 363 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 364 {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, 365 {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, 366 {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, 367 {140, 534}, 368 {144, DFS_TX_LEAKAGE_MIN} 369 } }, 370 371 {112, 372 {{36, 645}, {40, 645}, 373 {44, 641}, {48, 641}, 374 {52, 618}, {56, 618}, 375 {60, 612}, {64, 612}, 376 {100, 293}, {104, 293}, 377 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 378 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 379 {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, 380 {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, 381 {140, 521}, 382 {144, DFS_TX_LEAKAGE_MIN} 383 } }, 384 385 {116, 386 {{36, 661}, {40, 661}, 387 {44, 624}, {48, 624}, 388 {52, 634}, {56, 634}, 389 {60, 611}, {64, 611}, 390 {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN}, 391 {108, 217}, {112, 217}, 392 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 393 {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, 394 {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, 395 {140, DFS_TX_LEAKAGE_AUTO_MIN}, 396 {144, DFS_TX_LEAKAGE_MIN} 397 } }, 398 399 {120, 400 {{36, 667}, {40, 667}, 401 {44, 645}, {48, 645}, 402 {52, 633}, {56, 633}, 403 {60, 619}, {64, 619}, 404 {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN}, 405 {108, 291}, {112, 291}, 406 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 407 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 408 {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, 409 {140, DFS_TX_LEAKAGE_AUTO_MIN}, 410 {144, DFS_TX_LEAKAGE_MIN} 411 } }, 412 413 {124, 414 {{36, 676}, {40, 676}, 415 {44, 668}, {48, 668}, 416 {52, 595}, {56, 595}, 417 {60, 622}, {64, 622}, 418 {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN}, 419 {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, 420 {116, 225}, {120, 225}, 421 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 422 {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, 423 {140, DFS_TX_LEAKAGE_AUTO_MIN}, 424 {144, DFS_TX_LEAKAGE_MIN} 425 } }, 426 427 {128, 428 {{36, 678}, {40, 678}, 429 {44, 664}, {48, 664}, 430 {52, 651}, {56, 651}, 431 {60, 643}, {64, 643}, 432 {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN}, 433 {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, 434 {116, 293}, {120, 293}, 435 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 436 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 437 {140, DFS_TX_LEAKAGE_AUTO_MIN}, 438 {144, DFS_TX_LEAKAGE_MIN} 439 } }, 440 441 {132, 442 {{36, 689}, {40, 689}, 443 {44, 669}, {48, 669}, 444 {52, 662}, {56, 662}, 445 {60, 609}, {64, 609}, 446 {100, 538}, {104, 538}, 447 {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, 448 {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, 449 {124, 247}, {128, 247}, 450 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 451 {140, DFS_TX_LEAKAGE_MIN}, 452 {144, DFS_TX_LEAKAGE_MIN} 453 } }, 454 455 {136, 456 {{36, 703}, {40, 703}, 457 {44, 688}, {48, DFS_TX_LEAKAGE_MIN}, 458 {52, 671}, {56, 671}, 459 {60, 658}, {64, 658}, 460 {100, 504}, {104, 504}, 461 {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, 462 {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, 463 {124, 289}, {128, 289}, 464 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 465 {140, DFS_TX_LEAKAGE_MIN}, 466 {144, DFS_TX_LEAKAGE_MIN} 467 } }, 468 469 {140, 470 {{36, 695}, {40, 695}, 471 {44, 684}, {48, 684}, 472 {52, 664}, {56, 664}, 473 {60, 658}, {64, 658}, 474 {100, 601}, {104, 601}, 475 {108, 545}, {112, 545}, 476 {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, 477 {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, 478 {132, 262}, {136, 262}, 479 {140, DFS_TX_LEAKAGE_MIN}, 480 {144, DFS_TX_LEAKAGE_MIN} 481 } }, 482 483 {144, 484 {{36, 695}, {40, 695}, 485 {44, 684}, {48, 684}, 486 {52, 664}, {56, 664}, 487 {60, 658}, {64, 658}, 488 {100, 601}, {104, 601}, 489 {108, 545}, {112, 545}, 490 {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, 491 {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, 492 {132, 262}, {136, 262}, 493 {140, DFS_TX_LEAKAGE_MIN}, 494 {144, DFS_TX_LEAKAGE_MIN} 495 } }, 496 }; 497 498 /* channel tx leakage table - ht20 */ 499 struct dfs_matrix_tx_leak_info ht20_chan[] = { 500 {52, 501 {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 286}, 502 {44, 225}, {48, 121}, 503 {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, 504 {60, 300}, {64, DFS_TX_LEAKAGE_AUTO_MIN}, 505 {100, 637}, {104, DFS_TX_LEAKAGE_MAX}, 506 {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, 507 {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, 508 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 509 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 510 {140, DFS_TX_LEAKAGE_MAX}, 511 {144, DFS_TX_LEAKAGE_MIN} 512 } }, 513 514 {56, 515 {{36, 468}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, 516 {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 206}, 517 {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, 518 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 519 {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, 520 {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, 521 {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, 522 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 523 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 524 {140, DFS_TX_LEAKAGE_MAX}, 525 {144, DFS_TX_LEAKAGE_MIN} 526 } }, 527 528 {60, 529 {{36, 507}, {40, 440}, 530 {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 313}, 531 {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, 532 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 533 {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, 534 {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, 535 {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, 536 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 537 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 538 {140, DFS_TX_LEAKAGE_MAX}, 539 {144, DFS_TX_LEAKAGE_MIN} 540 } }, 541 542 {64, 543 {{36, 516}, {40, 520}, 544 {44, 506}, {48, DFS_TX_LEAKAGE_AUTO_MIN}, 545 {52, 301}, {56, 258}, 546 {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, 547 {100, 620}, {104, 617}, 548 {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, 549 {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, 550 {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, 551 {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, 552 {140, DFS_TX_LEAKAGE_MAX}, 553 {144, DFS_TX_LEAKAGE_MIN} 554 } }, 555 556 {100, 557 {{36, 616}, {40, 601}, 558 {44, 604}, {48, 589}, 559 {52, 612}, {56, 592}, 560 {60, 590}, {64, 582}, 561 {100, DFS_TX_LEAKAGE_MIN}, {104, 131}, 562 {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, 563 {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 522}, 564 {124, 571}, {128, 589}, 565 {132, 593}, {136, 598}, 566 {140, 594}, 567 {144, DFS_TX_LEAKAGE_MIN}, 568 } }, 569 570 {104, 571 {{36, 622}, {40, 624}, 572 {44, 618}, {48, 610}, 573 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 574 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 575 {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, 576 {108, DFS_TX_LEAKAGE_MIN}, {112, 463}, 577 {116, 483}, {120, 503}, 578 {124, 523}, {128, 565}, 579 {132, 570}, {136, 588}, 580 {140, 585}, 581 {144, DFS_TX_LEAKAGE_MIN}, 582 } }, 583 584 {108, 585 {{36, 620}, {40, 638}, 586 {44, 611}, {48, 614}, 587 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 588 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 589 {100, 477}, {104, DFS_TX_LEAKAGE_MIN}, 590 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 591 {116, 477}, {120, 497}, 592 {124, 517}, {128, 537}, 593 {132, 557}, {136, 577}, 594 {140, 603}, 595 {144, DFS_TX_LEAKAGE_MIN}, 596 } }, 597 598 {112, 599 {{36, 636}, {40, 623}, 600 {44, 638}, {48, 628}, 601 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 602 {60, DFS_TX_LEAKAGE_MAX}, {64, 606}, 603 {100, 501}, {104, 481}, 604 {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, 605 {116, DFS_TX_LEAKAGE_MIN}, {120, 481}, 606 {124, 501}, {128, 421}, 607 {132, 541}, {136, 561}, 608 {140, 583}, 609 {144, DFS_TX_LEAKAGE_MIN}, 610 } }, 611 612 {116, 613 {{36, 646}, {40, 648}, 614 {44, 633}, {48, 634}, 615 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 616 {60, 615}, {64, 594}, 617 {100, 575}, {104, 554}, 618 {108, 534}, {112, DFS_TX_LEAKAGE_MIN}, 619 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 620 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 621 {132, 534}, {136, 554}, 622 {140, 574}, 623 {144, DFS_TX_LEAKAGE_MIN}, 624 } }, 625 626 {120, 627 {{36, 643}, {40, 649}, 628 {44, 654}, {48, 629}, 629 {52, DFS_TX_LEAKAGE_MAX}, {56, 621}, 630 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 631 {100, 565}, {104, 545}, 632 {108, 525}, {112, 505}, 633 {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, 634 {124, DFS_TX_LEAKAGE_MIN}, {128, 505}, 635 {132, 525}, {136, 545}, 636 {140, 565}, 637 {144, DFS_TX_LEAKAGE_MIN}, 638 } }, 639 640 {124, 641 {{36, 638}, {40, 657}, 642 {44, 663}, {48, 649}, 643 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 644 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 645 {100, 581}, {104, 561}, 646 {108, 541}, {112, 521}, 647 {116, 499}, {120, DFS_TX_LEAKAGE_MIN}, 648 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 649 {132, 499}, {136, 519}, 650 {140, 539}, 651 {144, DFS_TX_LEAKAGE_MIN} 652 } }, 653 654 {128, 655 {{36, 651}, {40, 651}, 656 {44, 674}, {48, 640}, 657 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 658 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 659 {100, 603}, {104, 560}, 660 {108, 540}, {112, 520}, 661 {116, 499}, {120, 479}, 662 {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, 663 {132, DFS_TX_LEAKAGE_MIN}, {136, 479}, 664 {140, 499}, 665 {144, DFS_TX_LEAKAGE_MIN} 666 } }, 667 668 {132, 669 {{36, 643}, {40, 668}, 670 {44, 651}, {48, 657}, 671 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 672 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 673 {100, DFS_TX_LEAKAGE_MAX}, {104, 602}, 674 {108, 578}, {112, 570}, 675 {116, 550}, {120, 530}, 676 {124, 510}, {128, DFS_TX_LEAKAGE_MIN}, 677 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 678 {140, 490}, 679 {144, DFS_TX_LEAKAGE_MIN} 680 } }, 681 682 {136, 683 {{36, 654}, {40, 667}, 684 {44, 666}, {48, 642}, 685 {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, 686 {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, 687 {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, 688 {108, DFS_TX_LEAKAGE_MAX}, {112, 596}, 689 {116, 555}, {120, 535}, 690 {124, 515}, {128, 495}, 691 {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, 692 {140, DFS_TX_LEAKAGE_MIN}, 693 {144, DFS_TX_LEAKAGE_MIN} 694 } }, 695 696 {140, 697 {{36, 679}, {40, 673}, 698 {44, 667}, {48, 656}, 699 {52, 634}, {56, 663}, 700 {60, 662}, {64, 660}, 701 {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, 702 {108, DFS_TX_LEAKAGE_MAX}, {112, 590}, 703 {116, 573}, {120, 553}, 704 {124, 533}, {128, 513}, 705 {132, 490}, {136, DFS_TX_LEAKAGE_MIN}, 706 {140, DFS_TX_LEAKAGE_MIN}, 707 {144, DFS_TX_LEAKAGE_MIN} 708 } }, 709 710 {144, 711 {{36, 679}, {40, 673}, 712 {44, 667}, {48, 656}, 713 {52, 634}, {56, 663}, 714 {60, 662}, {64, 660}, 715 {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, 716 {108, DFS_TX_LEAKAGE_MAX}, {112, 590}, 717 {116, 573}, {120, 553}, 718 {124, 533}, {128, 513}, 719 {132, 490}, {136, DFS_TX_LEAKAGE_MIN}, 720 {140, DFS_TX_LEAKAGE_MIN}, 721 {144, DFS_TX_LEAKAGE_MIN} 722 } }, 723 }; 724 725 /* 726 * dfs_find_target_channel_in_channel_matrix() - finds the leakage matrix 727 * @ch_width: target channel width 728 * @NOL_channel: the NOL channel whose leakage matrix is required 729 * @pTarget_chnl_mtrx: pointer to target channel matrix returned. 730 * 731 * This function gives the leakage matrix for given NOL channel and ch_width 732 * 733 * Return: TRUE or FALSE 734 */ 735 static bool 736 dfs_find_target_channel_in_channel_matrix(enum phy_ch_width ch_width, 737 uint8_t NOL_channel, 738 struct dfs_tx_leak_info **pTarget_chnl_mtrx) 739 { 740 struct dfs_tx_leak_info *target_chan_matrix = NULL; 741 struct dfs_matrix_tx_leak_info *pchan_matrix = NULL; 742 uint32_t nchan_matrix; 743 int i = 0; 744 745 switch (ch_width) { 746 case CH_WIDTH_20MHZ: 747 /* HT20 */ 748 pchan_matrix = ht20_chan; 749 nchan_matrix = QDF_ARRAY_SIZE(ht20_chan); 750 break; 751 case CH_WIDTH_40MHZ: 752 /* HT40 */ 753 pchan_matrix = ht40_chan; 754 nchan_matrix = QDF_ARRAY_SIZE(ht40_chan); 755 break; 756 case CH_WIDTH_80MHZ: 757 /* HT80 */ 758 pchan_matrix = ht80_chan; 759 nchan_matrix = QDF_ARRAY_SIZE(ht80_chan); 760 break; 761 default: 762 /* handle exception and fall back to HT20 table */ 763 pchan_matrix = ht20_chan; 764 nchan_matrix = QDF_ARRAY_SIZE(ht20_chan); 765 break; 766 } 767 768 for (i = 0; i < nchan_matrix; i++) { 769 /* find the SAP channel to map the leakage matrix */ 770 if (NOL_channel == pchan_matrix[i].channel) { 771 target_chan_matrix = pchan_matrix[i].chan_matrix; 772 break; 773 } 774 } 775 776 if (NULL == target_chan_matrix) { 777 return false; 778 } else { 779 *pTarget_chnl_mtrx = target_chan_matrix; 780 return true; 781 } 782 } 783 784 QDF_STATUS 785 dfs_mark_leaking_ch(struct wlan_dfs *dfs, 786 enum phy_ch_width ch_width, 787 uint8_t temp_ch_lst_sz, 788 uint8_t *temp_ch_lst) 789 { 790 struct dfs_tx_leak_info *target_chan_matrix = NULL; 791 uint32_t num_channel = (CHAN_ENUM_144 - CHAN_ENUM_36) + 1; 792 uint32_t j = 0; 793 uint32_t k = 0; 794 uint8_t dfs_nol_channel; 795 struct dfs_nolelem *nol; 796 797 nol = dfs->dfs_nol; 798 while (nol) { 799 dfs_nol_channel = wlan_freq_to_chan(nol->nol_freq); 800 if (false == dfs_find_target_channel_in_channel_matrix( 801 ch_width, dfs_nol_channel, 802 &target_chan_matrix)) { 803 /* 804 * should never happen, we should always find a table 805 * here, if we don't, need a fix here! 806 */ 807 dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 808 "Couldn't find target channel matrix!"); 809 QDF_ASSERT(0); 810 return QDF_STATUS_E_FAILURE; 811 } 812 /* 813 * following is based on assumption that both temp_ch_lst 814 * and target channel matrix are in increasing order of 815 * ch_id 816 */ 817 for (j = 0, k = 0; j < temp_ch_lst_sz && k < num_channel;) { 818 if (temp_ch_lst[j] == 0) { 819 j++; 820 continue; 821 } 822 if (target_chan_matrix[k].leak_chan != temp_ch_lst[j]) { 823 k++; 824 continue; 825 } 826 /* 827 * check leakage from candidate channel 828 * to NOL channel 829 */ 830 if (target_chan_matrix[k].leak_lvl <= 831 dfs->tx_leakage_threshold) { 832 /* 833 * candidate channel will have 834 * bad leakage in NOL channel, 835 * remove from temp list 836 */ 837 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 838 "dfs: channel: %d will have bad leakage due to channel: %d\n", 839 dfs_nol_channel, temp_ch_lst[j]); 840 temp_ch_lst[j] = 0; 841 } 842 j++; 843 k++; 844 } 845 nol = nol->nol_next; 846 } /* end of loop that selects each NOL */ 847 848 return QDF_STATUS_SUCCESS; 849 } 850 #else 851 QDF_STATUS 852 dfs_mark_leaking_ch(struct wlan_dfs *dfs, 853 enum phy_ch_width ch_width, 854 uint8_t temp_ch_lst_sz, 855 uint8_t *temp_ch_lst) 856 { 857 return QDF_STATUS_SUCCESS; 858 } 859 #endif 860 861 /** 862 * dfs_populate_80mhz_available_channels()- Populate channels for 80MHz using 863 * bitmap 864 * @dfs: Pointer to DFS structure. 865 * @bitmap: bitmap 866 * @avail_chnl: prepared channel list 867 * 868 * Prepare 80MHz channels from the bitmap. 869 * 870 * Return: channel count 871 */ 872 static uint8_t dfs_populate_80mhz_available_channels( 873 struct wlan_dfs *dfs, 874 struct chan_bonding_bitmap *bitmap, 875 uint8_t *avail_chnl) 876 { 877 uint8_t i = 0; 878 uint8_t chnl_count = 0; 879 uint8_t start_chan = 0; 880 881 for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { 882 start_chan = bitmap->chan_bonding_set[i].start_chan; 883 if (bitmap->chan_bonding_set[i].chan_map == 884 DFS_80MHZ_MASK) { 885 avail_chnl[chnl_count++] = start_chan + 886 (DFS_NEXT_5GHZ_CHANNEL * 0); 887 avail_chnl[chnl_count++] = start_chan + 888 (DFS_NEXT_5GHZ_CHANNEL * 1); 889 avail_chnl[chnl_count++] = start_chan + 890 (DFS_NEXT_5GHZ_CHANNEL * 2); 891 avail_chnl[chnl_count++] = start_chan + 892 (DFS_NEXT_5GHZ_CHANNEL * 3); 893 } 894 } 895 896 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 897 "channel count %d", chnl_count); 898 899 return chnl_count; 900 } 901 902 /** 903 * dfs_populate_40mhz_available_channels()- Populate channels for 40MHz using 904 * bitmap 905 * @dfs: Pointer to DFS structure. 906 * @bitmap: bitmap 907 * @avail_chnl: prepared channel list 908 * 909 * Prepare 40MHz channels from the bitmap. 910 * 911 * Return: channel count 912 */ 913 static uint8_t dfs_populate_40mhz_available_channels( 914 struct wlan_dfs *dfs, 915 struct chan_bonding_bitmap *bitmap, 916 uint8_t *avail_chnl) 917 { 918 uint8_t i = 0; 919 uint8_t chnl_count = 0; 920 uint8_t start_chan = 0; 921 922 for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { 923 start_chan = bitmap->chan_bonding_set[i].start_chan; 924 if ((bitmap->chan_bonding_set[i].chan_map & 925 DFS_40MHZ_MASK_L) == DFS_40MHZ_MASK_L) { 926 avail_chnl[chnl_count++] = start_chan + 927 (DFS_NEXT_5GHZ_CHANNEL * 0); 928 avail_chnl[chnl_count++] = start_chan + 929 (DFS_NEXT_5GHZ_CHANNEL * 1); 930 } 931 if ((bitmap->chan_bonding_set[i].chan_map & 932 DFS_40MHZ_MASK_H) == DFS_40MHZ_MASK_H) { 933 avail_chnl[chnl_count++] = start_chan + 934 (DFS_NEXT_5GHZ_CHANNEL * 2); 935 avail_chnl[chnl_count++] = start_chan + 936 (DFS_NEXT_5GHZ_CHANNEL * 3); 937 } 938 } 939 940 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 941 "channel count %d", chnl_count); 942 943 return chnl_count; 944 } 945 946 /** 947 * dfs_populate_available_channels()- Populate channels based on width and 948 * bitmap 949 * @dfs: Pointer to DFS structure. 950 * @bitmap: bitmap 951 * @ch_width: channel width 952 * @avail_chnl: prepared channel list 953 * 954 * Prepare channel list based on width and channel bitmap. 955 * 956 * Return: channel count 957 */ 958 static uint8_t dfs_populate_available_channels( 959 struct wlan_dfs *dfs, 960 struct chan_bonding_bitmap *bitmap, 961 uint8_t ch_width, 962 uint8_t *avail_chnl) 963 { 964 switch (ch_width) { 965 case DFS_CH_WIDTH_160MHZ: 966 case DFS_CH_WIDTH_80P80MHZ: 967 case DFS_CH_WIDTH_80MHZ: 968 return dfs_populate_80mhz_available_channels( 969 dfs, bitmap, avail_chnl); 970 case DFS_CH_WIDTH_40MHZ: 971 return dfs_populate_40mhz_available_channels( 972 dfs, bitmap, avail_chnl); 973 default: 974 dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 975 "Invalid ch_width %d", ch_width); 976 break; 977 } 978 979 return 0; 980 } 981 982 /** 983 * dfs_get_rand_from_lst()- Get random channel from a given channel list 984 * @dfs: Pointer to DFS structure. 985 * @ch_lst: channel list 986 * @num_ch: number of channels 987 * 988 * Get random channel from given channel list. 989 * 990 * Return: channel number 991 */ 992 static uint8_t dfs_get_rand_from_lst( 993 struct wlan_dfs *dfs, 994 uint8_t *ch_lst, 995 uint8_t num_ch) 996 { 997 uint8_t i; 998 uint32_t rand_byte = 0; 999 1000 if (!num_ch || !ch_lst) { 1001 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 1002 "invalid param ch_lst %pK, num_ch = %d", 1003 ch_lst, num_ch); 1004 return 0; 1005 } 1006 1007 get_random_bytes((uint8_t *)&rand_byte, 1); 1008 i = (rand_byte + qdf_mc_timer_get_system_ticks()) % num_ch; 1009 1010 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1011 "random channel %d", ch_lst[i]); 1012 1013 return ch_lst[i]; 1014 } 1015 1016 /** 1017 * dfs_random_channel_sel_set_bitmap()- Set channel bit in bitmap based 1018 * on given channel number 1019 * @dfs: Pointer to DFS structure. 1020 * @bitmap: bitmap 1021 * @channel: channel number 1022 * 1023 * Set channel bit in bitmap based on given channel number. 1024 * 1025 * Return: None 1026 */ 1027 static void dfs_random_channel_sel_set_bitmap( 1028 struct wlan_dfs *dfs, 1029 struct chan_bonding_bitmap *bitmap, 1030 uint8_t channel) 1031 { 1032 int i = 0; 1033 int start_chan = 0; 1034 1035 for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { 1036 start_chan = bitmap->chan_bonding_set[i].start_chan; 1037 if (channel >= start_chan && channel <= start_chan + 12) { 1038 bitmap->chan_bonding_set[i].chan_map |= 1039 (1 << ((channel - start_chan) / 1040 DFS_80_NUM_SUB_CHANNNEL)); 1041 return; 1042 } 1043 } 1044 1045 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1046 "Channel=%d is not in the bitmap", channel); 1047 } 1048 1049 /** 1050 * dfs_find_ch_with_fallback()- find random channel 1051 * @dfs: Pointer to DFS structure. 1052 * @ch_wd: channel width 1053 * @center_freq_seg1: center frequency of secondary segment. 1054 * @ch_lst: list of available channels. 1055 * @num_ch: number of channels in the list. 1056 * 1057 * Find random channel based on given channel width and channel list, 1058 * fallback to lower width if requested channel width not available. 1059 * 1060 * Return: channel number 1061 */ 1062 static uint8_t dfs_find_ch_with_fallback( 1063 struct wlan_dfs *dfs, 1064 uint8_t *ch_wd, 1065 uint8_t *center_freq_seg1, 1066 uint8_t *ch_lst, 1067 uint32_t num_ch) 1068 { 1069 bool flag = false; 1070 uint32_t rand_byte = 0; 1071 struct chan_bonding_bitmap ch_map = { { {0} } }; 1072 uint8_t count = 0, i, index = 0, final_cnt = 0, target_channel = 0; 1073 uint8_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_160_start_ch = 0; 1074 uint8_t final_lst[DFS_MAX_NUM_CHAN] = {0}; 1075 1076 /* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */ 1077 ch_map.chan_bonding_set[0].start_chan = 36; 1078 ch_map.chan_bonding_set[1].start_chan = 52; 1079 ch_map.chan_bonding_set[2].start_chan = 100; 1080 ch_map.chan_bonding_set[3].start_chan = 116; 1081 ch_map.chan_bonding_set[4].start_chan = 132; 1082 ch_map.chan_bonding_set[5].start_chan = 149; 1083 1084 for (i = 0; i < num_ch; i++) { 1085 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1086 "channel = %d added to bitmap", ch_lst[i]); 1087 dfs_random_channel_sel_set_bitmap(dfs, &ch_map, ch_lst[i]); 1088 } 1089 1090 /* populate available channel list from bitmap */ 1091 final_cnt = dfs_populate_available_channels(dfs, &ch_map, 1092 *ch_wd, final_lst); 1093 1094 /* If no valid ch bonding found, fallback */ 1095 if (final_cnt == 0) { 1096 if ((*ch_wd == DFS_CH_WIDTH_160MHZ) || 1097 (*ch_wd == DFS_CH_WIDTH_80P80MHZ) || 1098 (*ch_wd == DFS_CH_WIDTH_80MHZ)) { 1099 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1100 "from [%d] to 40Mhz", *ch_wd); 1101 *ch_wd = DFS_CH_WIDTH_40MHZ; 1102 } else if (*ch_wd == DFS_CH_WIDTH_40MHZ) { 1103 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1104 "from 40Mhz to 20MHz"); 1105 *ch_wd = DFS_CH_WIDTH_20MHZ; 1106 } 1107 return 0; 1108 } 1109 1110 /* ch count should be > 8 to switch new channel in 160Mhz band */ 1111 if (((*ch_wd == DFS_CH_WIDTH_160MHZ) || 1112 (*ch_wd == DFS_CH_WIDTH_80P80MHZ)) && 1113 (final_cnt < DFS_MAX_20M_SUB_CH)) { 1114 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1115 "from [%d] to 80Mhz", *ch_wd); 1116 *ch_wd = DFS_CH_WIDTH_80MHZ; 1117 return 0; 1118 } 1119 1120 if (*ch_wd == DFS_CH_WIDTH_160MHZ) { 1121 /* 1122 * Only 2 blocks for 160Mhz bandwidth i.e 36-64 & 100-128 1123 * and all the channels in these blocks are continuous 1124 * and seperated by 4Mhz. 1125 */ 1126 for (i = 1; ((i < final_cnt)); i++) { 1127 if ((final_lst[i] - final_lst[i-1]) == 1128 DFS_NEXT_5GHZ_CHANNEL) 1129 count++; 1130 else 1131 count = 0; 1132 if (count == DFS_MAX_20M_SUB_CH - 1) { 1133 flag = true; 1134 new_160_start_ch = final_lst[i - count]; 1135 break; 1136 } 1137 } 1138 } else if (*ch_wd == DFS_CH_WIDTH_80P80MHZ) { 1139 flag = true; 1140 } 1141 1142 if ((flag == false) && (*ch_wd > DFS_CH_WIDTH_80MHZ)) { 1143 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1144 "from [%d] to 80Mhz", *ch_wd); 1145 *ch_wd = DFS_CH_WIDTH_80MHZ; 1146 return 0; 1147 } 1148 1149 if (*ch_wd == DFS_CH_WIDTH_160MHZ) { 1150 get_random_bytes((uint8_t *)&rand_byte, 1); 1151 rand_byte = (rand_byte + qdf_mc_timer_get_system_ticks()) 1152 % DFS_MAX_20M_SUB_CH; 1153 target_channel = new_160_start_ch + (rand_byte * 1154 DFS_80_NUM_SUB_CHANNNEL); 1155 } else if (*ch_wd == DFS_CH_WIDTH_80P80MHZ) { 1156 get_random_bytes((uint8_t *)&rand_byte, 1); 1157 index = (rand_byte + qdf_mc_timer_get_system_ticks()) % 1158 final_cnt; 1159 target_channel = final_lst[index]; 1160 index -= (index % DFS_80_NUM_SUB_CHANNNEL); 1161 primary_seg_start_ch = final_lst[index]; 1162 1163 /* reset channels associate with primary 80Mhz */ 1164 for (i = 0; i < DFS_80_NUM_SUB_CHANNNEL; i++) 1165 final_lst[i + index] = 0; 1166 /* select and calculate center freq for secondary segement */ 1167 for (i = 0; i < final_cnt / DFS_80_NUM_SUB_CHANNNEL; i++) { 1168 if (final_lst[i * DFS_80_NUM_SUB_CHANNNEL] && 1169 (abs(primary_seg_start_ch - 1170 final_lst[i * DFS_80_NUM_SUB_CHANNNEL]) > 1171 (DFS_MAX_20M_SUB_CH * 2))) { 1172 sec_seg_ch = 1173 final_lst[i * DFS_80_NUM_SUB_CHANNNEL] + 1174 DFS_80MHZ_START_CENTER_CH_DIFF; 1175 break; 1176 } 1177 } 1178 1179 if (!sec_seg_ch && (final_cnt == DFS_MAX_20M_SUB_CH)) 1180 *ch_wd = DFS_CH_WIDTH_160MHZ; 1181 else if (!sec_seg_ch) 1182 *ch_wd = DFS_CH_WIDTH_80MHZ; 1183 1184 *center_freq_seg1 = sec_seg_ch; 1185 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1186 "Center frequency seg1 = %d", sec_seg_ch); 1187 } else { 1188 target_channel = dfs_get_rand_from_lst(dfs, 1189 final_lst, final_cnt); 1190 } 1191 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1192 "target channel = %d", target_channel); 1193 1194 return target_channel; 1195 } 1196 1197 /** 1198 * dfs_remove_cur_ch_from_list()- remove current operating channels 1199 * @ch_list: list of avilable channel list 1200 * @ch_cnt: number of channels. 1201 * @ch_wd: channel width. 1202 * @cur_chan: current channel. 1203 * 1204 * Remove current channels from list of available channels. 1205 * 1206 * Return: channel number 1207 */ 1208 static void dfs_remove_cur_ch_from_list( 1209 struct dfs_channel *ch_list, 1210 uint32_t *ch_cnt, 1211 uint8_t *ch_wd, 1212 struct dfs_channel *cur_chan) 1213 { 1214 /* TODO */ 1215 return; 1216 } 1217 1218 /** 1219 * dfs_freq_is_in_nol()- check if given channel in nol list 1220 * @dfs: dfs handler 1221 * @freq: channel frequency. 1222 * 1223 * check if given channel in nol list. 1224 * 1225 * Return: true if channel in nol, false else 1226 */ 1227 static bool dfs_freq_is_in_nol(struct wlan_dfs *dfs, uint32_t freq) 1228 { 1229 struct dfs_nolelem *nol; 1230 1231 if (!dfs) { 1232 dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "null dfs"); 1233 return false; 1234 } 1235 1236 nol = dfs->dfs_nol; 1237 while (nol) { 1238 if (freq == nol->nol_freq) { 1239 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1240 "%d is in nol", freq); 1241 return true; 1242 } 1243 nol = nol->nol_next; 1244 } 1245 1246 return false; 1247 } 1248 1249 /** 1250 * dfs_apply_rules()- prepare channel list based on flags 1251 * @dfs: dfs handler 1252 * @flags: channel flags 1253 * @random_chan_list: ouput channel list 1254 * @random_chan_cnt: output channel count 1255 * @ch_list: input channel list 1256 * @ch_cnt: input channel count 1257 * @dfs_region: dfs region 1258 * @acs_info: acs channel range information 1259 * 1260 * prepare channel list based on flags 1261 * 1262 * Return: None 1263 */ 1264 static void dfs_apply_rules(struct wlan_dfs *dfs, 1265 uint32_t flags, 1266 uint8_t *random_chan_list, 1267 uint32_t *random_chan_cnt, 1268 struct dfs_channel *ch_list, 1269 uint32_t ch_cnt, 1270 uint8_t dfs_region, 1271 struct dfs_acs_info *acs_info) 1272 { 1273 struct dfs_channel *chan; 1274 uint16_t flag_no_weather = 0; 1275 uint16_t flag_no_lower_5g = 0; 1276 uint16_t flag_no_upper_5g = 0; 1277 uint16_t flag_no_dfs_chan = 0; 1278 uint16_t flag_no_2g_chan = 0; 1279 uint16_t flag_no_5g_chan = 0; 1280 int i; 1281 1282 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "flags %d", flags); 1283 flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ? 1284 flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0; 1285 1286 flag_no_lower_5g = (dfs_region == DFS_MKK_REGION_VAL) ? 1287 flags & DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH : 0; 1288 1289 flag_no_upper_5g = (dfs_region == DFS_MKK_REGION_VAL) ? 1290 flags & DFS_RANDOM_CH_FLAG_NO_UPEER_5G_CH : 0; 1291 1292 flag_no_dfs_chan = flags & DFS_RANDOM_CH_FLAG_NO_DFS_CH; 1293 flag_no_2g_chan = flags & DFS_RANDOM_CH_FLAG_NO_2GHZ_CH; 1294 flag_no_5g_chan = flags & DFS_RANDOM_CH_FLAG_NO_5GHZ_CH; 1295 1296 for (i = 0; i < ch_cnt; i++) { 1297 chan = &ch_list[i]; 1298 1299 if ((chan->dfs_ch_ieee == 0) || 1300 (chan->dfs_ch_ieee > MAX_CHANNEL_NUM)) { 1301 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1302 "invalid channel %d", 1303 chan->dfs_ch_ieee); 1304 continue; 1305 } 1306 1307 if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) { 1308 /* TODO : Skip all HT20 channels in the given mode */ 1309 if (chan->dfs_ch_ieee == 1310 dfs->dfs_curchan->dfs_ch_ieee) { 1311 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1312 "skip %d current operating channel\n", 1313 chan->dfs_ch_ieee); 1314 continue; 1315 } 1316 } 1317 1318 if (acs_info && (acs_info->acs_mode == 1) && 1319 ((chan->dfs_ch_ieee < acs_info->start_ch) || 1320 (chan->dfs_ch_ieee > acs_info->end_ch))) { 1321 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1322 "skip ch %d not in acs range (%d-%d)", 1323 chan->dfs_ch_ieee, acs_info->start_ch, 1324 acs_info->end_ch); 1325 continue; 1326 1327 } 1328 1329 if (flag_no_2g_chan && 1330 chan->dfs_ch_ieee <= DFS_MAX_24GHZ_CHANNEL) { 1331 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1332 "skip 2.4 GHz channel=%d", 1333 chan->dfs_ch_ieee); 1334 continue; 1335 } 1336 1337 if (flag_no_5g_chan && 1338 chan->dfs_ch_ieee > DFS_MAX_24GHZ_CHANNEL) { 1339 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1340 "skip 5 GHz channel=%d", 1341 chan->dfs_ch_ieee); 1342 continue; 1343 } 1344 1345 if (flag_no_weather) { 1346 if (DFS_IS_CHANNEL_WEATHER_RADAR(chan->dfs_ch_freq)) { 1347 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1348 "skip weather channel=%d", 1349 chan->dfs_ch_ieee); 1350 continue; 1351 } 1352 } 1353 1354 if (flag_no_lower_5g && 1355 DFS_IS_CHAN_JAPAN_INDOOR(chan->dfs_ch_ieee)) { 1356 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1357 "skip indoor channel=%d", 1358 chan->dfs_ch_ieee); 1359 continue; 1360 } 1361 1362 if (flag_no_upper_5g && 1363 DFS_IS_CHAN_JAPAN_OUTDOOR(chan->dfs_ch_ieee)) { 1364 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1365 "skip outdoor channel=%d", 1366 chan->dfs_ch_ieee); 1367 continue; 1368 } 1369 1370 if (flag_no_dfs_chan && 1371 (chan->dfs_ch_flagext & WLAN_CHAN_DFS)) { 1372 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1373 "skip dfs channel=%d", 1374 chan->dfs_ch_ieee); 1375 continue; 1376 } 1377 1378 if (dfs_freq_is_in_nol(dfs, chan->dfs_ch_freq)) { 1379 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1380 "skip nol channel=%d", 1381 chan->dfs_ch_ieee); 1382 continue; 1383 } 1384 1385 random_chan_list[*random_chan_cnt] = chan->dfs_ch_ieee; 1386 *random_chan_cnt += 1; 1387 } 1388 } 1389 1390 uint8_t dfs_prepare_random_channel(struct wlan_dfs *dfs, 1391 struct dfs_channel *ch_list, 1392 uint32_t ch_cnt, 1393 uint32_t flags, 1394 uint8_t *ch_wd, 1395 struct dfs_channel *cur_chan, 1396 uint8_t dfs_region, 1397 struct dfs_acs_info *acs_info) 1398 { 1399 int i = 0; 1400 uint8_t final_cnt = 0; 1401 uint8_t target_ch = 0; 1402 uint8_t *random_chan_list = NULL; 1403 uint32_t random_chan_cnt = 0; 1404 uint16_t flag_no_weather = 0; 1405 uint8_t *leakage_adjusted_lst; 1406 uint8_t final_lst[NUM_CHANNELS] = {0}; 1407 1408 if (!ch_list || !ch_cnt) { 1409 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1410 "Invalid params %pK, ch_cnt=%d", 1411 ch_list, ch_cnt); 1412 return 0; 1413 } 1414 1415 if (*ch_wd < DFS_CH_WIDTH_20MHZ || *ch_wd > DFS_CH_WIDTH_80P80MHZ) { 1416 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1417 "Invalid ch_wd %d", *ch_wd); 1418 return 0; 1419 } 1420 1421 random_chan_list = qdf_mem_malloc(ch_cnt * sizeof(*random_chan_list)); 1422 if (!random_chan_list) { 1423 dfs_alert(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1424 "Memory allocation failed"); 1425 return 0; 1426 } 1427 1428 if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) 1429 dfs_remove_cur_ch_from_list(ch_list, &ch_cnt, ch_wd, cur_chan); 1430 1431 dfs_apply_rules(dfs, flags, random_chan_list, &random_chan_cnt, 1432 ch_list, ch_cnt, dfs_region, acs_info); 1433 1434 flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ? 1435 flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0; 1436 1437 /* list adjusted after leakage has been marked */ 1438 leakage_adjusted_lst = qdf_mem_malloc(random_chan_cnt); 1439 if (!leakage_adjusted_lst) { 1440 dfs_alert(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1441 "Memory allocation failed"); 1442 qdf_mem_free(random_chan_list); 1443 return 0; 1444 } 1445 1446 do { 1447 qdf_mem_copy(leakage_adjusted_lst, random_chan_list, 1448 random_chan_cnt); 1449 if (QDF_IS_STATUS_ERROR(dfs_mark_leaking_ch(dfs, *ch_wd, 1450 random_chan_cnt, 1451 leakage_adjusted_lst))) { 1452 qdf_mem_free(random_chan_list); 1453 qdf_mem_free(leakage_adjusted_lst); 1454 return 0; 1455 } 1456 1457 if (*ch_wd == DFS_CH_WIDTH_20MHZ) { 1458 /* 1459 * PASS: 3 - from leakage_adjusted_lst, prepare valid 1460 * ch list and use random number from that 1461 */ 1462 for (i = 0; i < random_chan_cnt; i++) { 1463 if (leakage_adjusted_lst[i] == 0) 1464 continue; 1465 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1466 "dfs: Channel=%d added to available list", 1467 leakage_adjusted_lst[i]); 1468 final_lst[final_cnt] = leakage_adjusted_lst[i]; 1469 final_cnt++; 1470 } 1471 target_ch = dfs_get_rand_from_lst( 1472 dfs, final_lst, final_cnt); 1473 break; 1474 } 1475 1476 target_ch = dfs_find_ch_with_fallback(dfs, ch_wd, 1477 &cur_chan->dfs_ch_vhtop_ch_freq_seg2, 1478 leakage_adjusted_lst, 1479 random_chan_cnt); 1480 1481 /* 1482 * When flag_no_weather is set, avoid usage of Adjacent 1483 * weather radar channel in HT40 mode as extension channel 1484 * will be on 5600. 1485 */ 1486 if (flag_no_weather && 1487 (target_ch == 1488 DFS_ADJACENT_WEATHER_RADAR_CHANNEL_NUM) && 1489 (*ch_wd == DFS_CH_WIDTH_40MHZ)) { 1490 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1491 "skip weather adjacent ch=%d\n", 1492 target_ch); 1493 continue; 1494 } 1495 1496 if (target_ch) 1497 break; 1498 } while (true); 1499 1500 qdf_mem_free(random_chan_list); 1501 qdf_mem_free(leakage_adjusted_lst); 1502 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "target_ch = %d", target_ch); 1503 1504 return target_ch; 1505 } 1506