1 /* 2 * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "../dfs.h" 20 #include "../dfs_random_chan_sel.h" 21 #include <qdf_mc_timer.h> 22 #include <wlan_utility.h> 23 24 #ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION 25 /* 26 * TODO: At present SAP Channel leakage matrix for ch 144 27 * is not available from system's team. So to play it safe 28 * and avoid crash if channel 144 is request, in following 29 * matix channel 144 is added such that it will cause code 30 * to avoid selecting channel 144. 31 * 32 * THESE ENTRIES SHOULD BE REPLACED WITH CORRECT VALUES AS 33 * PROVIDED BY SYSTEM'S TEAM. 34 */ 35 36 /* channel tx leakage table - ht80 */ 37 struct dfs_matrix_tx_leak_info ht80_chan[] = { 38 {52, 5260, 39 {{36, 5180, 148}, {40, 5200, 199}, 40 {44, 5520, 193}, {48, 5240, 197}, 41 {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, 153}, 42 {60, 5300, 137}, {64, 5320, 134}, 43 {100, 5500, 358}, {104, 5520, 350}, 44 {108, 5540, 404}, {112, 5560, 344}, 45 {116, 5580, 424}, {120, 5600, 429}, 46 {124, 5620, 437}, {128, 5640, 435}, 47 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 48 {140, 5700, DFS_TX_LEAKAGE_MAX}, 49 {144, 5720, DFS_TX_LEAKAGE_MIN} 50 } }, 51 52 53 {56, 5280, 54 {{36, 5180, 171}, {40, 5200, 178}, 55 {44, 5220, 171}, {48, 5240, 178}, 56 {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, 57 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, 280}, 58 {100, 5500, 351}, {104, 5520, 376}, 59 {108, 5540, 362}, {112, 5560, 362}, 60 {116, 5580, 403}, {120, 5600, 397}, 61 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 62 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 63 {140, 5700, DFS_TX_LEAKAGE_MAX}, 64 {144, 5720, DFS_TX_LEAKAGE_MIN} 65 } }, 66 67 {60,5300, 68 {{36, 5180, 156}, {40, 5200, 146}, 69 {44, 5220, DFS_TX_LEAKAGE_MIN}, {48, 5240, DFS_TX_LEAKAGE_MIN}, 70 {52, 5260, 180}, {56, 5280, DFS_TX_LEAKAGE_MIN}, 71 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 72 {100, 5500, 376}, {104, 5520, 360}, 73 {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, 74 {116, 5580, 395}, {120, 5600, 399}, 75 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 76 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 77 {140, 5700, DFS_TX_LEAKAGE_MAX}, 78 {144, 5720, DFS_TX_LEAKAGE_MIN} 79 } }, 80 81 {64, 5320, 82 {{36, 5180, 217}, {40, 5200, 221}, 83 {44, 5220, DFS_TX_LEAKAGE_MIN}, {48, 5240, DFS_TX_LEAKAGE_MIN}, 84 {52, 5260, 176}, {56, 5280, 176}, 85 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 86 {100, 5500, 384}, {104, 5520, 390}, 87 {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, 88 {116, 5580, 375}, {120, 5600, 374}, 89 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 90 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 91 {140, 5700, DFS_TX_LEAKAGE_MAX}, 92 {144, 5720, DFS_TX_LEAKAGE_MIN} 93 } }, 94 95 {100, 5500, 96 {{36, 5180, 357}, {40, 5200, 326}, 97 {44, 5220, 321}, {48, 5240, 326}, 98 {52, 5260, 378}, {56, 5280, 396}, 99 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 100 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 101 {108, 5540, 196}, {112, 5560, 116}, 102 {116, 5580, 166}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 103 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 104 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 105 {140, 5700, DFS_TX_LEAKAGE_MIN}, 106 {144, 5720, DFS_TX_LEAKAGE_MIN} 107 } }, 108 109 {104, 5520, 110 {{36, 5180, 325}, {40, 5200, 325}, 111 {44, 5220, 305}, {48, 5240, 352}, 112 {52, 5260, 411}, {56, 5280, 411}, 113 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 114 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 115 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, 460}, 116 {116, 5580, 198}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 117 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 118 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 119 {140, 5700, DFS_TX_LEAKAGE_MIN}, 120 {144, 5720, DFS_TX_LEAKAGE_MIN} 121 } }, 122 123 {108, 5540, 124 {{36,5180, 304}, {40, 5200, 332}, 125 {44, 5220, 310}, {48, 5240, 335}, 126 {52, 5260, 431}, {56, 5280, 391}, 127 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 128 {100, 5500, 280}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 129 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 130 {116, 5580, 185}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 131 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 132 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 133 {140, 5700, DFS_TX_LEAKAGE_MIN}, 134 {144, 5720, DFS_TX_LEAKAGE_MIN} 135 } }, 136 137 {112,5560, 138 {{36, 5180, 327}, {40, 5200, 335}, 139 {44, 5220, 331}, {48, 5240, 345}, 140 {52, 5260, 367}, {56, 5280, 401}, 141 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 142 {100, 5500, 131}, {104, 5520, 132}, 143 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 144 {116, 5580, 189}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 145 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 146 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 147 {140, 5700, DFS_TX_LEAKAGE_MIN}, 148 {144, 5720, DFS_TX_LEAKAGE_MIN} 149 } }, 150 151 {116, 5580, 152 {{36, 5180, 384}, {40, 5200, 372}, 153 {44, 5220, 389}, {48, 5240, 396}, 154 {52, 5260, 348}, {56, 5280, 336}, 155 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 156 {100, 5500, 172}, {104, 5520, 169}, 157 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 158 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 159 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 160 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 161 {140, 5700, DFS_TX_LEAKAGE_MIN}, 162 {144, 5720, DFS_TX_LEAKAGE_MIN} 163 } }, 164 165 {120, 5600, 166 {{36, 5180, 395}, {40, 5200, 419}, 167 {44, 5220, 439}, {48, 5240, 407}, 168 {52, 5260, 321}, {56, 5280, 334}, 169 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 170 {100, 5500, 134}, {104, 5520, 186}, 171 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 172 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 173 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 159}, 174 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 175 {140, 5700, DFS_TX_LEAKAGE_MIN}, 176 {144, 5720, DFS_TX_LEAKAGE_MIN} 177 } }, 178 179 {124, 5620, 180 {{36, 5180, 469}, {40, 5200, 433}, 181 {44, 5220, 434}, {48, 5240, 435}, 182 {52, 5260, 332}, {56, 5280, 345}, 183 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 184 {100, 5500, 146}, {104, 5520, 177}, 185 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 186 {116, 5580, 350}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 187 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 138}, 188 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 189 {140, 5700, DFS_TX_LEAKAGE_MIN}, 190 {144, 5720, DFS_TX_LEAKAGE_MIN} 191 } }, 192 193 {128, 5640, 194 {{36, 5180, 408}, {40, 5200, 434}, 195 {44, 5220, 449}, {48, 5240, 444}, 196 {52, 5260, 341}, {56, 5280, 374}, 197 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 198 {100, 5500, 205}, {104, 5520, 208}, 199 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 200 {116, 5580, 142}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 201 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 202 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 203 {140, 5700, DFS_TX_LEAKAGE_MIN}, 204 {144, 5720, DFS_TX_LEAKAGE_MIN} 205 } }, 206 207 {132, 5660, 208 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX}, 209 {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX}, 210 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 211 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 212 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 213 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 214 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 215 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 216 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 217 {140, 5700, DFS_TX_LEAKAGE_MIN}, 218 {144, 5720, DFS_TX_LEAKAGE_MIN} 219 } }, 220 221 {136, 5680, 222 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX}, 223 {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX}, 224 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 225 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 226 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 227 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 228 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 229 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 230 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 231 {140, 5700, DFS_TX_LEAKAGE_MIN}, 232 {144, 5720, DFS_TX_LEAKAGE_MIN} 233 } }, 234 235 {140, 5700, 236 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX}, 237 {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX}, 238 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 239 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 240 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 241 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 242 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 243 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 244 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 245 {144, 5720, DFS_TX_LEAKAGE_MIN} 246 } }, 247 248 {144, 5720, 249 {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX}, 250 {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX}, 251 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 252 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 253 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 254 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 255 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 256 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 257 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 258 {144, 5720, DFS_TX_LEAKAGE_MIN} 259 } }, 260 }; 261 262 /* channel tx leakage table - ht40 */ 263 struct dfs_matrix_tx_leak_info ht40_chan[] = { 264 {52, 5260, 265 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, 266 {44, 5220, 230}, {48, 5240, 230}, 267 {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, 268 {60, 5300, DFS_TX_LEAKAGE_AUTO_MIN}, {64, 5320, DFS_TX_LEAKAGE_AUTO_MIN}, 269 {100, 5500, 625}, {104, 5520, 323}, 270 {108, 5540, 646}, {112, 5560, 646}, 271 {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, 272 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 273 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 274 {140, 5700, DFS_TX_LEAKAGE_MAX}, 275 {144, 5720, DFS_TX_LEAKAGE_MIN} 276 } }, 277 278 {56, 5280, 279 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, 280 {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN}, 281 {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, 282 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 283 {100, 5500, 611}, {104, 5520, 611}, 284 {108, 5540, 617}, {112, 5560, 617}, 285 {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, 286 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 287 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 288 {140, 5700, DFS_TX_LEAKAGE_MAX}, 289 {144, 5720, DFS_TX_LEAKAGE_MIN} 290 } }, 291 292 {60, 5300, 293 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, 294 {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN}, 295 {52, 5260, 190}, {56, 5280, 190}, 296 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 297 {100, 5500, 608}, {104, 5520, 608}, 298 {108, 5540, 623}, {112, 5560, 623}, 299 {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, 300 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 301 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 302 {140, 5700, DFS_TX_LEAKAGE_MAX}, 303 {144, 5720, DFS_TX_LEAKAGE_MIN} 304 } }, 305 306 {64, 5320, 307 {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, 308 {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN}, 309 {52, 5260, 295}, {56, 5280, 295}, 310 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 311 {100, 5500, 594}, {104, 5520, 594}, 312 {108, 5540, 625}, {112, 5560, 625}, 313 {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, 314 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 315 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 316 {140, 5700, DFS_TX_LEAKAGE_MAX}, 317 {144, 5720, DFS_TX_LEAKAGE_MIN} 318 } }, 319 320 {100, 5500, 321 {{36, 5180, 618}, {40, 5200, 618}, 322 {44, 5220, 604}, {48, 5240, 604}, 323 {52, 5260, 596}, {56, 5280, 596}, 324 {60, 5300, 584}, {64, 5320, 584}, 325 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 326 {108, 5540, 299}, {112, 5560, 299}, 327 {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, 328 {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, 329 {132, 5660, 538}, {136,5680, 538}, 330 {140, 5700, 598}, 331 {144, 5720, DFS_TX_LEAKAGE_MIN} 332 } }, 333 334 {104, 5520, 335 {{36, 5180, 636}, {40, 5200, 636}, 336 {44, 5220, 601}, {48, 5240, 601}, 337 {52, 5260, 616}, {56, 5280, 616}, 338 {60, 5300, 584}, {64, 5320, 584}, 339 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 340 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 341 {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, 342 {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, 343 {132, 5660, 553}, {136, 5680, 553}, 344 {140, 5700, 568}, 345 {144, 5720, DFS_TX_LEAKAGE_MIN} 346 } }, 347 348 {108, 5540, 349 {{36, 5180, 600}, {40, 5200, 600}, 350 {44, 5220, 627}, {48, 5240, 627}, 351 {52, 5260, 611}, {56, 5280, 611}, 352 {60, 5300, 611}, {64, 5320, 611}, 353 {100, 5500, 214}, {104, 5520, 214}, 354 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 355 {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, 356 {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, 357 {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, 358 {140, 5700, 534}, 359 {144, 5720, DFS_TX_LEAKAGE_MIN} 360 } }, 361 362 {112, 5560, 363 {{36, 5180, 645}, {40, 5200, 645}, 364 {44, 5220, 641}, {48, 5240, 641}, 365 {52, 5260, 618}, {56, 5280, 618}, 366 {60, 5300, 612}, {64, 5320, 612}, 367 {100, 5500, 293}, {104, 5520, 293}, 368 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 369 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 370 {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, 371 {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, 372 {140, 5700, 521}, 373 {144, 5720, DFS_TX_LEAKAGE_MIN} 374 } }, 375 376 {116, 5580, 377 {{36, 5180, 661}, {40, 5200, 661}, 378 {44, 5220, 624}, {48, 5240, 624}, 379 {52, 5260, 634}, {56, 5280, 634}, 380 {60, 5300, 611}, {64, 5320, 611}, 381 {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN}, 382 {108, 5540, 217}, {112, 5560, 217}, 383 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 384 {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, 385 {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, 386 {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN}, 387 {144, 5720, DFS_TX_LEAKAGE_MIN} 388 } }, 389 390 {120, 5600, 391 {{36, 5180, 667}, {40, 5200, 667}, 392 {44, 5220, 645}, {48, 5240, 645}, 393 {52, 5260, 633}, {56, 5280, 633}, 394 {60, 5300, 619}, {64, 5320, 619}, 395 {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN}, 396 {108, 5540, 291}, {112, 5560, 291}, 397 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 398 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 399 {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, 400 {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN}, 401 {144, 5720, DFS_TX_LEAKAGE_MIN} 402 } }, 403 404 {124, 5620, 405 {{36, 5180, 676}, {40, 5200, 676}, 406 {44, 5220, 668}, {48, 5240, 668}, 407 {52, 5260, 595}, {56, 5280, 595}, 408 {60, 5300, 622}, {64, 5320, 622}, 409 {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN}, 410 {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, 411 {116, 5580, 225}, {120, 5600, 225}, 412 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 413 {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, 414 {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN}, 415 {144, 5720, DFS_TX_LEAKAGE_MIN} 416 } }, 417 418 {128, 5640, 419 {{36, 5180, 678}, {40, 5200, 678}, 420 {44, 5220, 664}, {48, 5240, 664}, 421 {52, 5260, 651}, {56, 5280, 651}, 422 {60, 5300, 643}, {64, 5320, 643}, 423 {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN}, 424 {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, 425 {116, 5580, 293}, {120, 5600, 293}, 426 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 427 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 428 {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN}, 429 {144, 5720, DFS_TX_LEAKAGE_MIN} 430 } }, 431 432 {132, 5660, 433 {{36, 5180, 689}, {40, 5200, 689}, 434 {44, 5220, 669}, {48, 5240, 669}, 435 {52, 5260, 662}, {56, 5280, 662}, 436 {60, 5300, 609}, {64, 5320, 609}, 437 {100, 5500, 538}, {104, 5520, 538}, 438 {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, 439 {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, 440 {124, 5620, 247}, {128, 5640, 247}, 441 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 442 {140, 5700, DFS_TX_LEAKAGE_MIN}, 443 {144, 5720, DFS_TX_LEAKAGE_MIN} 444 } }, 445 446 {136, 5680, 447 {{36, 5180, 703}, {40, 5200, 703}, 448 {44, 5220, 688}, {48, 5240, DFS_TX_LEAKAGE_MIN}, 449 {52, 5260, 671}, {56, 5280, 671}, 450 {60, 5300, 658}, {64, 5320, 658}, 451 {100, 5500, 504}, {104, 5520, 504}, 452 {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, 453 {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, 454 {124, 5620, 289}, {128, 5640, 289}, 455 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 456 {140, 5700, DFS_TX_LEAKAGE_MIN}, 457 {144, 5720, DFS_TX_LEAKAGE_MIN} 458 } }, 459 460 {140, 5700, 461 {{36, 5180, 695}, {40, 5200, 695}, 462 {44, 5220, 684}, {48, 5240, 684}, 463 {52, 5260, 664}, {56, 5280, 664}, 464 {60, 5300, 658}, {64, 5320, 658}, 465 {100, 5500, 601}, {104, 5520, 601}, 466 {108, 5540, 545}, {112, 5560, 545}, 467 {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, 468 {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, 469 {132, 5660, 262}, {136, 5680, 262}, 470 {140, 5700, DFS_TX_LEAKAGE_MIN}, 471 {144, 5720, DFS_TX_LEAKAGE_MIN} 472 } }, 473 474 {144, 5720, 475 {{36, 5180, 695}, {40, 5200, 695}, 476 {44, 5220, 684}, {48, 5240, 684}, 477 {52, 5260, 664}, {56, 5280, 664}, 478 {60, 5300, 658}, {64, 5320, 658}, 479 {100, 5500, 601}, {104, 5520, 601}, 480 {108, 5540, 545}, {112, 5560, 545}, 481 {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, 482 {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, 483 {132, 5660, 262}, {136, 5680, 262}, 484 {140, 5700, DFS_TX_LEAKAGE_MIN}, 485 {144, 5720, DFS_TX_LEAKAGE_MIN} 486 } }, 487 }; 488 489 /* channel tx leakage table - ht20 */ 490 struct dfs_matrix_tx_leak_info ht20_chan[] = { 491 {52, 5260, 492 {{36, 5180,DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, 286}, 493 {44, 5220, 225}, {48,5240, 121}, 494 {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, 495 {60, 5300, 300}, {64, 5320, DFS_TX_LEAKAGE_AUTO_MIN}, 496 {100, 5500, 637}, {104, 5520, DFS_TX_LEAKAGE_MAX}, 497 {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, 498 {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, 499 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 500 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 501 {140, 5700, DFS_TX_LEAKAGE_MAX}, 502 {144, 5720, DFS_TX_LEAKAGE_MIN} 503 } }, 504 505 {56, 5280, 506 {{36, 5180, 468}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, 507 {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, 206}, 508 {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, 509 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 510 {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, 511 {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, 512 {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, 513 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 514 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 515 {140, 5700, DFS_TX_LEAKAGE_MAX}, 516 {144, 5720, DFS_TX_LEAKAGE_MIN} 517 } }, 518 519 {60, 5300, 520 {{36, 5180, 507}, {40, 5200, 440}, 521 {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48,5240, 313}, 522 {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, 523 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 524 {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, 525 {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, 526 {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, 527 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 528 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 529 {140, 5700, DFS_TX_LEAKAGE_MAX}, 530 {144, 5720, DFS_TX_LEAKAGE_MIN} 531 } }, 532 533 {64, 5320 , 534 {{36, 5180, 516}, {40, 5200, 520}, 535 {44, 5220, 506}, {48, 5240,DFS_TX_LEAKAGE_AUTO_MIN}, 536 {52, 5260, 301}, {56, 5280, 258}, 537 {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, 538 {100, 5500, 620}, {104, 5520, 617}, 539 {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, 540 {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, 541 {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, 542 {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, 543 {140, 5700, DFS_TX_LEAKAGE_MAX}, 544 {144, 5720, DFS_TX_LEAKAGE_MIN} 545 } }, 546 547 {100, 5500, 548 {{36, 5180, 616}, {40, 5200, 601}, 549 {44, 5220, 604}, {48, 5240, 589}, 550 {52, 5260, 612}, {56, 5280, 592}, 551 {60, 5300, 590}, {64, 5320, 582}, 552 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, 131}, 553 {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, 554 {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, 522}, 555 {124, 5620, 571}, {128, 5640, 589}, 556 {132, 5660, 593}, {136, 5680, 598}, 557 {140, 5700, 594}, 558 {144, 5720, DFS_TX_LEAKAGE_MIN}, 559 } }, 560 561 {104, 5520, 562 {{36, 5180, 622}, {40, 5200, 624}, 563 {44, 5220, 618}, {48, 5240, 610}, 564 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 565 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 566 {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 567 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, 463}, 568 {116, 5580, 483}, {120, 5600, 503}, 569 {124, 5620, 523}, {128, 5640, 565}, 570 {132, 5660, 570}, {136, 5680, 588}, 571 {140, 5700, 585}, 572 {144, 5720, DFS_TX_LEAKAGE_MIN}, 573 } }, 574 575 {108, 5540, 576 {{36, 5180, 620}, {40, 5200, 638}, 577 {44, 5220, 611}, {48, 5240, 614}, 578 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 579 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 580 {100, 5500, 477}, {104, 5520, DFS_TX_LEAKAGE_MIN}, 581 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 582 {116, 5580, 477}, {120, 5600, 497}, 583 {124, 5620, 517}, {128, 5640, 537}, 584 {132, 5660, 557}, {136, 5680, 577}, 585 {140, 5700, 603}, 586 {144, 5720, DFS_TX_LEAKAGE_MIN}, 587 } }, 588 589 {112, 5560, 590 {{36, 5180, 636}, {40, 5200, 623}, 591 {44, 5220, 638}, {48, 5240, 628}, 592 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 593 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, 606}, 594 {100, 5500, 501}, {104, 5520, 481}, 595 {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 596 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, 481}, 597 {124, 5620, 501}, {128, 5640, 421}, 598 {132, 5660, 541}, {136, 5680, 561}, 599 {140, 5700, 583}, 600 {144, 5720, DFS_TX_LEAKAGE_MIN}, 601 } }, 602 603 {116, 5580, 604 {{36, 5180, 646}, {40, 5200, 648}, 605 {44, 5220, 633}, {48, 5240, 634}, 606 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 607 {60, 5300, 615}, {64, 5320, 594}, 608 {100, 5500, 575}, {104, 5520, 554}, 609 {108, 5540, 534}, {112, 5560, DFS_TX_LEAKAGE_MIN}, 610 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 611 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 612 {132, 5660, 534}, {136, 5680, 554}, 613 {140, 5700, 574}, 614 {144, 5720, DFS_TX_LEAKAGE_MIN}, 615 } }, 616 617 {120, 5600, 618 {{36, 5180, 643}, {40, 5200, 649}, 619 {44, 5220, 654}, {48, 5240, 629}, 620 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, 621}, 621 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 622 {100, 5500, 565}, {104, 5520, 545}, 623 {108, 5540, 525}, {112, 5560, 505}, 624 {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 625 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 505}, 626 {132, 5660, 525}, {136, 5680, 545}, 627 {140, 5700, 565}, 628 {144, 5720, DFS_TX_LEAKAGE_MIN}, 629 } }, 630 631 {124, 5620, 632 {{36, 5180, 638}, {40, 5200, 657}, 633 {44, 5220, 663}, {48, 5240, 649}, 634 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 635 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 636 {100, 5500, 581}, {104, 5520, 561}, 637 {108, 5540, 541}, {112, 5560, 521}, 638 {116, 5580, 499}, {120, 5600, DFS_TX_LEAKAGE_MIN}, 639 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 640 {132, 5660, 499}, {136, 5680, 519}, 641 {140, 5700, 539}, 642 {144, 5720, DFS_TX_LEAKAGE_MIN} 643 } }, 644 645 {128, 5640, 646 {{36, 5180, 651}, {40, 5200, 651}, 647 {44, 5220, 674}, {48, 5240, 640}, 648 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 649 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 650 {100, 5500, 603}, {104, 5520, 560}, 651 {108, 5540, 540}, {112, 5560, 520}, 652 {116, 5580, 499}, {120, 5600, 479}, 653 {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 654 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, 479}, 655 {140, 5700, 499}, 656 {144, 5720, DFS_TX_LEAKAGE_MIN} 657 } }, 658 659 {132, 5660, 660 {{36, 5180, 643}, {40, 5200, 668}, 661 {44, 5220, 651}, {48, 5240, 657}, 662 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 663 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 664 {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, 602}, 665 {108, 5540, 578}, {112,5560, 570}, 666 {116, 5580, 550}, {120, 5600, 530}, 667 {124, 5620, 510}, {128, 5640, DFS_TX_LEAKAGE_MIN}, 668 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 669 {140, 5700, 490}, 670 {144, 5720, DFS_TX_LEAKAGE_MIN} 671 } }, 672 673 {136,5680, 674 {{36, 5180, 654}, {40, 5200, 667}, 675 {44, 5220, 666}, {48, 5240, 642}, 676 {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, 677 {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, 678 {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, 679 {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 596}, 680 {116, 5580, 555}, {120, 5600, 535}, 681 {124, 5620, 515}, {128, 5640, 495}, 682 {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 683 {140, 5700, DFS_TX_LEAKAGE_MIN}, 684 {144, 5720, DFS_TX_LEAKAGE_MIN} 685 } }, 686 687 {140,5700, 688 {{36, 5180, 679}, {40, 5200, 673}, 689 {44, 5220, 667}, {48, 5240, 656}, 690 {52, 5260, 634}, {56, 5280, 663}, 691 {60, 5300, 662}, {64, 5320, 660}, 692 {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, 693 {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 590}, 694 {116, 5580, 573}, {120, 5600, 553}, 695 {124, 5620, 533}, {128, 5640, 513}, 696 {132, 5660, 490}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 697 {140, 5700, DFS_TX_LEAKAGE_MIN}, 698 {144, 5720, DFS_TX_LEAKAGE_MIN} 699 } }, 700 701 {144,5720, 702 {{36, 5180, 679}, {40, 5200, 673}, 703 {44, 5220, 667}, {48, 5240, 656}, 704 {52, 5260, 634}, {56, 5280, 663}, 705 {60, 5300, 662}, {64, 5320, 660}, 706 {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, 707 {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 590}, 708 {116, 5580, 573}, {120, 5600, 553}, 709 {124, 5620, 533}, {128, 5640, 513}, 710 {132, 5660, 490}, {136, 5680, DFS_TX_LEAKAGE_MIN}, 711 {140, 5700, DFS_TX_LEAKAGE_MIN}, 712 {144, 5720, DFS_TX_LEAKAGE_MIN} 713 } }, 714 }; 715 716 /* 717 * dfs_find_target_channel_in_channel_matrix() - finds the leakage matrix 718 * @ch_width: target channel width 719 * @NOL_channel: the NOL channel whose leakage matrix is required 720 * @pTarget_chnl_mtrx: pointer to target channel matrix returned. 721 * 722 * This function gives the leakage matrix for given NOL channel and ch_width 723 * 724 * Return: TRUE or FALSE 725 */ 726 #ifdef CONFIG_CHAN_NUM_API 727 static bool 728 dfs_find_target_channel_in_channel_matrix(enum phy_ch_width ch_width, 729 uint8_t NOL_channel, 730 struct dfs_tx_leak_info **pTarget_chnl_mtrx) 731 { 732 struct dfs_tx_leak_info *target_chan_matrix = NULL; 733 struct dfs_matrix_tx_leak_info *pchan_matrix = NULL; 734 uint32_t nchan_matrix; 735 int i = 0; 736 737 switch (ch_width) { 738 case CH_WIDTH_20MHZ: 739 /* HT20 */ 740 pchan_matrix = ht20_chan; 741 nchan_matrix = QDF_ARRAY_SIZE(ht20_chan); 742 break; 743 case CH_WIDTH_40MHZ: 744 /* HT40 */ 745 pchan_matrix = ht40_chan; 746 nchan_matrix = QDF_ARRAY_SIZE(ht40_chan); 747 break; 748 case CH_WIDTH_80MHZ: 749 /* HT80 */ 750 pchan_matrix = ht80_chan; 751 nchan_matrix = QDF_ARRAY_SIZE(ht80_chan); 752 break; 753 default: 754 /* handle exception and fall back to HT20 table */ 755 pchan_matrix = ht20_chan; 756 nchan_matrix = QDF_ARRAY_SIZE(ht20_chan); 757 break; 758 } 759 760 for (i = 0; i < nchan_matrix; i++) { 761 /* find the SAP channel to map the leakage matrix */ 762 if (NOL_channel == pchan_matrix[i].channel) { 763 target_chan_matrix = pchan_matrix[i].chan_matrix; 764 break; 765 } 766 } 767 768 if (!target_chan_matrix) { 769 return false; 770 } else { 771 *pTarget_chnl_mtrx = target_chan_matrix; 772 return true; 773 } 774 } 775 #endif 776 777 /* 778 * dfs_find_target_channel_in_channel_matrix_for_freq() - finds the leakage 779 * matrix. 780 * @chan_width: target channel width 781 * @nol_channel: the NOL channel frequency whose leakage matrix is required 782 * @pTarget_chnl_mtrx: pointer to target channel matrix returned. 783 * 784 * This function gives the leakage matrix for given NOL channel and ch_width 785 * 786 * Return: TRUE or FALSE 787 */ 788 #ifdef CONFIG_CHAN_FREQ_API 789 static bool 790 dfs_find_target_channel_in_channel_matrix_for_freq(enum phy_ch_width chan_width, 791 uint16_t nol_freq, 792 struct dfs_tx_leak_info 793 **pTarget_chnl_mtrx) 794 { 795 struct dfs_tx_leak_info *target_chan_matrix = NULL; 796 struct dfs_matrix_tx_leak_info *pchan_matrix = NULL; 797 uint32_t nchan_matrix; 798 int i = 0; 799 800 switch (chan_width) { 801 case CH_WIDTH_20MHZ: 802 /* HT20 */ 803 pchan_matrix = ht20_chan; 804 nchan_matrix = QDF_ARRAY_SIZE(ht20_chan); 805 break; 806 case CH_WIDTH_40MHZ: 807 /* HT40 */ 808 pchan_matrix = ht40_chan; 809 nchan_matrix = QDF_ARRAY_SIZE(ht40_chan); 810 break; 811 case CH_WIDTH_80MHZ: 812 /* HT80 */ 813 pchan_matrix = ht80_chan; 814 nchan_matrix = QDF_ARRAY_SIZE(ht80_chan); 815 break; 816 default: 817 /* handle exception and fall back to HT20 table */ 818 pchan_matrix = ht20_chan; 819 nchan_matrix = QDF_ARRAY_SIZE(ht20_chan); 820 break; 821 } 822 823 for (i = 0; i < nchan_matrix; i++) { 824 /* find the SAP channel to map the leakage matrix */ 825 if (nol_freq == pchan_matrix[i].channel_freq) { 826 target_chan_matrix = pchan_matrix[i].chan_matrix; 827 break; 828 } 829 } 830 831 if (!target_chan_matrix) { 832 return false; 833 } else { 834 *pTarget_chnl_mtrx = target_chan_matrix; 835 return true; 836 } 837 } 838 #endif 839 840 #ifdef CONFIG_CHAN_NUM_API 841 QDF_STATUS 842 dfs_mark_leaking_ch(struct wlan_dfs *dfs, 843 enum phy_ch_width ch_width, 844 uint8_t temp_ch_lst_sz, 845 uint8_t *temp_ch_lst) 846 { 847 struct dfs_tx_leak_info *target_chan_matrix = NULL; 848 uint32_t num_channel = (CHAN_ENUM_5720 - CHAN_ENUM_5180) + 1; 849 uint32_t j = 0; 850 uint32_t k = 0; 851 uint8_t dfs_nol_channel; 852 struct dfs_nolelem *nol; 853 854 nol = dfs->dfs_nol; 855 while (nol) { 856 dfs_nol_channel = wlan_freq_to_chan(nol->nol_freq); 857 if (false == dfs_find_target_channel_in_channel_matrix( 858 ch_width, dfs_nol_channel, 859 &target_chan_matrix)) { 860 /* 861 * should never happen, we should always find a table 862 * here, if we don't, need a fix here! 863 */ 864 dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 865 "Couldn't find target channel matrix!"); 866 QDF_ASSERT(0); 867 return QDF_STATUS_E_FAILURE; 868 } 869 /* 870 * following is based on assumption that both temp_ch_lst 871 * and target channel matrix are in increasing order of 872 * ch_id 873 */ 874 for (j = 0, k = 0; j < temp_ch_lst_sz && k < num_channel;) { 875 if (temp_ch_lst[j] == 0) { 876 j++; 877 continue; 878 } 879 if (target_chan_matrix[k].leak_chan != temp_ch_lst[j]) { 880 k++; 881 continue; 882 } 883 /* 884 * check leakage from candidate channel 885 * to NOL channel 886 */ 887 if (target_chan_matrix[k].leak_lvl <= 888 dfs->tx_leakage_threshold) { 889 /* 890 * candidate channel will have 891 * bad leakage in NOL channel, 892 * remove from temp list 893 */ 894 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 895 "dfs: channel: %d will have bad leakage due to channel: %d\n", 896 dfs_nol_channel, temp_ch_lst[j]); 897 temp_ch_lst[j] = 0; 898 } 899 j++; 900 k++; 901 } 902 nol = nol->nol_next; 903 } /* end of loop that selects each NOL */ 904 905 return QDF_STATUS_SUCCESS; 906 } 907 #endif 908 909 #ifdef CONFIG_CHAN_FREQ_API 910 #define END_CHAN_INDEX CHAN_ENUM_5720 911 #define START_CHAN_INDEX CHAN_ENUM_5180 912 QDF_STATUS 913 dfs_mark_leaking_chan_for_freq(struct wlan_dfs *dfs, 914 enum phy_ch_width ch_width, 915 uint8_t temp_chan_lst_sz, 916 uint16_t *temp_freq_lst) 917 { 918 struct dfs_tx_leak_info *target_chan_matrix = NULL; 919 uint32_t num_channel = (END_CHAN_INDEX - START_CHAN_INDEX) + 1; 920 uint32_t j = 0; 921 uint32_t k = 0; 922 struct dfs_nolelem *nol; 923 924 nol = dfs->dfs_nol; 925 while (nol) { 926 if (false == dfs_find_target_channel_in_channel_matrix_for_freq( 927 ch_width, nol->nol_freq, 928 &target_chan_matrix)) { 929 /* 930 * should never happen, we should always find a table 931 * here, if we don't, need a fix here! 932 */ 933 dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 934 "Couldn't find target channel matrix!"); 935 QDF_ASSERT(0); 936 return QDF_STATUS_E_FAILURE; 937 } 938 /* 939 * following is based on assumption that both temp_freq_lst 940 * and target channel matrix are in increasing order of 941 * ch_id 942 */ 943 for (j = 0, k = 0; j < temp_chan_lst_sz && k < num_channel;) { 944 if (temp_freq_lst[j] == 0) { 945 j++; 946 continue; 947 } 948 if (target_chan_matrix[k].leak_chan_freq != 949 temp_freq_lst[j]) { 950 k++; 951 continue; 952 } 953 /* 954 * check leakage from candidate channel 955 * to NOL channel 956 */ 957 if (target_chan_matrix[k].leak_lvl <= 958 dfs->tx_leakage_threshold) { 959 /* 960 * candidate channel will have 961 * bad leakage in NOL channel, 962 * remove from temp list 963 */ 964 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 965 "dfs: channel: %d will have bad leakage due to channel: %d\n", 966 nol->nol_freq, temp_freq_lst[j]); 967 temp_freq_lst[j] = 0; 968 } 969 j++; 970 k++; 971 } 972 nol = nol->nol_next; 973 } /* end of loop that selects each NOL */ 974 975 return QDF_STATUS_SUCCESS; 976 } 977 #endif 978 #else 979 #ifdef CONFIG_CHAN_NUM_API 980 QDF_STATUS 981 dfs_mark_leaking_ch(struct wlan_dfs *dfs, 982 enum phy_ch_width ch_width, 983 uint8_t temp_ch_lst_sz, 984 uint8_t *temp_ch_lst) 985 { 986 return QDF_STATUS_SUCCESS; 987 } 988 #endif 989 #ifdef CONFIG_CHAN_FREQ_API 990 QDF_STATUS 991 dfs_mark_leaking_chan_for_freq(struct wlan_dfs *dfs, 992 enum phy_ch_width ch_width, 993 uint8_t temp_chan_lst_sz, 994 uint16_t *temp_freq_lst) 995 { 996 return QDF_STATUS_SUCCESS; 997 } 998 #endif 999 #endif 1000 1001 /** 1002 * dfs_populate_80mhz_available_channels()- Populate channels for 80MHz using 1003 * bitmap 1004 * @dfs: Pointer to DFS structure. 1005 * @bitmap: bitmap 1006 * @avail_freq_list: prepared channel list 1007 * 1008 * Prepare 80MHz channels from the bitmap. 1009 * 1010 * Return: channel count 1011 */ 1012 #ifdef CONFIG_CHAN_NUM_API 1013 static uint8_t dfs_populate_80mhz_available_channels( 1014 struct wlan_dfs *dfs, 1015 struct chan_bonding_bitmap *bitmap, 1016 uint8_t *avail_chnl) 1017 { 1018 uint8_t i = 0; 1019 uint8_t chnl_count = 0; 1020 uint8_t start_chan = 0; 1021 1022 for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { 1023 start_chan = bitmap->chan_bonding_set[i].start_chan; 1024 if (bitmap->chan_bonding_set[i].chan_map == 1025 DFS_80MHZ_MASK) { 1026 avail_chnl[chnl_count++] = start_chan + 1027 (DFS_NEXT_5GHZ_CHANNEL * 0); 1028 avail_chnl[chnl_count++] = start_chan + 1029 (DFS_NEXT_5GHZ_CHANNEL * 1); 1030 avail_chnl[chnl_count++] = start_chan + 1031 (DFS_NEXT_5GHZ_CHANNEL * 2); 1032 avail_chnl[chnl_count++] = start_chan + 1033 (DFS_NEXT_5GHZ_CHANNEL * 3); 1034 } 1035 } 1036 1037 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1038 "channel count %d", chnl_count); 1039 1040 return chnl_count; 1041 } 1042 #endif 1043 1044 /* 1045 * dfs_populate_80mhz_available_channel_for_freq() - Populate 80MHZ channels 1046 * available for selection. 1047 * @dfs: Pointer to wlan_dfs. 1048 * @bitmap: Pointer to bonding channel bitmap. 1049 * @avail_freq_list: Pointer to frequency list of available channels. 1050 */ 1051 #ifdef CONFIG_CHAN_FREQ_API 1052 static uint8_t dfs_populate_80mhz_available_channel_for_freq( 1053 struct wlan_dfs *dfs, 1054 struct chan_bonding_bitmap *bitmap, 1055 uint16_t *avail_freq_list) 1056 { 1057 uint8_t i = 0; 1058 uint8_t chnl_count = 0; 1059 uint16_t start_chan_freq = 0; 1060 1061 for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { 1062 start_chan_freq = bitmap->chan_bonding_set[i].start_chan_freq; 1063 if (bitmap->chan_bonding_set[i].chan_map == 1064 DFS_80MHZ_MASK) { 1065 avail_freq_list[chnl_count++] = start_chan_freq + 1066 (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 0); 1067 avail_freq_list[chnl_count++] = start_chan_freq + 1068 (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 1); 1069 avail_freq_list[chnl_count++] = start_chan_freq + 1070 (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 2); 1071 avail_freq_list[chnl_count++] = start_chan_freq + 1072 (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 3); 1073 } 1074 } 1075 1076 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1077 "channel count %d", chnl_count); 1078 1079 return chnl_count; 1080 } 1081 #endif 1082 1083 /** 1084 * dfs_populate_40mhz_available_channels()- Populate channels for 40MHz using 1085 * bitmap 1086 * @dfs: Pointer to DFS structure. 1087 * @bitmap: bitmap 1088 * @avail_chnl: prepared channel list 1089 * 1090 * Prepare 40MHz channels from the bitmap. 1091 * 1092 * Return: channel count 1093 */ 1094 #ifdef CONFIG_CHAN_NUM_API 1095 static uint8_t dfs_populate_40mhz_available_channels( 1096 struct wlan_dfs *dfs, 1097 struct chan_bonding_bitmap *bitmap, 1098 uint8_t *avail_chnl) 1099 { 1100 uint8_t i = 0; 1101 uint8_t chnl_count = 0; 1102 uint8_t start_chan = 0; 1103 1104 for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { 1105 start_chan = bitmap->chan_bonding_set[i].start_chan; 1106 if ((bitmap->chan_bonding_set[i].chan_map & 1107 DFS_40MHZ_MASK_L) == DFS_40MHZ_MASK_L) { 1108 avail_chnl[chnl_count++] = start_chan + 1109 (DFS_NEXT_5GHZ_CHANNEL * 0); 1110 avail_chnl[chnl_count++] = start_chan + 1111 (DFS_NEXT_5GHZ_CHANNEL * 1); 1112 } 1113 if ((bitmap->chan_bonding_set[i].chan_map & 1114 DFS_40MHZ_MASK_H) == DFS_40MHZ_MASK_H) { 1115 avail_chnl[chnl_count++] = start_chan + 1116 (DFS_NEXT_5GHZ_CHANNEL * 2); 1117 avail_chnl[chnl_count++] = start_chan + 1118 (DFS_NEXT_5GHZ_CHANNEL * 3); 1119 } 1120 } 1121 1122 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1123 "channel count %d", chnl_count); 1124 1125 return chnl_count; 1126 } 1127 #endif 1128 1129 #ifdef CONFIG_CHAN_FREQ_API 1130 static uint8_t 1131 dfs_populate_40mhz_available_channel_for_freq(struct wlan_dfs *dfs, 1132 struct chan_bonding_bitmap *bmap, 1133 uint16_t *avail_freq_list) 1134 { 1135 uint8_t i = 0; 1136 uint8_t chnl_count = 0; 1137 uint16_t start_chan_freq = 0; 1138 1139 for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { 1140 start_chan_freq = bmap->chan_bonding_set[i].start_chan_freq; 1141 if ((bmap->chan_bonding_set[i].chan_map & 1142 DFS_40MHZ_MASK_L) == DFS_40MHZ_MASK_L) { 1143 avail_freq_list[chnl_count++] = start_chan_freq + 1144 (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 0); 1145 avail_freq_list[chnl_count++] = start_chan_freq + 1146 (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 1); 1147 } 1148 if ((bmap->chan_bonding_set[i].chan_map & 1149 DFS_40MHZ_MASK_H) == DFS_40MHZ_MASK_H) { 1150 avail_freq_list[chnl_count++] = start_chan_freq + 1151 (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 2); 1152 avail_freq_list[chnl_count++] = start_chan_freq + 1153 (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 3); 1154 } 1155 } 1156 1157 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1158 "channel count %d", chnl_count); 1159 1160 return chnl_count; 1161 } 1162 #endif 1163 1164 /** 1165 * dfs_populate_available_channels()- Populate channels based on width and 1166 * bitmap 1167 * @dfs: Pointer to DFS structure. 1168 * @bitmap: bitmap 1169 * @ch_width: channel width 1170 * @avail_chnl: prepared channel list 1171 * 1172 * Prepare channel list based on width and channel bitmap. 1173 * 1174 * Return: channel count 1175 */ 1176 #ifdef CONFIG_CHAN_NUM_API 1177 static uint8_t dfs_populate_available_channels( 1178 struct wlan_dfs *dfs, 1179 struct chan_bonding_bitmap *bitmap, 1180 uint8_t ch_width, 1181 uint8_t *avail_chnl) 1182 { 1183 switch (ch_width) { 1184 case DFS_CH_WIDTH_160MHZ: 1185 case DFS_CH_WIDTH_80P80MHZ: 1186 case DFS_CH_WIDTH_80MHZ: 1187 return dfs_populate_80mhz_available_channels( 1188 dfs, bitmap, avail_chnl); 1189 case DFS_CH_WIDTH_40MHZ: 1190 return dfs_populate_40mhz_available_channels( 1191 dfs, bitmap, avail_chnl); 1192 default: 1193 dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1194 "Invalid ch_width %d", ch_width); 1195 break; 1196 } 1197 1198 return 0; 1199 } 1200 #endif 1201 1202 /** 1203 * dfs_populate_available_channel_for_freq()- Populate channels based on width 1204 * and bitmap. 1205 * @dfs: Pointer to DFS structure. 1206 * @bitmap: bitmap 1207 * @chan_width: channel width 1208 * @avail_freq_list: prepared channel list 1209 * 1210 * Prepare channel list based on width and channel bitmap. 1211 * 1212 * Return: channel count 1213 */ 1214 #ifdef CONFIG_CHAN_FREQ_API 1215 static uint8_t 1216 dfs_populate_available_channel_for_freq(struct wlan_dfs *dfs, 1217 struct chan_bonding_bitmap *bitmap, 1218 uint8_t chan_width, 1219 uint16_t *freq_list) 1220 { 1221 switch (chan_width) { 1222 case DFS_CH_WIDTH_160MHZ: 1223 case DFS_CH_WIDTH_80P80MHZ: 1224 case DFS_CH_WIDTH_80MHZ: 1225 return dfs_populate_80mhz_available_channel_for_freq(dfs, 1226 bitmap, 1227 freq_list); 1228 case DFS_CH_WIDTH_40MHZ: 1229 return dfs_populate_40mhz_available_channel_for_freq(dfs, 1230 bitmap, 1231 freq_list); 1232 default: 1233 dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1234 "Invalid chan_width %d", chan_width); 1235 break; 1236 } 1237 1238 return 0; 1239 } 1240 #endif 1241 1242 /** 1243 * dfs_get_rand_from_lst()- Get random channel from a given channel list 1244 * @dfs: Pointer to DFS structure. 1245 * @ch_lst: channel list 1246 * @num_ch: number of channels 1247 * 1248 * Get random channel from given channel list. 1249 * 1250 * Return: channel number 1251 */ 1252 #ifdef CONFIG_CHAN_NUM_API 1253 static uint8_t dfs_get_rand_from_lst( 1254 struct wlan_dfs *dfs, 1255 uint8_t *ch_lst, 1256 uint8_t num_ch) 1257 { 1258 uint8_t i; 1259 uint32_t rand_byte = 0; 1260 1261 if (!num_ch || !ch_lst) { 1262 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 1263 "invalid param ch_lst %pK, num_ch = %d", 1264 ch_lst, num_ch); 1265 return 0; 1266 } 1267 1268 get_random_bytes((uint8_t *)&rand_byte, 1); 1269 i = (rand_byte + qdf_mc_timer_get_system_ticks()) % num_ch; 1270 1271 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1272 "random channel %d", ch_lst[i]); 1273 1274 return ch_lst[i]; 1275 } 1276 #endif 1277 1278 /** 1279 * dfs_get_rand_from_lst_for_freq()- Get random channel from a given channel 1280 * list. 1281 * @dfs: Pointer to DFS structure. 1282 * @freq_lst: Frequency list 1283 * @num_chan: number of channels 1284 * 1285 * Get random channel from given channel list. 1286 * 1287 * Return: channel frequency. 1288 */ 1289 1290 #ifdef CONFIG_CHAN_FREQ_API 1291 static uint16_t dfs_get_rand_from_lst_for_freq(struct wlan_dfs *dfs, 1292 uint16_t *freq_lst, 1293 uint8_t num_chan) 1294 { 1295 uint8_t i; 1296 uint32_t rand_byte = 0; 1297 1298 if (!num_chan || !freq_lst) { 1299 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 1300 "invalid param freq_lst %pK, num_chan = %d", 1301 freq_lst, num_chan); 1302 return 0; 1303 } 1304 1305 get_random_bytes((uint8_t *)&rand_byte, 1); 1306 i = (rand_byte + qdf_mc_timer_get_system_ticks()) % num_chan; 1307 1308 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1309 "random channel %d", freq_lst[i]); 1310 1311 return freq_lst[i]; 1312 } 1313 #endif 1314 1315 /** 1316 * dfs_random_channel_sel_set_bitmap()- Set channel bit in bitmap based 1317 * on given channel number 1318 * @dfs: Pointer to DFS structure. 1319 * @bitmap: bitmap 1320 * @channel: channel number 1321 * 1322 * Set channel bit in bitmap based on given channel number. 1323 * 1324 * Return: None 1325 */ 1326 #ifdef CONFIG_CHAN_NUM_API 1327 static void dfs_random_channel_sel_set_bitmap( 1328 struct wlan_dfs *dfs, 1329 struct chan_bonding_bitmap *bitmap, 1330 uint8_t channel) 1331 { 1332 int i = 0; 1333 int start_chan = 0; 1334 1335 for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { 1336 start_chan = bitmap->chan_bonding_set[i].start_chan; 1337 if (channel >= start_chan && channel <= start_chan + 12) { 1338 bitmap->chan_bonding_set[i].chan_map |= 1339 (1 << ((channel - start_chan) / 1340 DFS_80_NUM_SUB_CHANNEL)); 1341 return; 1342 } 1343 } 1344 1345 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1346 "Channel=%d is not in the bitmap", channel); 1347 } 1348 #endif 1349 1350 /** 1351 * dfs_random_channel_sel_set_bitmap()- Set channel bit in bitmap based 1352 * on given channel number 1353 * @dfs: Pointer to DFS structure. 1354 * @bitmap: bitmap 1355 * @chan_freq: channel frequency 1356 * 1357 * Set channel bit in bitmap based on given channel frequency. 1358 * 1359 * Return: None 1360 */ 1361 #ifdef CONFIG_CHAN_FREQ_API 1362 #define FREQUENCY_BAND_LIMIT 60 1363 static void 1364 dfs_random_channel_sel_set_bitmap_for_freq(struct wlan_dfs *dfs, 1365 struct chan_bonding_bitmap *bitmap, 1366 uint16_t chan_freq) 1367 { 1368 int i = 0; 1369 int start_chan_freq = 0; 1370 1371 for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { 1372 start_chan_freq = bitmap->chan_bonding_set[i].start_chan_freq; 1373 if (chan_freq >= start_chan_freq && 1374 chan_freq <= start_chan_freq + 1375 FREQUENCY_BAND_LIMIT) { 1376 bitmap->chan_bonding_set[i].chan_map |= 1377 (1 << ((chan_freq - start_chan_freq) / 1378 DFS_80_NUM_SUB_CHANNEL_FREQ)); 1379 return; 1380 } 1381 } 1382 1383 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1384 "Frequency=%d is not in the bitmap", chan_freq); 1385 } 1386 #endif 1387 1388 /** 1389 * dfs_find_ch_with_fallback()- find random channel 1390 * @dfs: Pointer to DFS structure. 1391 * @ch_wd: channel width 1392 * @center_freq_seg1: center frequency of secondary segment. 1393 * @ch_lst: list of available channels. 1394 * @num_ch: number of channels in the list. 1395 * 1396 * Find random channel based on given channel width and channel list, 1397 * fallback to lower width if requested channel width not available. 1398 * 1399 * Return: channel number 1400 */ 1401 #ifdef CONFIG_CHAN_NUM_API 1402 static uint8_t dfs_find_ch_with_fallback( 1403 struct wlan_dfs *dfs, 1404 uint8_t *ch_wd, 1405 uint8_t *center_freq_seg1, 1406 uint8_t *ch_lst, 1407 uint32_t num_ch) 1408 { 1409 bool flag = false; 1410 uint32_t rand_byte = 0; 1411 struct chan_bonding_bitmap ch_map = { { {0} } }; 1412 uint8_t count = 0, i, index = 0, final_cnt = 0, target_channel = 0; 1413 uint8_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_160_start_ch = 0; 1414 uint8_t final_lst[DFS_MAX_NUM_CHAN] = {0}; 1415 1416 /* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */ 1417 ch_map.chan_bonding_set[0].start_chan = 36; 1418 ch_map.chan_bonding_set[1].start_chan = 52; 1419 ch_map.chan_bonding_set[2].start_chan = 100; 1420 ch_map.chan_bonding_set[3].start_chan = 116; 1421 ch_map.chan_bonding_set[4].start_chan = 132; 1422 ch_map.chan_bonding_set[5].start_chan = 149; 1423 1424 for (i = 0; i < num_ch; i++) { 1425 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1426 "channel = %d added to bitmap", ch_lst[i]); 1427 dfs_random_channel_sel_set_bitmap(dfs, &ch_map, ch_lst[i]); 1428 } 1429 1430 /* populate available channel list from bitmap */ 1431 final_cnt = dfs_populate_available_channels(dfs, &ch_map, 1432 *ch_wd, final_lst); 1433 1434 /* If no valid ch bonding found, fallback */ 1435 if (final_cnt == 0) { 1436 if ((*ch_wd == DFS_CH_WIDTH_160MHZ) || 1437 (*ch_wd == DFS_CH_WIDTH_80P80MHZ) || 1438 (*ch_wd == DFS_CH_WIDTH_80MHZ)) { 1439 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1440 "from [%d] to 40Mhz", *ch_wd); 1441 *ch_wd = DFS_CH_WIDTH_40MHZ; 1442 } else if (*ch_wd == DFS_CH_WIDTH_40MHZ) { 1443 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1444 "from 40Mhz to 20MHz"); 1445 *ch_wd = DFS_CH_WIDTH_20MHZ; 1446 } 1447 return 0; 1448 } 1449 1450 /* ch count should be > 8 to switch new channel in 160Mhz band */ 1451 if (((*ch_wd == DFS_CH_WIDTH_160MHZ) || 1452 (*ch_wd == DFS_CH_WIDTH_80P80MHZ)) && 1453 (final_cnt < DFS_MAX_20M_SUB_CH)) { 1454 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1455 "from [%d] to 80Mhz", *ch_wd); 1456 *ch_wd = DFS_CH_WIDTH_80MHZ; 1457 return 0; 1458 } 1459 1460 if (*ch_wd == DFS_CH_WIDTH_160MHZ) { 1461 /* 1462 * Only 2 blocks for 160Mhz bandwidth i.e 36-64 & 100-128 1463 * and all the channels in these blocks are continuous 1464 * and separated by 4Mhz. 1465 */ 1466 for (i = 1; ((i < final_cnt)); i++) { 1467 if ((final_lst[i] - final_lst[i-1]) == 1468 DFS_NEXT_5GHZ_CHANNEL) 1469 count++; 1470 else 1471 count = 0; 1472 if (count == DFS_MAX_20M_SUB_CH - 1) { 1473 flag = true; 1474 new_160_start_ch = final_lst[i - count]; 1475 break; 1476 } 1477 } 1478 } else if (*ch_wd == DFS_CH_WIDTH_80P80MHZ) { 1479 flag = true; 1480 } 1481 1482 if ((flag == false) && (*ch_wd > DFS_CH_WIDTH_80MHZ)) { 1483 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1484 "from [%d] to 80Mhz", *ch_wd); 1485 *ch_wd = DFS_CH_WIDTH_80MHZ; 1486 return 0; 1487 } 1488 1489 if (*ch_wd == DFS_CH_WIDTH_160MHZ) { 1490 get_random_bytes((uint8_t *)&rand_byte, 1); 1491 rand_byte = (rand_byte + qdf_mc_timer_get_system_ticks()) 1492 % DFS_MAX_20M_SUB_CH; 1493 target_channel = new_160_start_ch + (rand_byte * 1494 DFS_80_NUM_SUB_CHANNEL); 1495 } else if (*ch_wd == DFS_CH_WIDTH_80P80MHZ) { 1496 get_random_bytes((uint8_t *)&rand_byte, 1); 1497 index = (rand_byte + qdf_mc_timer_get_system_ticks()) % 1498 final_cnt; 1499 target_channel = final_lst[index]; 1500 index -= (index % DFS_80_NUM_SUB_CHANNEL); 1501 primary_seg_start_ch = final_lst[index]; 1502 1503 /* reset channels associate with primary 80Mhz */ 1504 for (i = 0; i < DFS_80_NUM_SUB_CHANNEL; i++) 1505 final_lst[i + index] = 0; 1506 /* select and calculate center freq for secondary segment */ 1507 for (i = 0; i < final_cnt / DFS_80_NUM_SUB_CHANNEL; i++) { 1508 if (final_lst[i * DFS_80_NUM_SUB_CHANNEL] && 1509 (abs(primary_seg_start_ch - 1510 final_lst[i * DFS_80_NUM_SUB_CHANNEL]) > 1511 (DFS_MAX_20M_SUB_CH * 2))) { 1512 sec_seg_ch = 1513 final_lst[i * DFS_80_NUM_SUB_CHANNEL] + 1514 DFS_80MHZ_START_CENTER_CH_DIFF; 1515 break; 1516 } 1517 } 1518 1519 if (!sec_seg_ch && (final_cnt == DFS_MAX_20M_SUB_CH)) 1520 *ch_wd = DFS_CH_WIDTH_160MHZ; 1521 else if (!sec_seg_ch) 1522 *ch_wd = DFS_CH_WIDTH_80MHZ; 1523 1524 *center_freq_seg1 = sec_seg_ch; 1525 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1526 "Center frequency seg1 = %d", sec_seg_ch); 1527 } else { 1528 target_channel = dfs_get_rand_from_lst(dfs, 1529 final_lst, final_cnt); 1530 } 1531 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1532 "target channel = %d", target_channel); 1533 1534 return target_channel; 1535 } 1536 #endif 1537 1538 /** 1539 * dfs_find_ch_with_fallback_for_freq()- find random channel 1540 * @dfs: Pointer to DFS structure. 1541 * @chan_wd: channel width 1542 * @center_freq_seg1: center frequency of secondary segment. 1543 * @freq_lst: list of available frequency. 1544 * @num_chan: number of channels in the list. 1545 * 1546 * Find random channel based on given channel width and channel list, 1547 * fallback to lower width if requested channel width not available. 1548 * 1549 * Return: channel frequency. 1550 */ 1551 #ifdef CONFIG_CHAN_FREQ_API 1552 static uint16_t dfs_find_ch_with_fallback_for_freq(struct wlan_dfs *dfs, 1553 uint8_t *chan_wd, 1554 uint16_t *center_freq_seg1, 1555 uint16_t *freq_lst, 1556 uint32_t num_chan) 1557 { 1558 bool flag = false; 1559 uint32_t rand_byte = 0; 1560 struct chan_bonding_bitmap ch_map = { { {0} } }; 1561 uint8_t count = 0, i, index = 0, final_cnt = 0; 1562 uint16_t target_channel = 0; 1563 uint16_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_160_start_ch = 0; 1564 uint16_t final_lst[DFS_MAX_NUM_CHAN] = {0}; 1565 1566 /* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */ 1567 ch_map.chan_bonding_set[0].start_chan_freq = 5180; 1568 ch_map.chan_bonding_set[1].start_chan_freq = 5260; 1569 ch_map.chan_bonding_set[2].start_chan_freq = 5500; 1570 ch_map.chan_bonding_set[3].start_chan_freq = 5580; 1571 ch_map.chan_bonding_set[4].start_chan_freq = 5660; 1572 ch_map.chan_bonding_set[5].start_chan_freq = 5745; 1573 1574 for (i = 0; i < num_chan; i++) { 1575 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1576 "channel = %d added to bitmap", freq_lst[i]); 1577 dfs_random_channel_sel_set_bitmap_for_freq(dfs, &ch_map, 1578 freq_lst[i]); 1579 } 1580 1581 /* populate available channel list from bitmap */ 1582 final_cnt = dfs_populate_available_channel_for_freq(dfs, &ch_map, 1583 *chan_wd, final_lst); 1584 1585 /* If no valid ch bonding found, fallback */ 1586 if (final_cnt == 0) { 1587 if ((*chan_wd == DFS_CH_WIDTH_160MHZ) || 1588 (*chan_wd == DFS_CH_WIDTH_80P80MHZ) || 1589 (*chan_wd == DFS_CH_WIDTH_80MHZ)) { 1590 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1591 "from [%d] to 40Mhz", *chan_wd); 1592 *chan_wd = DFS_CH_WIDTH_40MHZ; 1593 } else if (*chan_wd == DFS_CH_WIDTH_40MHZ) { 1594 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1595 "from 40Mhz to 20MHz"); 1596 *chan_wd = DFS_CH_WIDTH_20MHZ; 1597 } 1598 return 0; 1599 } 1600 1601 /* ch count should be > 8 to switch new channel in 160Mhz band */ 1602 if (((*chan_wd == DFS_CH_WIDTH_160MHZ) || 1603 (*chan_wd == DFS_CH_WIDTH_80P80MHZ)) && 1604 (final_cnt < DFS_MAX_20M_SUB_CH)) { 1605 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1606 "from [%d] to 80Mhz", *chan_wd); 1607 *chan_wd = DFS_CH_WIDTH_80MHZ; 1608 return 0; 1609 } 1610 1611 if (*chan_wd == DFS_CH_WIDTH_160MHZ) { 1612 /* 1613 * Only 2 blocks for 160Mhz bandwidth i.e 36-64 & 100-128 1614 * and all the channels in these blocks are continuous 1615 * and separated by 4Mhz. 1616 */ 1617 for (i = 1; ((i < final_cnt)); i++) { 1618 if ((final_lst[i] - final_lst[i - 1]) == 1619 DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET) 1620 count++; 1621 else 1622 count = 0; 1623 if (count == DFS_MAX_20M_SUB_CH - 1) { 1624 flag = true; 1625 new_160_start_ch = final_lst[i - count]; 1626 break; 1627 } 1628 } 1629 } else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) { 1630 flag = true; 1631 } 1632 1633 if ((flag == false) && (*chan_wd > DFS_CH_WIDTH_80MHZ)) { 1634 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1635 "from [%d] to 80Mhz", *chan_wd); 1636 *chan_wd = DFS_CH_WIDTH_80MHZ; 1637 return 0; 1638 } 1639 1640 if (*chan_wd == DFS_CH_WIDTH_160MHZ) { 1641 get_random_bytes((uint8_t *)&rand_byte, 1); 1642 rand_byte = (rand_byte + qdf_mc_timer_get_system_ticks()) 1643 % DFS_MAX_20M_SUB_CH; 1644 target_channel = new_160_start_ch + (rand_byte * 1645 DFS_80_NUM_SUB_CHANNEL_FREQ); 1646 } else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) { 1647 get_random_bytes((uint8_t *)&rand_byte, 1); 1648 index = (rand_byte + qdf_mc_timer_get_system_ticks()) % 1649 final_cnt; 1650 target_channel = final_lst[index]; 1651 index -= (index % DFS_80_NUM_SUB_CHANNEL_FREQ); 1652 primary_seg_start_ch = final_lst[index]; 1653 1654 /* reset channels associate with primary 80Mhz */ 1655 for (i = 0; i < DFS_80_NUM_SUB_CHANNEL; i++) 1656 final_lst[i + index] = 0; 1657 /* select and calculate center freq for secondary segment */ 1658 for (i = 0; i < final_cnt / DFS_80_NUM_SUB_CHANNEL; i++) { 1659 if (final_lst[i * DFS_80_NUM_SUB_CHANNEL_FREQ] && 1660 (abs(primary_seg_start_ch - 1661 final_lst[i * DFS_80_NUM_SUB_CHANNEL_FREQ]) > 1662 (DFS_MAX_20M_SUB_CH * 2))) { 1663 sec_seg_ch = final_lst[i * 1664 DFS_80_NUM_SUB_CHANNEL_FREQ] + 1665 DFS_80MHZ_START_CENTER_CH_FREQ_DIFF; 1666 break; 1667 } 1668 } 1669 1670 if (!sec_seg_ch && (final_cnt == DFS_MAX_20M_SUB_CH)) 1671 *chan_wd = DFS_CH_WIDTH_160MHZ; 1672 else if (!sec_seg_ch) 1673 *chan_wd = DFS_CH_WIDTH_80MHZ; 1674 1675 *center_freq_seg1 = sec_seg_ch; 1676 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1677 "Center frequency seg1 = %d", sec_seg_ch); 1678 } else { 1679 target_channel = dfs_get_rand_from_lst_for_freq(dfs, 1680 final_lst, 1681 final_cnt); 1682 } 1683 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1684 "target channel = %d", target_channel); 1685 1686 return target_channel; 1687 } 1688 #endif 1689 1690 /** 1691 * dfs_remove_cur_ch_from_list()- remove current operating channels 1692 * @ch_list: list of avilable channel list 1693 * @ch_cnt: number of channels. 1694 * @ch_wd: channel width. 1695 * @cur_chan: current channel. 1696 * 1697 * Remove current channels from list of available channels. 1698 * 1699 * Return: channel number 1700 */ 1701 static void dfs_remove_cur_ch_from_list( 1702 struct dfs_channel *ch_list, 1703 uint32_t *ch_cnt, 1704 uint8_t *ch_wd, 1705 struct dfs_channel *cur_chan) 1706 { 1707 /* TODO */ 1708 return; 1709 } 1710 1711 bool dfs_is_freq_in_nol(struct wlan_dfs *dfs, uint32_t freq) 1712 { 1713 struct dfs_nolelem *nol; 1714 1715 if (!dfs) { 1716 dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "null dfs"); 1717 return false; 1718 } 1719 1720 nol = dfs->dfs_nol; 1721 while (nol) { 1722 if (freq == nol->nol_freq) { 1723 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1724 "%d is in nol", freq); 1725 return true; 1726 } 1727 nol = nol->nol_next; 1728 } 1729 1730 return false; 1731 } 1732 1733 /** 1734 * dfs_apply_rules()- prepare channel list based on flags 1735 * @dfs: dfs handler 1736 * @flags: channel flags 1737 * @random_chan_list: output channel list 1738 * @random_chan_cnt: output channel count 1739 * @ch_list: input channel list 1740 * @ch_cnt: input channel count 1741 * @dfs_region: dfs region 1742 * @acs_info: acs channel range information 1743 * 1744 * prepare channel list based on flags 1745 * 1746 * return: none 1747 */ 1748 #ifdef CONFIG_CHAN_NUM_API 1749 static void dfs_apply_rules(struct wlan_dfs *dfs, 1750 uint32_t flags, 1751 uint8_t *random_chan_list, 1752 uint32_t *random_chan_cnt, 1753 struct dfs_channel *ch_list, 1754 uint32_t ch_cnt, 1755 uint8_t dfs_region, 1756 struct dfs_acs_info *acs_info) 1757 { 1758 struct dfs_channel *chan; 1759 bool flag_no_weather = 0; 1760 bool flag_no_lower_5g = 0; 1761 bool flag_no_upper_5g = 0; 1762 bool flag_no_dfs_chan = 0; 1763 bool flag_no_2g_chan = 0; 1764 bool flag_no_5g_chan = 0; 1765 bool flag_no_japan_w53 = 0; 1766 int i; 1767 bool found = false; 1768 uint16_t j; 1769 1770 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "flags %d", flags); 1771 flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ? 1772 flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0; 1773 1774 if (dfs_region == DFS_MKK_REGION_VAL) { 1775 flag_no_lower_5g = flags & DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH; 1776 flag_no_upper_5g = flags & DFS_RANDOM_CH_FLAG_NO_UPEER_5G_CH; 1777 flag_no_japan_w53 = flags & DFS_RANDOM_CH_FLAG_NO_JAPAN_W53_CH; 1778 } 1779 1780 flag_no_dfs_chan = flags & DFS_RANDOM_CH_FLAG_NO_DFS_CH; 1781 flag_no_2g_chan = flags & DFS_RANDOM_CH_FLAG_NO_2GHZ_CH; 1782 flag_no_5g_chan = flags & DFS_RANDOM_CH_FLAG_NO_5GHZ_CH; 1783 1784 for (i = 0; i < ch_cnt; i++) { 1785 chan = &ch_list[i]; 1786 1787 if ((chan->dfs_ch_ieee == 0) || 1788 (chan->dfs_ch_ieee > MAX_CHANNEL_NUM)) { 1789 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1790 "invalid channel %d", chan->dfs_ch_ieee); 1791 continue; 1792 } 1793 1794 if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) { 1795 /* TODO : Skip all HT20 channels in the given mode */ 1796 if (chan->dfs_ch_ieee == 1797 dfs->dfs_curchan->dfs_ch_ieee) { 1798 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1799 "skip %d current operating channel", 1800 chan->dfs_ch_ieee); 1801 continue; 1802 } 1803 } 1804 1805 if (acs_info && acs_info->acs_mode) { 1806 for (j = 0; j < acs_info->num_of_channel; j++) { 1807 if (acs_info->channel_list[j] == 1808 chan->dfs_ch_ieee) { 1809 found = true; 1810 break; 1811 } 1812 } 1813 1814 if (!found) { 1815 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1816 "skip ch %d not in acs range", 1817 chan->dfs_ch_ieee); 1818 continue; 1819 } 1820 found = false; 1821 } 1822 1823 if (flag_no_2g_chan && 1824 chan->dfs_ch_ieee <= DFS_MAX_24GHZ_CHANNEL) { 1825 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1826 "skip 2.4 GHz channel=%d", chan->dfs_ch_ieee); 1827 continue; 1828 } 1829 1830 if (flag_no_5g_chan && 1831 chan->dfs_ch_ieee > DFS_MAX_24GHZ_CHANNEL) { 1832 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1833 "skip 5 GHz channel=%d", chan->dfs_ch_ieee); 1834 continue; 1835 } 1836 1837 if (flag_no_weather) { 1838 if (DFS_IS_CHANNEL_WEATHER_RADAR(chan->dfs_ch_freq)) { 1839 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1840 "skip weather channel=%d", 1841 chan->dfs_ch_ieee); 1842 continue; 1843 } 1844 } 1845 1846 if (flag_no_lower_5g && 1847 DFS_IS_CHAN_JAPAN_INDOOR(chan->dfs_ch_ieee)) { 1848 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1849 "skip indoor channel=%d", chan->dfs_ch_ieee); 1850 continue; 1851 } 1852 1853 if (flag_no_upper_5g && 1854 DFS_IS_CHAN_JAPAN_OUTDOOR(chan->dfs_ch_ieee)) { 1855 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1856 "skip outdoor channel=%d", chan->dfs_ch_ieee); 1857 continue; 1858 } 1859 1860 if (flag_no_dfs_chan && 1861 (chan->dfs_ch_flagext & WLAN_CHAN_DFS)) { 1862 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1863 "skip dfs channel=%d", chan->dfs_ch_ieee); 1864 continue; 1865 } 1866 1867 if (flag_no_japan_w53 && 1868 DFS_IS_CHAN_JAPAN_W53(chan->dfs_ch_ieee)) { 1869 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1870 "skip japan W53 channel=%d", 1871 chan->dfs_ch_ieee); 1872 continue; 1873 } 1874 1875 if (dfs_is_freq_in_nol(dfs, chan->dfs_ch_freq)) { 1876 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1877 "skip nol channel=%d", chan->dfs_ch_ieee); 1878 continue; 1879 } 1880 1881 random_chan_list[*random_chan_cnt] = chan->dfs_ch_ieee; 1882 *random_chan_cnt += 1; 1883 } 1884 } 1885 #endif 1886 1887 /** 1888 * dfs_apply_rules_for_freq()- prepare channel list based on flags 1889 * @dfs: dfs handler 1890 * @flags: channel flags 1891 * @random_chan_freq_list: output channel list 1892 * @random_chan_cnt: output channel count 1893 * @chan_list: input channel list 1894 * @chan_cnt: input channel count 1895 * @dfs_region: dfs region 1896 * @acs_info: acs channel range information 1897 * 1898 * prepare channel list based on flags 1899 * 1900 * return: none 1901 */ 1902 #ifdef CONFIG_CHAN_FREQ_API 1903 static void dfs_apply_rules_for_freq(struct wlan_dfs *dfs, 1904 uint32_t flags, 1905 uint16_t *random_chan_freq_list, 1906 uint32_t *random_chan_cnt, 1907 struct dfs_channel *chan_list, 1908 uint32_t chan_cnt, 1909 uint8_t dfs_region, 1910 struct dfs_acs_info *acs_info) 1911 { 1912 struct dfs_channel *chan; 1913 bool flag_no_weather = 0; 1914 bool flag_no_lower_5g = 0; 1915 bool flag_no_upper_5g = 0; 1916 bool flag_no_dfs_chan = 0; 1917 bool flag_no_2g_chan = 0; 1918 bool flag_no_5g_chan = 0; 1919 bool flag_no_japan_w53 = 0; 1920 int i; 1921 bool found = false; 1922 uint16_t j; 1923 1924 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "flags %d", flags); 1925 flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ? 1926 flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0; 1927 1928 if (dfs_region == DFS_MKK_REGION_VAL) { 1929 flag_no_lower_5g = flags & DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH; 1930 flag_no_upper_5g = flags & DFS_RANDOM_CH_FLAG_NO_UPEER_5G_CH; 1931 flag_no_japan_w53 = flags & DFS_RANDOM_CH_FLAG_NO_JAPAN_W53_CH; 1932 } 1933 1934 flag_no_dfs_chan = flags & DFS_RANDOM_CH_FLAG_NO_DFS_CH; 1935 flag_no_2g_chan = flags & DFS_RANDOM_CH_FLAG_NO_2GHZ_CH; 1936 flag_no_5g_chan = flags & DFS_RANDOM_CH_FLAG_NO_5GHZ_CH; 1937 1938 for (i = 0; i < chan_cnt; i++) { 1939 chan = &chan_list[i]; 1940 1941 if ((chan->dfs_ch_ieee == 0) || 1942 (chan->dfs_ch_ieee > MAX_CHANNEL_NUM)) { 1943 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1944 "invalid channel %d", chan->dfs_ch_ieee); 1945 continue; 1946 } 1947 1948 if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) { 1949 /* TODO : Skip all HT20 channels in the given mode */ 1950 if (chan->dfs_ch_freq == 1951 dfs->dfs_curchan->dfs_ch_freq) { 1952 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1953 "skip %d current operating channel", 1954 chan->dfs_ch_ieee); 1955 continue; 1956 } 1957 } 1958 if (acs_info && acs_info->acs_mode) { 1959 for (j = 0; j < acs_info->num_of_channel; j++) { 1960 if (acs_info->channel_list[j] == 1961 chan->dfs_ch_ieee) { 1962 found = true; 1963 break; 1964 } 1965 } 1966 1967 if (!found) { 1968 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1969 "skip ch %d not in acs range", 1970 chan->dfs_ch_ieee); 1971 continue; 1972 } 1973 found = false; 1974 } 1975 1976 if (flag_no_2g_chan && 1977 chan->dfs_ch_freq <= DFS_MAX_24GHZ_CHANNEL_FREQ) { 1978 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1979 "skip 2.4 GHz channel=%d", chan->dfs_ch_ieee); 1980 continue; 1981 } 1982 1983 if (flag_no_5g_chan && chan->dfs_ch_freq > 1984 DFS_MAX_24GHZ_CHANNEL_FREQ) 1985 { 1986 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1987 "skip 5 GHz channel=%d", chan->dfs_ch_ieee); 1988 continue; 1989 } 1990 1991 if (flag_no_weather) { 1992 if (DFS_IS_CHANNEL_WEATHER_RADAR(chan->dfs_ch_freq)) { 1993 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 1994 "skip weather channel=%d", 1995 chan->dfs_ch_ieee); 1996 continue; 1997 } 1998 } 1999 2000 if (flag_no_lower_5g && 2001 DFS_IS_CHAN_JAPAN_INDOOR_FREQ(chan->dfs_ch_freq)) { 2002 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2003 "skip indoor channel=%d", chan->dfs_ch_ieee); 2004 continue; 2005 } 2006 2007 if (flag_no_upper_5g && 2008 DFS_IS_CHAN_JAPAN_OUTDOOR_FREQ(chan->dfs_ch_freq)) { 2009 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2010 "skip outdoor channel=%d", chan->dfs_ch_ieee); 2011 continue; 2012 } 2013 2014 if (flag_no_dfs_chan && 2015 (chan->dfs_ch_flagext & WLAN_CHAN_DFS)) { 2016 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2017 "skip dfs channel=%d", chan->dfs_ch_ieee); 2018 continue; 2019 } 2020 2021 if (flag_no_japan_w53 && 2022 DFS_IS_CHAN_JAPAN_W53_FREQ(chan->dfs_ch_freq)) { 2023 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2024 "skip japan W53 channel=%d", 2025 chan->dfs_ch_ieee); 2026 continue; 2027 } 2028 2029 if (dfs_is_freq_in_nol(dfs, chan->dfs_ch_freq)) { 2030 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2031 "skip nol channel=%d", chan->dfs_ch_ieee); 2032 continue; 2033 } 2034 2035 random_chan_freq_list[*random_chan_cnt] = chan->dfs_ch_freq; 2036 *random_chan_cnt += 1; 2037 } 2038 } 2039 #endif 2040 2041 #ifdef CONFIG_CHAN_NUM_API 2042 uint8_t dfs_prepare_random_channel(struct wlan_dfs *dfs, 2043 struct dfs_channel *ch_list, 2044 uint32_t ch_cnt, 2045 uint32_t flags, 2046 uint8_t *ch_wd, 2047 struct dfs_channel *cur_chan, 2048 uint8_t dfs_region, 2049 struct dfs_acs_info *acs_info) 2050 { 2051 int i = 0; 2052 uint8_t final_cnt = 0; 2053 uint8_t target_ch = 0; 2054 uint8_t *random_chan_list = NULL; 2055 uint32_t random_chan_cnt = 0; 2056 uint16_t flag_no_weather = 0; 2057 uint8_t *leakage_adjusted_lst; 2058 uint8_t final_lst[NUM_CHANNELS] = {0}; 2059 2060 if (!ch_list || !ch_cnt) { 2061 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2062 "Invalid params %pK, ch_cnt=%d", 2063 ch_list, ch_cnt); 2064 return 0; 2065 } 2066 2067 if (*ch_wd < DFS_CH_WIDTH_20MHZ || *ch_wd > DFS_CH_WIDTH_80P80MHZ) { 2068 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2069 "Invalid ch_wd %d", *ch_wd); 2070 return 0; 2071 } 2072 2073 random_chan_list = qdf_mem_malloc(ch_cnt * sizeof(*random_chan_list)); 2074 if (!random_chan_list) 2075 return 0; 2076 2077 if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) 2078 dfs_remove_cur_ch_from_list(ch_list, &ch_cnt, ch_wd, cur_chan); 2079 2080 dfs_apply_rules(dfs, flags, random_chan_list, &random_chan_cnt, 2081 ch_list, ch_cnt, dfs_region, acs_info); 2082 2083 flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ? 2084 flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0; 2085 2086 /* list adjusted after leakage has been marked */ 2087 leakage_adjusted_lst = qdf_mem_malloc(random_chan_cnt); 2088 if (!leakage_adjusted_lst) { 2089 qdf_mem_free(random_chan_list); 2090 return 0; 2091 } 2092 2093 do { 2094 qdf_mem_copy(leakage_adjusted_lst, random_chan_list, 2095 random_chan_cnt); 2096 if (QDF_IS_STATUS_ERROR(dfs_mark_leaking_ch(dfs, *ch_wd, 2097 random_chan_cnt, 2098 leakage_adjusted_lst))) { 2099 qdf_mem_free(random_chan_list); 2100 qdf_mem_free(leakage_adjusted_lst); 2101 return 0; 2102 } 2103 2104 if (*ch_wd == DFS_CH_WIDTH_20MHZ) { 2105 /* 2106 * PASS: 3 - from leakage_adjusted_lst, prepare valid 2107 * ch list and use random number from that 2108 */ 2109 for (i = 0; i < random_chan_cnt; i++) { 2110 if (leakage_adjusted_lst[i] == 0) 2111 continue; 2112 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2113 "dfs: Channel=%d added to available list", 2114 leakage_adjusted_lst[i]); 2115 final_lst[final_cnt] = leakage_adjusted_lst[i]; 2116 final_cnt++; 2117 } 2118 target_ch = dfs_get_rand_from_lst( 2119 dfs, final_lst, final_cnt); 2120 break; 2121 } 2122 2123 target_ch = dfs_find_ch_with_fallback(dfs, ch_wd, 2124 &cur_chan->dfs_ch_vhtop_ch_freq_seg2, 2125 leakage_adjusted_lst, 2126 random_chan_cnt); 2127 2128 /* 2129 * When flag_no_weather is set, avoid usage of Adjacent 2130 * weather radar channel in HT40 mode as extension channel 2131 * will be on 5600. 2132 */ 2133 if (flag_no_weather && 2134 (target_ch == 2135 DFS_ADJACENT_WEATHER_RADAR_CHANNEL_NUM) && 2136 (*ch_wd == DFS_CH_WIDTH_40MHZ)) { 2137 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2138 "skip weather adjacent ch=%d\n", 2139 target_ch); 2140 continue; 2141 } 2142 2143 if (target_ch) 2144 break; 2145 } while (true); 2146 2147 qdf_mem_free(random_chan_list); 2148 qdf_mem_free(leakage_adjusted_lst); 2149 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "target_ch = %d", target_ch); 2150 2151 return target_ch; 2152 } 2153 #endif 2154 2155 #ifdef CONFIG_CHAN_FREQ_API 2156 uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs, 2157 struct dfs_channel *chan_list, 2158 uint32_t chan_cnt, 2159 uint32_t flags, 2160 uint8_t *chan_wd, 2161 struct dfs_channel *cur_chan, 2162 uint8_t dfs_region, 2163 struct dfs_acs_info *acs_info) 2164 { 2165 int i = 0; 2166 uint8_t final_cnt = 0; 2167 uint16_t target_freq = 0; 2168 uint16_t *random_chan_freq_list = NULL; 2169 uint32_t random_chan_cnt = 0; 2170 uint16_t flag_no_weather = 0; 2171 uint16_t *leakage_adjusted_lst; 2172 uint16_t final_lst[NUM_CHANNELS] = {0}; 2173 uint16_t *dfs_cfreq_seg2 = NULL; 2174 2175 if (!chan_list || !chan_cnt) { 2176 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2177 "Invalid params %pK, chan_cnt=%d", 2178 chan_list, chan_cnt); 2179 return 0; 2180 } 2181 2182 if (*chan_wd < DFS_CH_WIDTH_20MHZ || *chan_wd > DFS_CH_WIDTH_80P80MHZ) { 2183 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2184 "Invalid chan_wd %d", *chan_wd); 2185 return 0; 2186 } 2187 2188 random_chan_freq_list = 2189 qdf_mem_malloc(chan_cnt * sizeof(*random_chan_freq_list)); 2190 if (!random_chan_freq_list) 2191 return 0; 2192 2193 if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) 2194 dfs_remove_cur_ch_from_list(chan_list, &chan_cnt, chan_wd, cur_chan); 2195 2196 dfs_apply_rules_for_freq(dfs, flags, random_chan_freq_list, 2197 &random_chan_cnt, chan_list, chan_cnt, 2198 dfs_region, acs_info); 2199 2200 flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ? 2201 flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0; 2202 2203 /* list adjusted after leakage has been marked */ 2204 leakage_adjusted_lst = qdf_mem_malloc(random_chan_cnt); 2205 if (!leakage_adjusted_lst) { 2206 qdf_mem_free(random_chan_freq_list); 2207 return 0; 2208 } 2209 2210 do { 2211 int ret; 2212 2213 qdf_mem_copy(leakage_adjusted_lst, random_chan_freq_list, 2214 random_chan_cnt); 2215 ret = dfs_mark_leaking_chan_for_freq(dfs, *chan_wd, 2216 random_chan_cnt, 2217 leakage_adjusted_lst); 2218 if (QDF_IS_STATUS_ERROR(ret)) { 2219 qdf_mem_free(random_chan_freq_list); 2220 qdf_mem_free(leakage_adjusted_lst); 2221 return 0; 2222 } 2223 2224 if (*chan_wd == DFS_CH_WIDTH_20MHZ) { 2225 /* 2226 * PASS: 3 - from leakage_adjusted_lst, prepare valid 2227 * ch list and use random number from that 2228 */ 2229 for (i = 0; i < random_chan_cnt; i++) { 2230 if (leakage_adjusted_lst[i] == 0) 2231 continue; 2232 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2233 "Channel=%d added to available list", 2234 leakage_adjusted_lst[i]); 2235 final_lst[final_cnt] = leakage_adjusted_lst[i]; 2236 final_cnt++; 2237 } 2238 target_freq = dfs_get_rand_from_lst_for_freq(dfs, 2239 final_lst, 2240 final_cnt); 2241 break; 2242 } 2243 dfs_cfreq_seg2 = &cur_chan->dfs_ch_mhz_freq_seg2; 2244 target_freq = 2245 dfs_find_ch_with_fallback_for_freq(dfs, chan_wd, 2246 dfs_cfreq_seg2, 2247 leakage_adjusted_lst, 2248 random_chan_cnt); 2249 2250 /* 2251 * When flag_no_weather is set, avoid usage of Adjacent 2252 * weather radar channel in HT40 mode as extension channel 2253 * will be on 5600. 2254 */ 2255 if (flag_no_weather && 2256 (target_freq == 2257 DFS_ADJACENT_WEATHER_RADAR_CHANNEL_FREQ) && 2258 (*chan_wd == DFS_CH_WIDTH_40MHZ)) { 2259 dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, 2260 "skip weather adjacent ch=%d\n", 2261 target_freq); 2262 continue; 2263 } 2264 2265 if (target_freq) 2266 break; 2267 } while (true); 2268 2269 qdf_mem_free(random_chan_freq_list); 2270 qdf_mem_free(leakage_adjusted_lst); 2271 dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "target_freq = %d", 2272 target_freq); 2273 2274 return target_freq; 2275 } 2276 #endif 2277