1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: This file contains definition for mandatory legacy API 20 */ 21 22 #include "qdf_str.h" 23 #include "wlan_utility.h" 24 #include <wlan_cmn.h> 25 #include "wlan_osif_priv.h" 26 #include <net/cfg80211.h> 27 #include <qdf_module.h> 28 #include <wlan_vdev_mlme_api.h> 29 #include "cfg_ucfg_api.h" 30 #include <wlan_serialization_api.h> 31 #include "wlan_cm_api.h" 32 #include "host_diag_core_event.h" 33 34 /* CRC polynomial 0xedb88320 */ 35 static unsigned long const wlan_shortssid_table[] = { 36 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 37 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 38 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 39 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 40 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 41 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 42 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 43 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 44 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 45 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 46 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 47 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 48 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 49 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 50 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 51 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 52 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 53 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 54 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 55 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 56 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 57 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 58 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 59 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 60 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 61 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 62 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 63 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 64 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 65 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 66 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 67 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 68 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 69 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 70 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 71 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 72 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 73 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 74 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 75 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 76 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 77 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 78 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 79 }; 80 81 uint32_t wlan_construct_shortssid(uint8_t *ssid, uint8_t ssid_len) 82 { 83 uint32_t shortssid = 0xffffffff; 84 uint8_t i; 85 86 if (!ssid || ssid_len > WLAN_SSID_MAX_LEN) 87 return shortssid; 88 89 for (i = 0; i < ssid_len; i++) 90 shortssid = wlan_shortssid_table[(shortssid ^ ssid[i]) & 0xff] ^ 91 (shortssid >> 8); 92 return (shortssid ^ 0xffffffff); 93 } 94 95 uint32_t wlan_chan_to_freq(uint8_t chan) 96 { 97 if (chan == 0 ) 98 return 0; 99 100 if (chan < WLAN_24_GHZ_CHANNEL_14) 101 return WLAN_24_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ; 102 else if (chan == WLAN_24_GHZ_CHANNEL_14) 103 return WLAN_CHAN_14_FREQ; 104 else if (chan < WLAN_24_GHZ_CHANNEL_27) 105 /* ch 15 - ch 26 */ 106 return WLAN_CHAN_15_FREQ + 107 (chan - WLAN_24_GHZ_CHANNEL_15) * WLAN_CHAN_SPACING_20MHZ; 108 else if (chan == WLAN_5_GHZ_CHANNEL_170) 109 return WLAN_CHAN_170_FREQ; 110 else 111 return WLAN_5_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ; 112 } 113 114 uint8_t wlan_freq_to_chan(uint32_t freq) 115 { 116 uint8_t chan; 117 118 if (freq == 0) 119 return 0; 120 121 if (freq > WLAN_24_GHZ_BASE_FREQ && freq < WLAN_CHAN_14_FREQ) 122 chan = ((freq - WLAN_24_GHZ_BASE_FREQ) / 123 WLAN_CHAN_SPACING_5MHZ); 124 else if (freq == WLAN_CHAN_14_FREQ) 125 chan = WLAN_24_GHZ_CHANNEL_14; 126 else if ((freq > WLAN_24_GHZ_BASE_FREQ) && 127 (freq < WLAN_5_GHZ_BASE_FREQ)) 128 chan = (((freq - WLAN_CHAN_15_FREQ) / 129 WLAN_CHAN_SPACING_20MHZ) + 130 WLAN_24_GHZ_CHANNEL_15); 131 else 132 chan = (freq - WLAN_5_GHZ_BASE_FREQ) / 133 WLAN_CHAN_SPACING_5MHZ; 134 135 return chan; 136 } 137 138 void 139 wlan_get_320_center_freq(qdf_freq_t freq, 140 qdf_freq_t *center_freq1, 141 qdf_freq_t *center_freq2) 142 { 143 *center_freq1 = 0; 144 *center_freq2 = 0; 145 146 if ((freq >= 5500) && (freq <= 5800)) { 147 *center_freq1 = 5650; 148 } else if ((freq >= 5955) && (freq <= 6095)) { 149 *center_freq1 = 6105; 150 } else if ((freq >= 6115) && (freq <= 6255)) { 151 *center_freq1 = 6105; 152 *center_freq2 = 6265; 153 } else if ((freq >= 6275) && (freq <= 6415)) { 154 *center_freq1 = 6265; 155 *center_freq2 = 6425; 156 } else if ((freq >= 6435) && (freq <= 6575)) { 157 *center_freq1 = 6425; 158 *center_freq2 = 6585; 159 } else if ((freq >= 6595) && (freq <= 6735)) { 160 *center_freq1 = 6585; 161 *center_freq2 = 6745; 162 } else if ((freq >= 6755) && (freq <= 6895)) { 163 *center_freq1 = 6745; 164 *center_freq2 = 6905; 165 } else if ((freq >= 6915) && (freq <= 7055)) { 166 *center_freq1 = 6905; 167 } 168 } 169 170 bool wlan_is_ie_valid(const uint8_t *ie, size_t ie_len) 171 { 172 uint8_t elen; 173 174 while (ie_len) { 175 if (ie_len < 2) 176 return false; 177 178 elen = ie[1]; 179 ie_len -= 2; 180 ie += 2; 181 if (elen > ie_len) 182 return false; 183 184 ie_len -= elen; 185 ie += elen; 186 } 187 188 return true; 189 } 190 191 static const uint8_t *wlan_get_ie_ptr_from_eid_n_oui(uint8_t eid, 192 const uint8_t *oui, 193 uint8_t oui_size, 194 const uint8_t *ie, 195 uint16_t ie_len) 196 { 197 int32_t left = ie_len; 198 const uint8_t *ptr = ie; 199 uint8_t elem_id, elem_len; 200 201 while (left >= 2) { 202 elem_id = ptr[0]; 203 elem_len = ptr[1]; 204 left -= 2; 205 206 if (elem_len > left) 207 return NULL; 208 209 if (eid == elem_id) { 210 /* if oui is not provide eid match is enough */ 211 if (!oui) 212 return ptr; 213 214 /* 215 * if oui is provided and oui_size is more than left 216 * bytes, then we cannot have match 217 */ 218 if (oui_size > left) 219 return NULL; 220 221 if (qdf_mem_cmp(&ptr[2], oui, oui_size) == 0) 222 return ptr; 223 } 224 225 left -= elem_len; 226 ptr += (elem_len + 2); 227 } 228 229 return NULL; 230 } 231 232 void wlan_iecap_set(uint8_t *iecap, 233 uint8_t bit_pos, 234 uint8_t tot_bits, 235 uint32_t value) 236 { 237 uint8_t fit_bits; 238 uint8_t byte_cnt; 239 uint8_t prev_fit_bits = 0; 240 uint32_t shift_value; 241 242 /* calculate byte position of the field in IE capability */ 243 byte_cnt = bit_pos / 8; 244 /* calculate the bit position in the start byte that needs to be set */ 245 bit_pos = bit_pos % 8; 246 fit_bits = 8 - bit_pos; 247 fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits; 248 249 while ((bit_pos + tot_bits) > 8) { 250 /* clear the target bit */ 251 QDF_SET_BITS(iecap[byte_cnt], bit_pos, fit_bits, value); 252 tot_bits = tot_bits - fit_bits; 253 bit_pos = bit_pos + fit_bits; 254 if (bit_pos == 8) { 255 bit_pos = 0; 256 byte_cnt++; 257 } 258 prev_fit_bits = prev_fit_bits + fit_bits; 259 fit_bits = 8 - bit_pos; 260 fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits; 261 } 262 263 if ((bit_pos + tot_bits) <= 8) { 264 /* clear the target bit */ 265 shift_value = value >> prev_fit_bits; 266 QDF_SET_BITS(iecap[byte_cnt], bit_pos, fit_bits, shift_value); 267 } 268 } 269 270 uint32_t wlan_iecap_get(uint8_t *iecap, 271 uint8_t bit_pos, 272 uint32_t tot_bits) 273 { 274 uint8_t fit_bits; 275 uint8_t byte_cnt; 276 uint8_t temp_val; 277 uint8_t cur_bit_pos = 0; 278 uint32_t val = 0; 279 280 /* calculate byte position of the field in IE capability */ 281 byte_cnt = bit_pos / 8; 282 temp_val = *(iecap + byte_cnt); 283 /* calculate the bit position in the start byte */ 284 bit_pos = bit_pos % 8; 285 fit_bits = 8 - bit_pos; 286 fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits; 287 288 while ((tot_bits + bit_pos) > 8) { 289 val |= QDF_GET_BITS(temp_val, bit_pos, fit_bits) << cur_bit_pos; 290 tot_bits = tot_bits - fit_bits; 291 bit_pos = bit_pos + fit_bits; 292 if (bit_pos == 8) { 293 bit_pos = 0; 294 byte_cnt++; 295 temp_val = *(iecap + byte_cnt); 296 } 297 cur_bit_pos = cur_bit_pos + fit_bits; 298 299 fit_bits = 8 - bit_pos; 300 fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits; 301 } 302 303 if ((bit_pos + tot_bits) <= 8) 304 val |= QDF_GET_BITS(temp_val, bit_pos, fit_bits) << cur_bit_pos; 305 306 return val; 307 } 308 309 const uint8_t *wlan_get_ie_ptr_from_eid(uint8_t eid, 310 const uint8_t *ie, 311 int ie_len) 312 { 313 return wlan_get_ie_ptr_from_eid_n_oui(eid, NULL, 0, ie, ie_len); 314 } 315 316 const uint8_t *wlan_get_vendor_ie_ptr_from_oui(const uint8_t *oui, 317 uint8_t oui_size, 318 const uint8_t *ie, 319 uint16_t ie_len) 320 { 321 return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_VENDOR, 322 oui, oui_size, ie, ie_len); 323 } 324 325 const uint8_t *wlan_get_ext_ie_ptr_from_ext_id(const uint8_t *oui, 326 uint8_t oui_size, 327 const uint8_t *ie, 328 uint16_t ie_len) 329 { 330 return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_EXT, 331 oui, oui_size, ie, ie_len); 332 } 333 334 static inline 335 QDF_STATUS wlan_get_elemunit_info(bool is_subelem, 336 uint8_t subelemfragid, 337 uint8_t *elemunit_fragid, 338 qdf_size_t *elemunit_hdrlen, 339 qdf_size_t *elemunit_maxpayloadlen, 340 int *elemunit_id_pos, 341 int *elemunit_len_pos, 342 int *elemunit_idext_pos) 343 { 344 /* Helper function to populate information about the given element unit. 345 * Here, an 'element unit' refers to either an 802.11 element or a 346 * 802.11 subelement. 347 * 348 * Populating this information in a central helper here allows for 349 * better control over handling of future variances, and also for common 350 * code for handling different types of element units. 351 */ 352 353 if (is_subelem) { 354 /* Populate the subelement header length */ 355 if (elemunit_hdrlen) 356 *elemunit_hdrlen = sizeof(struct subelem_header); 357 358 /* Populate the subelement's max payload length */ 359 if (elemunit_maxpayloadlen) 360 *elemunit_maxpayloadlen = WLAN_MAX_SUBELEM_LEN; 361 362 /* Populate the index position for the subelement ID */ 363 if (elemunit_id_pos) 364 *elemunit_id_pos = qdf_offsetof(struct subelem_header, 365 subelem_id); 366 367 /* Populate the index position for the subelement length */ 368 if (elemunit_len_pos) 369 *elemunit_len_pos = qdf_offsetof(struct subelem_header, 370 subelem_len); 371 372 /* Mark that there is (currently) no valid value for subelement 373 * ID extension. 374 */ 375 if (elemunit_idext_pos) 376 *elemunit_idext_pos = -1; 377 378 /* Populate the subelement fragment ID (which can vary by 379 * protocol area). This could also have been directly populated 380 * by the caller, but we populate it here for uniformity and 381 * future control of variability. 382 */ 383 if (elemunit_fragid) 384 *elemunit_fragid = subelemfragid; 385 } else { 386 /* Populate the element header length */ 387 if (elemunit_hdrlen) 388 *elemunit_hdrlen = sizeof(struct ie_header); 389 390 /* Populate the element's max payload length */ 391 if (elemunit_maxpayloadlen) 392 *elemunit_maxpayloadlen = WLAN_MAX_IE_LEN; 393 394 /* Populate the index position for the element ID */ 395 if (elemunit_id_pos) 396 *elemunit_id_pos = qdf_offsetof(struct ie_header, 397 ie_id); 398 399 /* Populate the index position for the element length */ 400 if (elemunit_len_pos) 401 *elemunit_len_pos = qdf_offsetof(struct ie_header, 402 ie_len); 403 404 /* Populate the index position for the element ID extension 405 */ 406 if (elemunit_idext_pos) 407 *elemunit_idext_pos = 408 qdf_offsetof(struct extn_ie_header, ie_extn_id); 409 410 /* Populate the element fragment ID. */ 411 if (elemunit_fragid) 412 *elemunit_fragid = WLAN_ELEMID_FRAGMENT; 413 } 414 415 return QDF_STATUS_SUCCESS; 416 } 417 418 static QDF_STATUS 419 wlan_get_elemsubelem_fragseq_creationparams(bool is_subelem, 420 uint8_t id, 421 qdf_size_t payloadlen, 422 bool *is_frag_required, 423 qdf_size_t *expected_fragseqlen, 424 qdf_size_t *prepayload_leadbytes, 425 uint32_t *num_maxsizefrags, 426 qdf_size_t *smallerfrag_size, 427 qdf_size_t *extrahdrbytes) 428 { 429 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element 430 * or a 802.11 subelement. 431 */ 432 qdf_size_t elemunit_hdrlen; 433 qdf_size_t elemunit_maxpayloadlen; 434 435 qdf_size_t tmp_expected_fragseqlen; 436 qdf_size_t tmp_prepayload_leadbytes; 437 uint32_t tmp_num_maxsizefrags; 438 qdf_size_t tmp_smallerfrag_size; 439 qdf_size_t tmp_extrahdrbytes; 440 441 QDF_STATUS ret; 442 443 /* Helper function to determine element or subelement fragment sequence 444 * creation parameters. Currently, this helper determines the following 445 * parameters (it is mandatory for the caller to provide the pointer 446 * for the first parameter, those for the remaining are optional): 447 * 448 * - Whether fragmentation is required 449 * If fragmentation is required then the following are determined, else 450 * they should be ignored by the caller: 451 * - Expected fragment sequence length (inclusive of payload and all 452 * headers) 453 * - The lead bytes that occur before the payload (i.e. the lead 454 * element/subelement's header, and if applicable, the element's 455 * element ID extension) 456 * - The number of max sized fragments (inclusive of the lead element) 457 * - The size of the smaller sized fragment at the end (non-zero if such 458 * a fragment would be present, zero if it would be absent) 459 * - The number of extra header bytes that would be introduced (not 460 * inclusive of the header of the lead fragment). 461 */ 462 463 if (!is_frag_required) { 464 qdf_nofl_err("Pointer to indication of whether fragmentation is required or not is NULL"); 465 return QDF_STATUS_E_NULL_VALUE; 466 } 467 468 ret = wlan_get_elemunit_info(is_subelem, 469 0, 470 NULL, 471 &elemunit_hdrlen, 472 &elemunit_maxpayloadlen, 473 NULL, 474 NULL, 475 NULL); 476 if (QDF_IS_STATUS_ERROR(ret)) { 477 qdf_rl_nofl_err("Get elem unit info: Error %d", 478 ret); 479 return QDF_STATUS_E_FAILURE; 480 } 481 482 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM)) { 483 if (payloadlen <= (elemunit_maxpayloadlen - 1)) { 484 *is_frag_required = false; 485 return QDF_STATUS_SUCCESS; 486 } 487 } else { 488 if (payloadlen <= elemunit_maxpayloadlen) { 489 *is_frag_required = false; 490 return QDF_STATUS_SUCCESS; 491 } 492 } 493 494 *is_frag_required = true; 495 496 if (!expected_fragseqlen && 497 !prepayload_leadbytes && !num_maxsizefrags && 498 !smallerfrag_size && !extrahdrbytes) 499 return QDF_STATUS_SUCCESS; 500 501 tmp_expected_fragseqlen = 0; 502 tmp_prepayload_leadbytes = 0; 503 tmp_num_maxsizefrags = 0; 504 tmp_smallerfrag_size = 0; 505 tmp_extrahdrbytes = 0; 506 507 /* As per the standard, the information to be fragmented is divided into 508 * M + N portions, where the following define each variable: 509 * 510 * I)For an element without an Element ID Extension field, or for a 511 * subelement: 512 * L is the size of the information in octets (this does not include the 513 * element/subelement header) 514 * M is L/255 floored 515 * N is equal to 1 if L mod 255 > 0 and equal to 0 otherwise. 516 * The size of each of the M fragments is 255 octets 517 * If N is 1, then the size of this single fragment is L mod 255 octets 518 * 519 * II) For an element with an Element ID Extension field: 520 * L is the size of the information in octets (this does not include the 521 * element header and the element ID extension field) 522 * M is (L + 1)/255 floored 523 * N is equal to 1 if (L - 254) mod 255 > 0 and equal to 0 otherwise. 524 * The size of each of the M fragments is 255 octets 525 * If N is 1, then the size of this single fragment is (L - 254) mod 255 526 * octets. 527 * 528 * For both I and II above, the mapping of code variables is as follows: 529 * payloadlen = L 530 * tmp_num_maxsizefrags = M 531 * tmp_smallerfrag_size = Size of N if N is 1, else 0 532 * Additionally, elemunit_maxpayloadlen is used to denote the value 533 * 255 for future extensibility if and when required. 534 */ 535 536 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM)) { 537 tmp_num_maxsizefrags = (payloadlen + 1) / 538 elemunit_maxpayloadlen; 539 tmp_smallerfrag_size = 540 (payloadlen - (elemunit_maxpayloadlen - 1)) % 541 elemunit_maxpayloadlen; 542 } else { 543 tmp_num_maxsizefrags = payloadlen / elemunit_maxpayloadlen; 544 tmp_smallerfrag_size = payloadlen % 545 elemunit_maxpayloadlen; 546 } 547 548 /* Determine the number of extra bytes introduced due to the headers of 549 * non-leading fragments. 550 */ 551 tmp_extrahdrbytes = (tmp_num_maxsizefrags - 1) * elemunit_hdrlen; 552 if (tmp_smallerfrag_size) 553 tmp_extrahdrbytes += elemunit_hdrlen; 554 555 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM)) 556 tmp_prepayload_leadbytes = elemunit_hdrlen + 1; 557 else 558 tmp_prepayload_leadbytes = elemunit_hdrlen; 559 560 tmp_expected_fragseqlen = tmp_prepayload_leadbytes + 561 payloadlen + tmp_extrahdrbytes; 562 563 if (expected_fragseqlen) 564 *expected_fragseqlen = tmp_expected_fragseqlen; 565 566 if (prepayload_leadbytes) 567 *prepayload_leadbytes = tmp_prepayload_leadbytes; 568 569 if (num_maxsizefrags) 570 *num_maxsizefrags = tmp_num_maxsizefrags; 571 572 if (smallerfrag_size) 573 *smallerfrag_size = tmp_smallerfrag_size; 574 575 if (extrahdrbytes) 576 *extrahdrbytes = tmp_extrahdrbytes; 577 578 return QDF_STATUS_SUCCESS; 579 } 580 581 static QDF_STATUS 582 wlan_create_elemsubelem_fragseq(bool inline_frag, 583 bool is_subelem, 584 uint8_t id, 585 uint8_t idext, 586 uint8_t subelemfragid, 587 uint8_t *payloadbuff, 588 qdf_size_t payloadbuff_maxsize, 589 qdf_size_t payloadlen, 590 uint8_t *fragbuff, 591 qdf_size_t fragbuff_maxsize, 592 qdf_size_t *fragseqlen) 593 { 594 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element 595 * or a 802.11 subelement. 596 */ 597 uint8_t elemunit_fragid; 598 qdf_size_t elemunit_hdrlen; 599 qdf_size_t elemunit_maxpayloadlen; 600 int elemunit_id_pos; 601 int elemunit_len_pos; 602 int elemunit_idext_pos; 603 uint8_t *curr_elemunit_ptr; 604 605 /* Whether fragmentation is required */ 606 bool is_frag_required; 607 608 /*Fragment sequence length (inclusive of payload and all headers) */ 609 qdf_size_t expected_fragseqlen; 610 611 /* Number of fragments with the maximum size */ 612 uint32_t num_maxsizefrags; 613 /* Size of the last fragment which is smaller than the maximum (if 614 * present). If such a fragment is not present, this size will be zero. 615 */ 616 qdf_size_t smallerfrag_size; 617 618 /* The number of extra header bytes that would be introduced (not 619 * inclusive of the header of the lead fragment). 620 */ 621 qdf_size_t extrahdrbytes; 622 /* The number of extra header bytes remaining to be introduced */ 623 qdf_size_t extrahdrbytes_remaining; 624 625 /* The lead bytes that occur before the payload */ 626 qdf_size_t prepayload_leadbytes; 627 628 /* used for inline copy, the extra bytes needed in the payload buffer 629 * due to difference in destination and source. 630 * Note that the caller should ensure there is enough bytes beyond 631 * valid data until payloadbuff_maxsize*/ 632 qdf_size_t payloadbuff_shiftsize; 633 634 /* Miscellaneous variables */ 635 uint8_t *src; 636 uint8_t *dst; 637 uint16_t i; 638 qdf_size_t bytes_to_transfer; 639 640 QDF_STATUS ret; 641 642 /* Helper function to create an element or subelement fragment sequence. 643 * Refer to the documentation of the public APIs which call this helper, 644 * for more information. These APIs are mainly wrappers over this 645 * helper. 646 */ 647 648 ret = wlan_get_elemunit_info(is_subelem, 649 subelemfragid, 650 &elemunit_fragid, 651 &elemunit_hdrlen, 652 &elemunit_maxpayloadlen, 653 &elemunit_id_pos, 654 &elemunit_len_pos, 655 &elemunit_idext_pos); 656 if (QDF_IS_STATUS_ERROR(ret)) { 657 qdf_rl_nofl_err("Get elem unit info: Error %d", 658 ret); 659 return QDF_STATUS_E_FAILURE; 660 } 661 662 ret = wlan_get_elemsubelem_fragseq_creationparams(is_subelem, 663 id, 664 payloadlen, 665 &is_frag_required, 666 &expected_fragseqlen, 667 &prepayload_leadbytes, 668 &num_maxsizefrags, 669 &smallerfrag_size, 670 &extrahdrbytes); 671 if (QDF_IS_STATUS_ERROR(ret)) 672 return ret; 673 674 if (!is_frag_required) { 675 /* We treat this as an error since the caller is expected to 676 * have first determined requirements related to fragmentation, 677 * including whether fragmentation is required or not. 678 */ 679 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM)) 680 qdf_nofl_err("Fragmentation inapplicable for elem with elem ID ext and post elem ID ext payload len %zu", 681 payloadlen); 682 else 683 qdf_nofl_err("Fragmentation inapplicable for subelem/elem without elem ID ext and with payload len %zu", 684 payloadlen); 685 686 return QDF_STATUS_E_INVAL; 687 } 688 689 if (!payloadbuff) { 690 qdf_nofl_err("Payload buff is NULL"); 691 return QDF_STATUS_E_NULL_VALUE; 692 } 693 694 if (payloadbuff_maxsize == 0) { 695 qdf_nofl_err("Payload buff max size is 0"); 696 return QDF_STATUS_E_INVAL; 697 } 698 699 if (payloadbuff_maxsize < payloadlen) { 700 qdf_nofl_err("Payload buff max size %zu < payload len %zu", 701 payloadbuff_maxsize, 702 payloadlen); 703 return QDF_STATUS_E_INVAL; 704 } 705 706 if (inline_frag) { 707 if (payloadbuff_maxsize < expected_fragseqlen) { 708 qdf_nofl_err("Inline frag buff max size %zu < frag sequence expected len %zu", 709 payloadbuff_maxsize, 710 expected_fragseqlen); 711 return QDF_STATUS_E_INVAL; 712 } 713 } else { 714 if (!fragbuff) { 715 qdf_nofl_err("Frag sequence buff is NULL"); 716 return QDF_STATUS_E_NULL_VALUE; 717 } 718 719 if (fragbuff_maxsize == 0) { 720 qdf_nofl_err("Frag sequence buff max size is 0"); 721 return QDF_STATUS_E_INVAL; 722 } 723 724 if (fragbuff_maxsize < expected_fragseqlen) { 725 qdf_nofl_err("Frag sequence buff max size %zu < frag sequence expected len %zu", 726 fragbuff_maxsize, 727 expected_fragseqlen); 728 return QDF_STATUS_E_INVAL; 729 } 730 } 731 732 if (!fragseqlen) { 733 qdf_nofl_err("Pointer to location of frag sequence len is NULL"); 734 return QDF_STATUS_E_NULL_VALUE; 735 } 736 737 /* Preferably, ensure that error checks (if any) for future changes are 738 * executed before this point. We wouldn't want to touch the destination 739 * buffer unless we are sure we can successfully execute (especially for 740 * the inline mode). 741 */ 742 743 /* We rely on wlan_get_elemsubelem_fragseq_creationparams() to give us 744 * sane values for extrahdrbytes and other parameters. 745 */ 746 747 extrahdrbytes_remaining = extrahdrbytes; 748 749 /* We need to accommodate elemunit_hdrlen bytes for each non-leading 750 * fragment by moving the non-leading fragment to a higher location. 751 * Shift bytes and form fragment elements/subelements starting with the 752 * last fragment and going backwards from there. 753 */ 754 755 /* First move/copy the smaller sized fragment if present */ 756 if (smallerfrag_size) { 757 /* The source for the copy/move is just after the end of all the 758 * max sized fragments (including the lead fragment). The 759 * element unit header is present for the lead fragment alone. 760 */ 761 src = payloadbuff + elemunit_hdrlen + 762 (num_maxsizefrags * elemunit_maxpayloadlen); 763 764 /* The destination for the copy/move is computed to reflect a 765 * shift by extrahdrbytes_remaining to accommodate the headers 766 * for the smaller fragment and all the non-lead max sized 767 * fragments. 768 */ 769 if (inline_frag) 770 dst = src + extrahdrbytes_remaining; 771 else 772 dst = fragbuff + elemunit_hdrlen + 773 (num_maxsizefrags * elemunit_maxpayloadlen) + 774 extrahdrbytes_remaining; 775 776 bytes_to_transfer = smallerfrag_size; 777 778 /* Account for increased size due to shift in data */ 779 if (inline_frag && (dst > src)) 780 payloadbuff_shiftsize = (dst - src); 781 else 782 payloadbuff_shiftsize = 0; 783 784 /* In the case of inline fragmentation, if the payload buffer 785 * has additional contents beyond the payload, include those 786 * contents in the move/copy. 787 */ 788 if (inline_frag && 789 (payloadbuff_maxsize > (prepayload_leadbytes + payloadlen))) 790 bytes_to_transfer += (payloadbuff_maxsize - 791 prepayload_leadbytes - 792 payloadlen - 793 payloadbuff_shiftsize); 794 795 if (inline_frag) 796 qdf_mem_move(dst, src, bytes_to_transfer); 797 else 798 qdf_mem_copy(dst, src, bytes_to_transfer); 799 800 /* Copy/move of payload done. Set fragment ID and length in 801 * element unit header. 802 */ 803 curr_elemunit_ptr = dst - elemunit_hdrlen; 804 curr_elemunit_ptr[elemunit_id_pos] = elemunit_fragid; 805 curr_elemunit_ptr[elemunit_len_pos] = smallerfrag_size; 806 807 extrahdrbytes_remaining -= elemunit_hdrlen; 808 } 809 810 /* Next, move/copy the non-lead max-sized fragments, if present. 811 * Fragments at higher memory locations are processed first. 812 */ 813 for (i = num_maxsizefrags; i > 1; i--) { 814 /* Process the 'i'th max-sized fragment. The lead max-sized 815 * fragment has i=1 and is not processed in this 'for' loop. 816 * Also note that 'previous .* fragments' in comments for this 817 * 'for' loop refers to fragments in lower memory locations as 818 * compared to the current, i.e. 'i'th max-sized fragment. 819 */ 820 821 /* The source for the copy/move is just after the end of all the 822 * previous max-sized fragments (including the lead fragment). 823 * The element unit header is present for the lead fragment 824 * alone. 825 */ 826 src = payloadbuff + elemunit_hdrlen + 827 ((i - 1) * elemunit_maxpayloadlen); 828 829 /* The destination for the copy/move is computed to reflect a 830 * shift by extrahdrbytes_remaining to accommodate the headers 831 * for the current non-lead max-sized fragment and all the 832 * previous max-sized non-lead fragments. 833 */ 834 if (inline_frag) 835 dst = src + extrahdrbytes_remaining; 836 else 837 dst = fragbuff + elemunit_hdrlen + 838 ((i - 1) * elemunit_maxpayloadlen) + 839 extrahdrbytes_remaining; 840 841 bytes_to_transfer = elemunit_maxpayloadlen; 842 843 /* Account for increased size due to shift in data */ 844 if (inline_frag && (dst > src)) 845 payloadbuff_shiftsize = (dst - src); 846 else 847 payloadbuff_shiftsize = 0; 848 849 /* In the case of inline fragmentation, if this is the last 850 * non-lead max-sized fragment (i.e. at the highest memory 851 * location), if the payload buffer has additional contents 852 * beyond the payload, and these additional contents have not 853 * already been taken care of by the presence (and processing) 854 * of a smaller fragment, include the additional contents in the 855 * move/copy. 856 */ 857 if (inline_frag && 858 (i == num_maxsizefrags) && 859 (payloadbuff_maxsize > (prepayload_leadbytes + 860 payloadlen)) && 861 !smallerfrag_size) 862 bytes_to_transfer += (payloadbuff_maxsize - 863 prepayload_leadbytes - 864 payloadlen - 865 payloadbuff_shiftsize); 866 867 if (inline_frag) 868 qdf_mem_move(dst, src, bytes_to_transfer); 869 else 870 qdf_mem_copy(dst, src, bytes_to_transfer); 871 872 /* Copy/move of payload done. Set fragment ID and length in 873 * element unit header. 874 */ 875 curr_elemunit_ptr = dst - elemunit_hdrlen; 876 curr_elemunit_ptr[elemunit_id_pos] = elemunit_fragid; 877 curr_elemunit_ptr[elemunit_len_pos] = elemunit_maxpayloadlen; 878 879 extrahdrbytes_remaining -= elemunit_hdrlen; 880 } 881 882 /* Update the element unit pointer for the lead max-sized fragment. 883 * 884 * Copy the payload of the lead max-sized fragment if inline 885 * fragmentation is not being used. 886 */ 887 if (inline_frag) { 888 curr_elemunit_ptr = payloadbuff; 889 } else { 890 qdf_mem_copy(fragbuff + elemunit_hdrlen, 891 payloadbuff + elemunit_hdrlen, 892 elemunit_maxpayloadlen); 893 curr_elemunit_ptr = fragbuff; 894 } 895 896 /* Set IDs and length in the header for the leading fragment */ 897 curr_elemunit_ptr[elemunit_id_pos] = id; 898 curr_elemunit_ptr[elemunit_len_pos] = elemunit_maxpayloadlen; 899 if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM)) 900 curr_elemunit_ptr[elemunit_idext_pos] = idext; 901 902 *fragseqlen = expected_fragseqlen; 903 904 return QDF_STATUS_SUCCESS; 905 } 906 907 static inline QDF_STATUS 908 wlan_get_elemsubelem_successorfrag(bool is_subelem, 909 uint8_t subelemfragid, 910 uint8_t *curr_elemunit_ptr, 911 uint8_t *buff, 912 qdf_size_t buff_maxsize, 913 uint8_t **successorfrag, 914 qdf_size_t *successorfrag_totallen, 915 qdf_size_t *successorfrag_payloadlen) 916 { 917 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element 918 * or a 802.11 subelement. 919 */ 920 uint8_t elemunit_fragid; 921 qdf_size_t elemunit_hdrlen; 922 qdf_size_t elemunit_maxpayloadlen; 923 int elemunit_id_pos; 924 int elemunit_len_pos; 925 926 qdf_size_t curr_elemunit_totallen; 927 928 uint8_t *next_elemunit_ptr; 929 qdf_size_t next_elemunit_totallen; 930 931 QDF_STATUS ret; 932 933 /* This helper checks if the very next element unit after the current 934 * one is a valid fragment element unit and that there is sufficient 935 * space in the buffer for this next element, and if so, it returns a 936 * pointer to this fragment element unit as well as the total length of 937 * this fragment element unit and the length of the payload of this 938 * fragment element unit. 939 */ 940 941 ret = wlan_get_elemunit_info(is_subelem, 942 subelemfragid, 943 &elemunit_fragid, 944 &elemunit_hdrlen, 945 &elemunit_maxpayloadlen, 946 &elemunit_id_pos, 947 &elemunit_len_pos, 948 NULL); 949 if (QDF_IS_STATUS_ERROR(ret)) { 950 qdf_rl_nofl_err("Get elem unit info: Error %d", 951 ret); 952 return QDF_STATUS_E_FAILURE; 953 } 954 955 if (!curr_elemunit_ptr) { 956 qdf_nofl_err("Ptr to curr elem unit is NULL"); 957 return QDF_STATUS_E_NULL_VALUE; 958 } 959 960 if (!buff) { 961 qdf_nofl_err("Elem unit buff is NULL"); 962 return QDF_STATUS_E_NULL_VALUE; 963 } 964 965 if (buff_maxsize == 0) { 966 qdf_nofl_err("Max size of elem unit buff is 0"); 967 return QDF_STATUS_E_INVAL; 968 } 969 970 if (!successorfrag) { 971 qdf_nofl_err("Double ptr to successor frag is NULL"); 972 return QDF_STATUS_E_NULL_VALUE; 973 } 974 975 if (!successorfrag_totallen) { 976 qdf_nofl_err("Ptr to successor frag total len is NULL"); 977 return QDF_STATUS_E_NULL_VALUE; 978 } 979 980 if (!successorfrag_payloadlen) { 981 qdf_nofl_err("Ptr to successor frag payload len is NULL"); 982 return QDF_STATUS_E_NULL_VALUE; 983 } 984 985 if ((buff + buff_maxsize) < (curr_elemunit_ptr + elemunit_hdrlen)) { 986 qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (header size of elem unit %zu)", 987 buff_maxsize - (curr_elemunit_ptr - buff), 988 curr_elemunit_ptr - buff, 989 elemunit_hdrlen); 990 return QDF_STATUS_E_PROTO; 991 } 992 993 curr_elemunit_totallen = 994 elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos]; 995 996 if ((buff + buff_maxsize) < 997 (curr_elemunit_ptr + curr_elemunit_totallen)) { 998 qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (indicated total len of elem unit %zu)", 999 buff_maxsize - (curr_elemunit_ptr - buff), 1000 curr_elemunit_ptr - buff, 1001 curr_elemunit_totallen); 1002 return QDF_STATUS_E_PROTO; 1003 } 1004 1005 if ((buff + buff_maxsize) == 1006 (curr_elemunit_ptr + curr_elemunit_totallen)) { 1007 /* We have reached the end of the buffer. There is no successor 1008 * fragment. 1009 */ 1010 *successorfrag = NULL; 1011 return QDF_STATUS_SUCCESS; 1012 } 1013 1014 next_elemunit_ptr = curr_elemunit_ptr + curr_elemunit_totallen; 1015 1016 if ((buff + buff_maxsize) < (next_elemunit_ptr + elemunit_hdrlen)) { 1017 qdf_rl_nofl_err("(Space %zu after next elem unit offset %zu in elem unit buff) < (header size of elem unit %zu)", 1018 buff_maxsize - (next_elemunit_ptr - buff), 1019 next_elemunit_ptr - buff, 1020 elemunit_hdrlen); 1021 return QDF_STATUS_E_PROTO; 1022 } 1023 1024 next_elemunit_totallen = 1025 elemunit_hdrlen + next_elemunit_ptr[elemunit_len_pos]; 1026 1027 if ((buff + buff_maxsize) < 1028 (next_elemunit_ptr + next_elemunit_totallen)) { 1029 qdf_rl_nofl_err("(Space %zu after next elem unit offset %zu in elem unit buff) < (indicated total len of elem unit %zu)", 1030 buff_maxsize - (next_elemunit_ptr - buff), 1031 next_elemunit_ptr - buff, 1032 next_elemunit_totallen); 1033 return QDF_STATUS_E_PROTO; 1034 } 1035 1036 if (next_elemunit_ptr[elemunit_id_pos] != elemunit_fragid) { 1037 *successorfrag = NULL; 1038 return QDF_STATUS_SUCCESS; 1039 } 1040 1041 /* We should not be seeing a successor fragment if the length of the 1042 * current element unit is lesser than the max. 1043 */ 1044 if (curr_elemunit_ptr[elemunit_len_pos] != elemunit_maxpayloadlen) { 1045 qdf_rl_nofl_err("Potential successor frag found though (len %u of payload of curr elem unit) != (max payload len %zu)", 1046 curr_elemunit_ptr[elemunit_len_pos], 1047 elemunit_maxpayloadlen); 1048 return QDF_STATUS_E_PROTO; 1049 } 1050 1051 if (next_elemunit_ptr[elemunit_len_pos] == 0) { 1052 qdf_rl_nofl_err("Potential successor frag len is 0"); 1053 return QDF_STATUS_E_PROTO; 1054 } 1055 1056 *successorfrag = next_elemunit_ptr; 1057 *successorfrag_totallen = next_elemunit_totallen; 1058 *successorfrag_payloadlen = next_elemunit_ptr[elemunit_len_pos]; 1059 1060 return QDF_STATUS_SUCCESS; 1061 } 1062 1063 static QDF_STATUS 1064 wlan_get_elemsubelem_fragseq_info(bool is_subelem, 1065 uint8_t subelemfragid, 1066 uint8_t *buff, 1067 qdf_size_t buff_maxsize, 1068 bool *is_fragseq, 1069 qdf_size_t *fragseq_totallen, 1070 qdf_size_t *fragseq_payloadlen) 1071 { 1072 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element 1073 * or a 802.11 subelement. 1074 */ 1075 qdf_size_t elemunit_hdrlen; 1076 int elemunit_id_pos; 1077 int elemunit_len_pos; 1078 1079 uint8_t *curr_elemunit_ptr; 1080 qdf_size_t curr_elemunit_totallen; 1081 1082 qdf_size_t fragseq_currtotallen; 1083 qdf_size_t fragseq_currpayloadlen; 1084 1085 uint8_t *successorfrag; 1086 qdf_size_t successorfrag_totallen; 1087 qdf_size_t successorfrag_payloadlen; 1088 1089 QDF_STATUS ret; 1090 1091 /* Helper function to get element or subelement fragment sequence 1092 * information. Refer to the documentation of the public APIs which 1093 * call this helper, for more information. These APIs are mainly 1094 * wrappers over this helper. 1095 * 1096 * If this helper reports that an element fragment sequence is present, 1097 * it also serves to check for the sanity of various lengths and 1098 * protocol requirements related to the fragment sequence (either by 1099 * itself or though other helpers). 1100 */ 1101 1102 ret = wlan_get_elemunit_info(is_subelem, 1103 0, 1104 NULL, 1105 &elemunit_hdrlen, 1106 NULL, 1107 &elemunit_id_pos, 1108 &elemunit_len_pos, 1109 NULL); 1110 if (QDF_IS_STATUS_ERROR(ret)) { 1111 qdf_rl_nofl_err("Get elem unit info: Error %d", 1112 ret); 1113 return QDF_STATUS_E_FAILURE; 1114 } 1115 1116 if (!buff) { 1117 qdf_nofl_err("Elem unit buff is NULL"); 1118 return QDF_STATUS_E_NULL_VALUE; 1119 } 1120 1121 if (buff_maxsize == 0) { 1122 qdf_nofl_err("Max size of elem unit buff is 0"); 1123 return QDF_STATUS_E_INVAL; 1124 } 1125 1126 if (!is_fragseq) { 1127 qdf_nofl_err("Ptr to status of frag seq presence is NULL"); 1128 return QDF_STATUS_E_NULL_VALUE; 1129 } 1130 1131 if (!fragseq_totallen) { 1132 qdf_nofl_err("Ptr to total len of frag seq is NULL"); 1133 return QDF_STATUS_E_NULL_VALUE; 1134 } 1135 1136 if (!fragseq_payloadlen) { 1137 qdf_nofl_err("Ptr to payload len of frag seq is NULL"); 1138 return QDF_STATUS_E_NULL_VALUE; 1139 } 1140 1141 curr_elemunit_ptr = buff; 1142 fragseq_currtotallen = 0; 1143 fragseq_currpayloadlen = 0; 1144 1145 if ((buff + buff_maxsize) < (curr_elemunit_ptr + elemunit_hdrlen)) { 1146 qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (header size of elem unit %zu)", 1147 buff_maxsize - (curr_elemunit_ptr - buff), 1148 curr_elemunit_ptr - buff, 1149 elemunit_hdrlen); 1150 return QDF_STATUS_E_PROTO; 1151 } 1152 1153 curr_elemunit_totallen = 1154 elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos]; 1155 1156 if ((buff + buff_maxsize) < 1157 (curr_elemunit_ptr + curr_elemunit_totallen)) { 1158 qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (indicated total len of elem unit %zu)", 1159 buff_maxsize - (curr_elemunit_ptr - buff), 1160 curr_elemunit_ptr - buff, 1161 curr_elemunit_totallen); 1162 return QDF_STATUS_E_PROTO; 1163 } 1164 1165 successorfrag = NULL; 1166 1167 ret = wlan_get_elemsubelem_successorfrag(is_subelem, 1168 subelemfragid, 1169 curr_elemunit_ptr, 1170 buff, 1171 buff_maxsize, 1172 &successorfrag, 1173 &successorfrag_totallen, 1174 &successorfrag_payloadlen); 1175 if (QDF_IS_STATUS_ERROR(ret)) 1176 return ret; 1177 1178 if (!successorfrag) { 1179 *is_fragseq = false; 1180 *fragseq_totallen = 0; 1181 *fragseq_payloadlen = 0; 1182 return QDF_STATUS_SUCCESS; 1183 } 1184 1185 fragseq_currtotallen += curr_elemunit_totallen; 1186 1187 if (!is_subelem && 1188 (curr_elemunit_ptr[elemunit_id_pos] == WLAN_ELEMID_EXTN_ELEM)) { 1189 fragseq_currpayloadlen += 1190 (curr_elemunit_ptr[elemunit_len_pos] - 1); 1191 } else { 1192 fragseq_currpayloadlen += 1193 curr_elemunit_ptr[elemunit_len_pos]; 1194 } 1195 1196 while (successorfrag) { 1197 /* wlan_get_elemsubelem_successorfrag() has already validated 1198 * the length values for the successor fragment. 1199 */ 1200 fragseq_currtotallen += successorfrag_totallen; 1201 fragseq_currpayloadlen += successorfrag_payloadlen; 1202 1203 curr_elemunit_ptr = successorfrag; 1204 successorfrag = NULL; 1205 1206 ret = wlan_get_elemsubelem_successorfrag(is_subelem, 1207 subelemfragid, 1208 curr_elemunit_ptr, 1209 buff, 1210 buff_maxsize, 1211 &successorfrag, 1212 &successorfrag_totallen, 1213 &successorfrag_payloadlen); 1214 if (QDF_IS_STATUS_ERROR(ret)) 1215 return ret; 1216 } 1217 1218 *is_fragseq = true; 1219 *fragseq_totallen = fragseq_currtotallen; 1220 *fragseq_payloadlen = fragseq_currpayloadlen; 1221 1222 return QDF_STATUS_SUCCESS; 1223 } 1224 1225 static QDF_STATUS wlan_defrag_elemsubelem_fragseq(bool inline_defrag, 1226 bool is_subelem, 1227 uint8_t subelemfragid, 1228 uint8_t *fragbuff, 1229 qdf_size_t fragbuff_maxsize, 1230 uint8_t *defragbuff, 1231 qdf_size_t defragbuff_maxsize, 1232 qdf_size_t *defragpayload_len) 1233 { 1234 /* elemunit, i.e. 'element unit' here refers to either an 802.11 element 1235 * or a 802.11 subelement. 1236 */ 1237 uint8_t elemunit_fragid; 1238 qdf_size_t elemunit_hdrlen; 1239 int elemunit_id_pos; 1240 int elemunit_len_pos; 1241 int elemunit_idext_pos; 1242 1243 bool is_fragseq; 1244 qdf_size_t fragseq_totallen; 1245 qdf_size_t fragseq_payloadlen; 1246 1247 uint8_t *curr_elemunit_ptr; 1248 qdf_size_t curr_elemunit_payloadlen; 1249 qdf_size_t curr_elemunit_totallen; 1250 1251 uint8_t *src; 1252 uint8_t *dst; 1253 1254 /* Current length of the defragmented payload */ 1255 qdf_size_t defragpayload_currlen; 1256 1257 /* Remaining length available in the source buffer containing the 1258 * fragment sequence, after element units processed so far. 1259 */ 1260 qdf_size_t fragbuff_remlen; 1261 1262 QDF_STATUS ret; 1263 1264 /* Helper function to de-fragment element or subelement fragment 1265 * sequence. Refer to the documentation of the public APIs which call 1266 * this helper, for more information. Those APIs are mainly wrappers 1267 * over this helper. 1268 */ 1269 1270 ret = wlan_get_elemunit_info(is_subelem, 1271 subelemfragid, 1272 &elemunit_fragid, 1273 &elemunit_hdrlen, 1274 NULL, 1275 &elemunit_id_pos, 1276 &elemunit_len_pos, 1277 &elemunit_idext_pos); 1278 if (QDF_IS_STATUS_ERROR(ret)) { 1279 qdf_rl_nofl_err("Get elem unit info: Error %d", 1280 ret); 1281 return QDF_STATUS_E_FAILURE; 1282 } 1283 1284 if (!fragbuff) { 1285 qdf_nofl_err("Src buff for frag seq is NULL"); 1286 return QDF_STATUS_E_NULL_VALUE; 1287 } 1288 1289 if (fragbuff_maxsize == 0) { 1290 qdf_nofl_err("Size of src buff for frag seq is 0"); 1291 return QDF_STATUS_E_INVAL; 1292 } 1293 1294 if (!inline_defrag) { 1295 if (!defragbuff) { 1296 qdf_nofl_err("Dest buff for defragged payload is NULL"); 1297 return QDF_STATUS_E_NULL_VALUE; 1298 } 1299 1300 if (defragbuff_maxsize == 0) { 1301 qdf_nofl_err("Size of dest buff for defragged payload is 0"); 1302 return QDF_STATUS_E_INVAL; 1303 } 1304 } 1305 1306 if (!defragpayload_len) { 1307 qdf_nofl_err("Ptr to len of defragged payload is NULL"); 1308 return QDF_STATUS_E_NULL_VALUE; 1309 } 1310 1311 ret = wlan_get_elemsubelem_fragseq_info(is_subelem, 1312 subelemfragid, 1313 fragbuff, 1314 fragbuff_maxsize, 1315 &is_fragseq, 1316 &fragseq_totallen, 1317 &fragseq_payloadlen); 1318 if (QDF_IS_STATUS_ERROR(ret)) 1319 return ret; 1320 1321 if (!is_fragseq) { 1322 /* We treat this as an error since the caller is supposed to 1323 * check this. 1324 */ 1325 qdf_rl_nofl_err("Frag seq not found at start of src buff for frag seq"); 1326 return QDF_STATUS_E_INVAL; 1327 } 1328 1329 /* fragseq_totallen is known to be smaller than or equal to 1330 * fragbuff_maxsize since wlan_get_elemsubelem_fragseq_info() is bound 1331 * by fragbuff_maxsize in the search for a fragment sequence and it's 1332 * total length. 1333 */ 1334 1335 if (!inline_defrag && (defragbuff_maxsize < fragseq_payloadlen)) { 1336 qdf_rl_nofl_err("(Size of dest buff for defragged payload %zu) < (size of frag seq payload %zu)", 1337 defragbuff_maxsize, fragseq_payloadlen); 1338 return QDF_STATUS_E_INVAL; 1339 } 1340 1341 defragpayload_currlen = 0; 1342 fragbuff_remlen = fragbuff_maxsize; 1343 1344 /* We have already validated through wlan_get_elemsubelem_fragseq_info() 1345 * that the elements we are about to access below are within the bounds 1346 * of fragbuff. 1347 */ 1348 1349 curr_elemunit_ptr = fragbuff; 1350 1351 if (!is_subelem && 1352 (curr_elemunit_ptr[elemunit_id_pos] == WLAN_ELEMID_EXTN_ELEM)) { 1353 curr_elemunit_payloadlen = 1354 curr_elemunit_ptr[elemunit_len_pos] - 1; 1355 src = curr_elemunit_ptr + elemunit_hdrlen + 1; 1356 } else { 1357 curr_elemunit_payloadlen = curr_elemunit_ptr[elemunit_len_pos]; 1358 src = curr_elemunit_ptr + elemunit_hdrlen; 1359 } 1360 1361 curr_elemunit_totallen = 1362 elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos]; 1363 1364 if (inline_defrag) { 1365 /* There is no need to move any bytes in the lead element. Set 1366 * dst=src so that the next update for dst can happen in a 1367 * manner uniform with the non-inlined defrag case. 1368 */ 1369 dst = src; 1370 } else { 1371 dst = defragbuff; 1372 qdf_mem_copy(dst, src, curr_elemunit_payloadlen); 1373 } 1374 1375 defragpayload_currlen += curr_elemunit_payloadlen; 1376 1377 fragbuff_remlen -= curr_elemunit_totallen; 1378 1379 dst += curr_elemunit_payloadlen; 1380 1381 curr_elemunit_ptr += curr_elemunit_totallen; 1382 1383 /* We have already validated through wlan_get_elemsubelem_fragseq_info() 1384 * that at least one non-lead fragment element is present as required in 1385 * the standard. 1386 */ 1387 while (curr_elemunit_ptr[elemunit_id_pos] == elemunit_fragid) { 1388 curr_elemunit_payloadlen = curr_elemunit_ptr[elemunit_len_pos]; 1389 curr_elemunit_totallen = 1390 elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos]; 1391 src = curr_elemunit_ptr + elemunit_hdrlen; 1392 1393 if (inline_defrag) 1394 qdf_mem_move(dst, src, curr_elemunit_payloadlen); 1395 else 1396 qdf_mem_copy(dst, src, curr_elemunit_payloadlen); 1397 1398 defragpayload_currlen += curr_elemunit_payloadlen; 1399 1400 fragbuff_remlen -= curr_elemunit_totallen; 1401 1402 if (fragbuff_remlen == 0) 1403 break; 1404 1405 dst += curr_elemunit_payloadlen; 1406 1407 curr_elemunit_ptr += curr_elemunit_totallen; 1408 } 1409 1410 if (inline_defrag && (fragbuff_remlen != 0)) { 1411 /* Move the residual content after the fragments, in the source 1412 * buffer. 1413 */ 1414 src = curr_elemunit_ptr; 1415 qdf_mem_move(dst, src, fragbuff_remlen); 1416 } 1417 1418 *defragpayload_len = defragpayload_currlen; 1419 1420 return QDF_STATUS_SUCCESS; 1421 } 1422 1423 QDF_STATUS 1424 wlan_get_elem_fragseq_requirements(uint8_t elemid, 1425 qdf_size_t payloadlen, 1426 bool *is_frag_required, 1427 qdf_size_t *required_fragbuff_size) 1428 { 1429 return wlan_get_elemsubelem_fragseq_creationparams(false, 1430 elemid, 1431 payloadlen, 1432 is_frag_required, 1433 required_fragbuff_size, 1434 NULL, 1435 NULL, 1436 NULL, 1437 NULL); 1438 } 1439 1440 QDF_STATUS wlan_create_elem_fragseq(bool inline_frag, 1441 uint8_t elemid, 1442 uint8_t elemidext, 1443 uint8_t *payloadbuff, 1444 qdf_size_t payloadbuff_maxsize, 1445 qdf_size_t payloadlen, 1446 uint8_t *fragbuff, 1447 qdf_size_t fragbuff_maxsize, 1448 qdf_size_t *fragseqlen) 1449 { 1450 return wlan_create_elemsubelem_fragseq(inline_frag, 1451 false, 1452 elemid, 1453 elemidext, 1454 0, 1455 payloadbuff, 1456 payloadbuff_maxsize, 1457 payloadlen, 1458 fragbuff, 1459 fragbuff_maxsize, 1460 fragseqlen); 1461 } 1462 1463 QDF_STATUS 1464 wlan_get_subelem_fragseq_requirements(uint8_t subelemid, 1465 qdf_size_t payloadlen, 1466 bool *is_frag_required, 1467 qdf_size_t *required_fragbuff_size) 1468 { 1469 return wlan_get_elemsubelem_fragseq_creationparams(true, 1470 subelemid, 1471 payloadlen, 1472 is_frag_required, 1473 required_fragbuff_size, 1474 NULL, 1475 NULL, 1476 NULL, 1477 NULL); 1478 } 1479 1480 QDF_STATUS wlan_create_subelem_fragseq(bool inline_frag, 1481 uint8_t subelemid, 1482 uint8_t subelemfragid, 1483 uint8_t *payloadbuff, 1484 qdf_size_t payloadbuff_maxsize, 1485 qdf_size_t payloadlen, 1486 uint8_t *fragbuff, 1487 qdf_size_t fragbuff_maxsize, 1488 qdf_size_t *fragseqlen) 1489 { 1490 return wlan_create_elemsubelem_fragseq(inline_frag, 1491 true, 1492 subelemid, 1493 0, 1494 subelemfragid, 1495 payloadbuff, 1496 payloadbuff_maxsize, 1497 payloadlen, 1498 fragbuff, 1499 fragbuff_maxsize, 1500 fragseqlen); 1501 } 1502 1503 QDF_STATUS wlan_get_elem_fragseq_info(uint8_t *elembuff, 1504 qdf_size_t elembuff_maxsize, 1505 bool *is_fragseq, 1506 qdf_size_t *fragseq_totallen, 1507 qdf_size_t *fragseq_payloadlen) 1508 { 1509 return wlan_get_elemsubelem_fragseq_info(false, 1510 0, 1511 elembuff, 1512 elembuff_maxsize, 1513 is_fragseq, 1514 fragseq_totallen, 1515 fragseq_payloadlen); 1516 } 1517 1518 QDF_STATUS wlan_defrag_elem_fragseq(bool inline_defrag, 1519 uint8_t *fragbuff, 1520 qdf_size_t fragbuff_maxsize, 1521 uint8_t *defragbuff, 1522 qdf_size_t defragbuff_maxsize, 1523 qdf_size_t *defragpayload_len) 1524 { 1525 return wlan_defrag_elemsubelem_fragseq(inline_defrag, 1526 false, 1527 0, 1528 fragbuff, 1529 fragbuff_maxsize, 1530 defragbuff, 1531 defragbuff_maxsize, 1532 defragpayload_len); 1533 } 1534 1535 QDF_STATUS wlan_get_subelem_fragseq_info(uint8_t subelemfragid, 1536 uint8_t *subelembuff, 1537 qdf_size_t subelembuff_maxsize, 1538 bool *is_fragseq, 1539 qdf_size_t *fragseq_totallen, 1540 qdf_size_t *fragseq_payloadlen) 1541 { 1542 return wlan_get_elemsubelem_fragseq_info(true, 1543 subelemfragid, 1544 subelembuff, 1545 subelembuff_maxsize, 1546 is_fragseq, 1547 fragseq_totallen, 1548 fragseq_payloadlen); 1549 } 1550 1551 QDF_STATUS wlan_defrag_subelem_fragseq(bool inline_defrag, 1552 uint8_t subelemfragid, 1553 uint8_t *fragbuff, 1554 qdf_size_t fragbuff_maxsize, 1555 uint8_t *defragbuff, 1556 qdf_size_t defragbuff_maxsize, 1557 qdf_size_t *defragpayload_len) 1558 { 1559 return wlan_defrag_elemsubelem_fragseq(inline_defrag, 1560 true, 1561 subelemfragid, 1562 fragbuff, 1563 fragbuff_maxsize, 1564 defragbuff, 1565 defragbuff_maxsize, 1566 defragpayload_len); 1567 } 1568 1569 bool wlan_is_emulation_platform(uint32_t phy_version) 1570 { 1571 if ((phy_version == 0xABC0) || (phy_version == 0xABC1) || 1572 (phy_version == 0xABC2) || (phy_version == 0xABC3) || 1573 (phy_version == 0xFFFF) || (phy_version == 0xABCD)) 1574 return true; 1575 1576 return false; 1577 } 1578 1579 uint32_t wlan_get_pdev_id_from_vdev_id(struct wlan_objmgr_psoc *psoc, 1580 uint8_t vdev_id, 1581 wlan_objmgr_ref_dbgid dbg_id) 1582 { 1583 struct wlan_objmgr_vdev *vdev; 1584 struct wlan_objmgr_pdev *pdev = NULL; 1585 uint32_t pdev_id = WLAN_INVALID_PDEV_ID; 1586 1587 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, 1588 vdev_id, dbg_id); 1589 1590 if (vdev) { 1591 pdev = wlan_vdev_get_pdev(vdev); 1592 if (pdev) 1593 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1594 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 1595 } 1596 1597 return pdev_id; 1598 } 1599 qdf_export_symbol(wlan_get_pdev_id_from_vdev_id); 1600 1601 static void wlan_vdev_active(struct wlan_objmgr_pdev *pdev, void *object, 1602 void *arg) 1603 { 1604 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 1605 uint8_t *flag = (uint8_t *)arg; 1606 1607 wlan_vdev_obj_lock(vdev); 1608 if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS) 1609 *flag = 1; 1610 1611 wlan_vdev_obj_unlock(vdev); 1612 } 1613 1614 QDF_STATUS wlan_vdev_is_up(struct wlan_objmgr_vdev *vdev) 1615 { 1616 return wlan_vdev_allow_connect_n_tx(vdev); 1617 } 1618 qdf_export_symbol(wlan_vdev_is_up); 1619 1620 QDF_STATUS wlan_util_is_vdev_active(struct wlan_objmgr_pdev *pdev, 1621 wlan_objmgr_ref_dbgid dbg_id) 1622 { 1623 uint8_t flag = 0; 1624 1625 if (!pdev) 1626 return QDF_STATUS_E_INVAL; 1627 1628 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, wlan_vdev_active, 1629 &flag, 0, dbg_id); 1630 1631 if (flag == 1) 1632 return QDF_STATUS_SUCCESS; 1633 1634 return QDF_STATUS_E_INVAL; 1635 } 1636 1637 qdf_export_symbol(wlan_util_is_vdev_active); 1638 1639 void wlan_util_change_map_index(unsigned long *map, uint8_t id, uint8_t set) 1640 { 1641 if (set) 1642 qdf_set_bit(id, map); 1643 else 1644 qdf_clear_bit(id, map); 1645 } 1646 1647 bool wlan_util_map_index_is_set(unsigned long *map, uint8_t id) 1648 { 1649 return qdf_test_bit(id, map); 1650 } 1651 1652 bool wlan_util_map_is_any_index_set(unsigned long *map, unsigned long nbytes) 1653 { 1654 return !qdf_bitmap_empty(map, QDF_CHAR_BIT * nbytes); 1655 } 1656 1657 static void wlan_vdev_chan_change_pending(struct wlan_objmgr_pdev *pdev, 1658 void *object, void *arg) 1659 { 1660 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 1661 unsigned long *vdev_id_map = (unsigned long *)arg; 1662 uint8_t id = 0; 1663 struct wlan_objmgr_psoc *psoc; 1664 1665 psoc = wlan_pdev_get_psoc(pdev); 1666 if (!psoc) 1667 return; 1668 1669 wlan_vdev_obj_lock(vdev); 1670 if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) { 1671 id = wlan_vdev_get_id(vdev); 1672 /* Invalid vdev id */ 1673 if (id >= wlan_psoc_get_max_vdev_count(psoc)) { 1674 wlan_vdev_obj_unlock(vdev); 1675 return; 1676 } 1677 1678 wlan_util_change_map_index(vdev_id_map, id, 1); 1679 } 1680 1681 wlan_vdev_obj_unlock(vdev); 1682 } 1683 1684 QDF_STATUS wlan_pdev_chan_change_pending_vdevs(struct wlan_objmgr_pdev *pdev, 1685 unsigned long *vdev_id_map, 1686 wlan_objmgr_ref_dbgid dbg_id) 1687 { 1688 if (!pdev) 1689 return QDF_STATUS_E_INVAL; 1690 1691 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 1692 wlan_vdev_chan_change_pending, 1693 vdev_id_map, 0, dbg_id); 1694 1695 return QDF_STATUS_SUCCESS; 1696 } 1697 1698 static void wlan_vdev_down_pending(struct wlan_objmgr_pdev *pdev, 1699 void *object, void *arg) 1700 { 1701 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 1702 unsigned long *vdev_id_map = (unsigned long *)arg; 1703 uint8_t id = 0; 1704 struct wlan_objmgr_psoc *psoc; 1705 enum wlan_serialization_cmd_type cmd_type; 1706 1707 psoc = wlan_pdev_get_psoc(pdev); 1708 if (!psoc) 1709 return; 1710 1711 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) 1712 return; 1713 1714 cmd_type = wlan_serialization_get_vdev_active_cmd_type(vdev); 1715 wlan_vdev_obj_lock(vdev); 1716 if ((wlan_vdev_mlme_is_init_state(vdev) != QDF_STATUS_SUCCESS) || 1717 (cmd_type == WLAN_SER_CMD_VDEV_START_BSS)) { 1718 id = wlan_vdev_get_id(vdev); 1719 /* Invalid vdev id */ 1720 if (id >= wlan_psoc_get_max_vdev_count(psoc)) { 1721 wlan_vdev_obj_unlock(vdev); 1722 return; 1723 } 1724 wlan_util_change_map_index(vdev_id_map, id, 1); 1725 } 1726 1727 wlan_vdev_obj_unlock(vdev); 1728 } 1729 1730 static void wlan_vdev_ap_down_pending(struct wlan_objmgr_pdev *pdev, 1731 void *object, void *arg) 1732 { 1733 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 1734 unsigned long *vdev_id_map = (unsigned long *)arg; 1735 uint8_t id = 0; 1736 struct wlan_objmgr_psoc *psoc; 1737 enum wlan_serialization_cmd_type cmd_type; 1738 1739 psoc = wlan_pdev_get_psoc(pdev); 1740 if (!psoc) 1741 return; 1742 1743 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE) 1744 return; 1745 1746 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) 1747 return; 1748 1749 cmd_type = wlan_serialization_get_vdev_active_cmd_type(vdev); 1750 wlan_vdev_obj_lock(vdev); 1751 if ((wlan_vdev_mlme_is_init_state(vdev) != QDF_STATUS_SUCCESS) || 1752 (cmd_type == WLAN_SER_CMD_VDEV_START_BSS)) { 1753 id = wlan_vdev_get_id(vdev); 1754 /* Invalid vdev id */ 1755 if (id >= wlan_psoc_get_max_vdev_count(psoc)) { 1756 wlan_vdev_obj_unlock(vdev); 1757 return; 1758 } 1759 wlan_util_change_map_index(vdev_id_map, id, 1); 1760 } 1761 1762 wlan_vdev_obj_unlock(vdev); 1763 } 1764 1765 QDF_STATUS wlan_pdev_chan_change_pending_vdevs_down( 1766 struct wlan_objmgr_pdev *pdev, 1767 unsigned long *vdev_id_map, 1768 wlan_objmgr_ref_dbgid dbg_id) 1769 { 1770 if (!pdev) 1771 return QDF_STATUS_E_INVAL; 1772 1773 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 1774 wlan_vdev_down_pending, 1775 vdev_id_map, 0, dbg_id); 1776 1777 return QDF_STATUS_SUCCESS; 1778 } 1779 1780 QDF_STATUS wlan_pdev_chan_change_pending_ap_vdevs_down( 1781 struct wlan_objmgr_pdev *pdev, 1782 unsigned long *vdev_id_map, 1783 wlan_objmgr_ref_dbgid dbg_id) 1784 { 1785 if (!pdev) 1786 return QDF_STATUS_E_INVAL; 1787 1788 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 1789 wlan_vdev_ap_down_pending, 1790 vdev_id_map, 0, dbg_id); 1791 1792 return QDF_STATUS_SUCCESS; 1793 } 1794 1795 #ifdef WLAN_FEATURE_11BE 1796 static inline bool 1797 wlan_chan_puncture_eq(struct wlan_channel *chan1, struct wlan_channel *chan2) 1798 { 1799 if (chan1->puncture_bitmap == chan2->puncture_bitmap) 1800 return true; 1801 1802 return false; 1803 } 1804 #else 1805 static inline bool 1806 wlan_chan_puncture_eq(struct wlan_channel *chan1, struct wlan_channel *chan2) 1807 { 1808 return true; 1809 } 1810 #endif /* WLAN_FEATURE_11BE */ 1811 1812 QDF_STATUS wlan_chan_eq(struct wlan_channel *chan1, struct wlan_channel *chan2) 1813 { 1814 if ((chan1->ch_ieee == chan2->ch_ieee) && 1815 (chan1->ch_freq_seg2 == chan2->ch_freq_seg2) && 1816 wlan_chan_puncture_eq(chan1, chan2)) 1817 return QDF_STATUS_SUCCESS; 1818 1819 return QDF_STATUS_E_FAILURE; 1820 } 1821 1822 void wlan_chan_copy(struct wlan_channel *tgt, struct wlan_channel *src) 1823 { 1824 qdf_mem_copy(tgt, src, sizeof(struct wlan_channel)); 1825 } 1826 1827 struct wlan_channel *wlan_vdev_get_active_channel(struct wlan_objmgr_vdev *vdev) 1828 { 1829 struct wlan_channel *comp_vdev_chan = NULL; 1830 1831 if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) { 1832 /* compare with BSS channel, when vdev is active, since desired 1833 * channel gets update, if channel is triggered in another path 1834 */ 1835 if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS) 1836 comp_vdev_chan = wlan_vdev_mlme_get_bss_chan(vdev); 1837 else 1838 comp_vdev_chan = wlan_vdev_mlme_get_des_chan(vdev); 1839 } 1840 1841 return comp_vdev_chan; 1842 } 1843 1844 /** 1845 * struct wlan_check_bssid_context - bssid check context 1846 * @bssid: bssid to be checked 1847 * @connected: connected by vdev or not 1848 * @vdev_id: vdev id of connected vdev 1849 */ 1850 struct wlan_check_bssid_context { 1851 struct qdf_mac_addr bssid; 1852 bool connected; 1853 uint8_t vdev_id; 1854 }; 1855 1856 /** 1857 * wlan_get_connected_vdev_handler() - check vdev connected on bssid 1858 * @psoc: psoc object 1859 * @obj: vdev object 1860 * @args: handler context 1861 * 1862 * This function will check whether vdev is connected on bssid or not and 1863 * update the result to handler context accordingly. 1864 * 1865 * Return: void 1866 */ 1867 static void wlan_get_connected_vdev_handler(struct wlan_objmgr_psoc *psoc, 1868 void *obj, void *args) 1869 { 1870 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj; 1871 struct wlan_check_bssid_context *context = 1872 (struct wlan_check_bssid_context *)args; 1873 struct qdf_mac_addr bss_peer_mac; 1874 enum QDF_OPMODE op_mode; 1875 1876 if (context->connected) 1877 return; 1878 1879 op_mode = wlan_vdev_mlme_get_opmode(vdev); 1880 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) 1881 return; 1882 1883 if (wlan_cm_is_vdev_disconnected(vdev)) 1884 return; 1885 1886 if (wlan_vdev_get_bss_peer_mac(vdev, &bss_peer_mac) != 1887 QDF_STATUS_SUCCESS) 1888 return; 1889 if (qdf_is_macaddr_equal(&bss_peer_mac, &context->bssid)) { 1890 context->connected = true; 1891 context->vdev_id = wlan_vdev_get_id(vdev); 1892 } 1893 } 1894 1895 bool wlan_get_connected_vdev_from_psoc_by_bssid(struct wlan_objmgr_psoc *psoc, 1896 uint8_t *bssid, 1897 uint8_t *vdev_id) 1898 { 1899 struct wlan_check_bssid_context context; 1900 1901 qdf_mem_zero(&context, sizeof(struct wlan_check_bssid_context)); 1902 qdf_mem_copy(context.bssid.bytes, bssid, QDF_MAC_ADDR_SIZE); 1903 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 1904 wlan_get_connected_vdev_handler, 1905 &context, true, WLAN_OSIF_SCAN_ID); 1906 if (context.connected) 1907 *vdev_id = context.vdev_id; 1908 1909 return context.connected; 1910 } 1911 1912 qdf_export_symbol(wlan_get_connected_vdev_from_psoc_by_bssid); 1913 1914 bool wlan_get_connected_vdev_by_bssid(struct wlan_objmgr_pdev *pdev, 1915 uint8_t *bssid, uint8_t *vdev_id) 1916 { 1917 return wlan_get_connected_vdev_from_psoc_by_bssid( 1918 wlan_pdev_get_psoc(pdev), bssid, vdev_id); 1919 } 1920 1921 qdf_export_symbol(wlan_get_connected_vdev_by_bssid); 1922 1923 #ifdef WLAN_FEATURE_11BE_MLO 1924 /** 1925 * struct wlan_check_mld_addr_context - mld mac addr check context 1926 * @mld_addr: mld_addrto be checked 1927 * @connected: connected by vdev or not 1928 * @vdev_id: vdev id of connected vdev 1929 */ 1930 struct wlan_check_mld_addr_context { 1931 struct qdf_mac_addr mld_addr; 1932 bool connected; 1933 uint8_t vdev_id; 1934 }; 1935 1936 /** 1937 * wlan_get_connected_mlo_dev_ctx_handler() - check vdev connected on mld mac 1938 * @psoc: psoc object 1939 * @obj: vdev object 1940 * @args: handler context 1941 * 1942 * This function will check whether vdev is connected on mld mac or not and 1943 * update the result to handler context accordingly. 1944 * 1945 * Return: void 1946 */ 1947 static void wlan_get_connected_mlo_dev_ctx_handler( 1948 struct wlan_objmgr_psoc *psoc, 1949 void *obj, void *args) 1950 { 1951 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj; 1952 struct wlan_check_mld_addr_context *context = 1953 (struct wlan_check_mld_addr_context *)args; 1954 struct qdf_mac_addr bss_peer_mld_mac; 1955 enum QDF_OPMODE op_mode; 1956 1957 if (context->connected) 1958 return; 1959 op_mode = wlan_vdev_mlme_get_opmode(vdev); 1960 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) 1961 return; 1962 if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS) 1963 return; 1964 if (QDF_IS_STATUS_ERROR(wlan_vdev_get_bss_peer_mld_mac( 1965 vdev, &bss_peer_mld_mac))) 1966 return; 1967 if (qdf_is_macaddr_equal(&bss_peer_mld_mac, &context->mld_addr)) { 1968 context->connected = true; 1969 context->vdev_id = wlan_vdev_get_id(vdev); 1970 } 1971 } 1972 1973 bool wlan_get_connected_vdev_by_mld_addr(struct wlan_objmgr_psoc *psoc, 1974 uint8_t *mld_mac, uint8_t *vdev_id) 1975 { 1976 struct wlan_check_mld_addr_context context; 1977 1978 qdf_mem_zero(&context, sizeof(struct wlan_check_mld_addr_context)); 1979 qdf_copy_macaddr(&context.mld_addr, (struct qdf_mac_addr *)mld_mac); 1980 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 1981 wlan_get_connected_mlo_dev_ctx_handler, 1982 &context, true, WLAN_MLME_OBJMGR_ID); 1983 1984 if (context.connected) 1985 *vdev_id = context.vdev_id; 1986 1987 return context.connected; 1988 } 1989 #endif 1990 1991 #if defined(WLAN_FEATURE_11BE) 1992 enum wlan_phymode 1993 wlan_eht_chan_phy_mode(uint32_t freq, 1994 uint16_t bw_val, 1995 enum phy_ch_width chan_width) 1996 { 1997 if (wlan_reg_is_24ghz_ch_freq(freq)) { 1998 if (bw_val == 20) 1999 return WLAN_PHYMODE_11BEG_EHT20; 2000 else if (bw_val == 40) 2001 return WLAN_PHYMODE_11BEG_EHT40; 2002 } else { 2003 if (bw_val == 20) 2004 return WLAN_PHYMODE_11BEA_EHT20; 2005 else if (bw_val == 40) 2006 return WLAN_PHYMODE_11BEA_EHT40; 2007 else if (bw_val == 80) 2008 return WLAN_PHYMODE_11BEA_EHT80; 2009 else if (chan_width == CH_WIDTH_160MHZ) 2010 return WLAN_PHYMODE_11BEA_EHT160; 2011 else if (chan_width == CH_WIDTH_320MHZ) 2012 return WLAN_PHYMODE_11BEA_EHT320; 2013 } 2014 return WLAN_PHYMODE_AUTO; 2015 } 2016 #else 2017 enum wlan_phymode 2018 wlan_eht_chan_phy_mode(uint32_t freq, 2019 uint16_t bw_val, 2020 enum phy_ch_width chan_width) 2021 { 2022 return WLAN_PHYMODE_AUTO; 2023 } 2024 2025 #endif 2026 2027 static void wlan_pdev_chan_match(struct wlan_objmgr_pdev *pdev, void *object, 2028 void *arg) 2029 { 2030 struct wlan_objmgr_vdev *comp_vdev = (struct wlan_objmgr_vdev *)object; 2031 struct wlan_vdev_ch_check_filter *ch_filter = arg; 2032 struct wlan_channel vdev_chan, *chan; 2033 struct wlan_channel *iter_vdev_chan; 2034 2035 if (ch_filter->flag) 2036 return; 2037 2038 if (comp_vdev == ch_filter->vdev) 2039 return; 2040 2041 wlan_vdev_obj_lock(comp_vdev); 2042 chan = wlan_vdev_get_active_channel(comp_vdev); 2043 if (!chan) { 2044 wlan_vdev_obj_unlock(comp_vdev); 2045 return; 2046 } 2047 wlan_chan_copy(&vdev_chan, chan); 2048 wlan_vdev_obj_unlock(comp_vdev); 2049 2050 wlan_vdev_obj_lock(ch_filter->vdev); 2051 iter_vdev_chan = wlan_vdev_mlme_get_des_chan(ch_filter->vdev); 2052 if (wlan_chan_eq(&vdev_chan, iter_vdev_chan) 2053 != QDF_STATUS_SUCCESS) { 2054 ch_filter->flag = 1; 2055 qdf_debug("==> iter vdev id: %d: ieee %d, mode %d", 2056 wlan_vdev_get_id(comp_vdev), 2057 vdev_chan.ch_ieee, 2058 vdev_chan.ch_phymode); 2059 qdf_debug("fl %016llx, fl-ext %08x, s1 %d, s2 %d ", 2060 vdev_chan.ch_flags, vdev_chan.ch_flagext, 2061 vdev_chan.ch_freq_seg1, 2062 vdev_chan.ch_freq_seg2); 2063 qdf_debug("==> base vdev id: %d: ieee %d mode %d", 2064 wlan_vdev_get_id(ch_filter->vdev), 2065 iter_vdev_chan->ch_ieee, 2066 iter_vdev_chan->ch_phymode); 2067 qdf_debug("fl %016llx, fl-ext %08x s1 %d, s2 %d", 2068 iter_vdev_chan->ch_flags, 2069 iter_vdev_chan->ch_flagext, 2070 iter_vdev_chan->ch_freq_seg1, 2071 iter_vdev_chan->ch_freq_seg2); 2072 } 2073 wlan_vdev_obj_unlock(ch_filter->vdev); 2074 } 2075 2076 QDF_STATUS wlan_util_pdev_vdevs_deschan_match(struct wlan_objmgr_pdev *pdev, 2077 struct wlan_objmgr_vdev *vdev, 2078 wlan_objmgr_ref_dbgid dbg_id) 2079 { 2080 struct wlan_vdev_ch_check_filter ch_filter; 2081 2082 if (!pdev) 2083 return QDF_STATUS_E_INVAL; 2084 2085 if (wlan_pdev_nif_feat_cap_get(pdev, WLAN_PDEV_F_CHAN_CONCURRENCY)) 2086 return QDF_STATUS_SUCCESS; 2087 2088 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == QDF_STATUS_SUCCESS) { 2089 ch_filter.flag = 0; 2090 ch_filter.vdev = vdev; 2091 2092 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 2093 wlan_pdev_chan_match, 2094 &ch_filter, 0, dbg_id); 2095 2096 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 2097 2098 if (ch_filter.flag == 0) 2099 return QDF_STATUS_SUCCESS; 2100 } 2101 2102 return QDF_STATUS_E_FAILURE; 2103 } 2104 2105 static void wlan_vdev_restart_progress(struct wlan_objmgr_pdev *pdev, 2106 void *object, void *arg) 2107 { 2108 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 2109 uint8_t *flag = (uint8_t *)arg; 2110 2111 wlan_vdev_obj_lock(vdev); 2112 if (wlan_vdev_is_restart_progress(vdev) == QDF_STATUS_SUCCESS) 2113 *flag = 1; 2114 2115 wlan_vdev_obj_unlock(vdev); 2116 } 2117 2118 QDF_STATUS wlan_util_is_pdev_restart_progress(struct wlan_objmgr_pdev *pdev, 2119 wlan_objmgr_ref_dbgid dbg_id) 2120 { 2121 uint8_t flag = 0; 2122 2123 if (!pdev) 2124 return QDF_STATUS_E_INVAL; 2125 2126 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 2127 wlan_vdev_restart_progress, 2128 &flag, 0, dbg_id); 2129 2130 if (flag == 1) 2131 return QDF_STATUS_SUCCESS; 2132 2133 return QDF_STATUS_E_INVAL; 2134 } 2135 2136 static void wlan_vdev_scan_allowed(struct wlan_objmgr_pdev *pdev, void *object, 2137 void *arg) 2138 { 2139 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 2140 uint8_t *flag = (uint8_t *)arg; 2141 2142 wlan_vdev_obj_lock(vdev); 2143 if (wlan_vdev_mlme_is_scan_allowed(vdev) != QDF_STATUS_SUCCESS) 2144 *flag = 1; 2145 2146 wlan_vdev_obj_unlock(vdev); 2147 } 2148 2149 QDF_STATUS wlan_util_is_pdev_scan_allowed(struct wlan_objmgr_pdev *pdev, 2150 wlan_objmgr_ref_dbgid dbg_id) 2151 { 2152 uint8_t flag = 0; 2153 2154 if (!pdev) 2155 return QDF_STATUS_E_INVAL; 2156 2157 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 2158 wlan_vdev_scan_allowed, 2159 &flag, 0, dbg_id); 2160 2161 if (flag == 1) 2162 return QDF_STATUS_E_FAILURE; 2163 2164 return QDF_STATUS_SUCCESS; 2165 } 2166 2167 void 2168 wlan_util_stats_get_rssi(bool db2dbm_enabled, int32_t bcn_snr, int32_t dat_snr, 2169 int8_t *rssi) 2170 { 2171 uint32_t snr; 2172 2173 if (db2dbm_enabled) { 2174 if (TGT_IS_VALID_RSSI(bcn_snr)) 2175 *rssi = bcn_snr; 2176 else if (TGT_IS_VALID_RSSI(dat_snr)) 2177 *rssi = dat_snr; 2178 else 2179 *rssi = TGT_NOISE_FLOOR_DBM; 2180 } else { 2181 if (TGT_IS_VALID_SNR(bcn_snr)) 2182 snr = bcn_snr; 2183 else if (TGT_IS_VALID_SNR(dat_snr)) 2184 snr = dat_snr; 2185 else 2186 snr = TGT_INVALID_SNR; 2187 2188 /* Get the absolute rssi value from the current rssi value */ 2189 *rssi = snr + TGT_NOISE_FLOOR_DBM; 2190 } 2191 } 2192 2193 /** 2194 * wlan_util_get_mode_specific_peer_count - This api gives vdev mode specific 2195 * peer count` 2196 * @pdev: PDEV object 2197 * @object: vdev object 2198 * @arg: argument passed by caller 2199 * 2200 * Return: void 2201 */ 2202 static void 2203 wlan_util_get_mode_specific_peer_count(struct wlan_objmgr_pdev *pdev, 2204 void *object, void *arg) 2205 { 2206 struct wlan_objmgr_vdev *vdev = object; 2207 uint16_t temp_count = 0; 2208 struct wlan_op_mode_peer_count *count = arg; 2209 2210 wlan_vdev_obj_lock(vdev); 2211 if (wlan_vdev_mlme_get_opmode(vdev) == count->opmode) { 2212 temp_count = wlan_vdev_get_peer_count(vdev); 2213 /* Decrement the self peer count */ 2214 if (temp_count > 1) 2215 count->peer_count += (temp_count - 1); 2216 } 2217 wlan_vdev_obj_unlock(vdev); 2218 } 2219 2220 uint16_t wlan_util_get_peer_count_for_mode(struct wlan_objmgr_pdev *pdev, 2221 enum QDF_OPMODE mode) 2222 { 2223 struct wlan_op_mode_peer_count count; 2224 2225 count.opmode = mode; 2226 count.peer_count = 0; 2227 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 2228 wlan_util_get_mode_specific_peer_count, &count, 2229 0, WLAN_OBJMGR_ID); 2230 2231 return count.peer_count; 2232 } 2233 2234 #ifdef CONFIG_QCA_MINIDUMP 2235 static bool wlan_minidump_log_enabled(struct wlan_objmgr_psoc *psoc, 2236 enum wlan_minidump_host_data type) 2237 { 2238 bool setval = false; 2239 2240 switch (type) { 2241 case WLAN_MD_CP_EXT_PDEV: 2242 if (cfg_get(psoc, CFG_OL_MD_CP_EXT_PDEV)) 2243 setval = true; 2244 break; 2245 case WLAN_MD_CP_EXT_PSOC: 2246 if (cfg_get(psoc, CFG_OL_MD_CP_EXT_PSOC)) 2247 setval = true; 2248 break; 2249 case WLAN_MD_CP_EXT_VDEV: 2250 if (cfg_get(psoc, CFG_OL_MD_CP_EXT_VDEV)) 2251 setval = true; 2252 break; 2253 case WLAN_MD_CP_EXT_PEER: 2254 if (cfg_get(psoc, CFG_OL_MD_CP_EXT_PEER)) 2255 setval = true; 2256 break; 2257 case WLAN_MD_DP_SOC: 2258 if (cfg_get(psoc, CFG_OL_MD_DP_SOC)) 2259 setval = true; 2260 break; 2261 case WLAN_MD_DP_PDEV: 2262 if (cfg_get(psoc, CFG_OL_MD_DP_PDEV)) 2263 setval = true; 2264 break; 2265 case WLAN_MD_DP_PEER: 2266 if (cfg_get(psoc, CFG_OL_MD_DP_PEER)) 2267 setval = true; 2268 break; 2269 case WLAN_MD_DP_SRNG_REO_DEST: 2270 case WLAN_MD_DP_SRNG_REO_EXCEPTION: 2271 case WLAN_MD_DP_SRNG_RX_REL: 2272 case WLAN_MD_DP_SRNG_REO_REINJECT: 2273 case WLAN_MD_DP_SRNG_REO_CMD: 2274 case WLAN_MD_DP_SRNG_REO_STATUS: 2275 if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_REO)) 2276 setval = true; 2277 break; 2278 case WLAN_MD_DP_SRNG_TCL_DATA: 2279 case WLAN_MD_DP_SRNG_TCL_CMD: 2280 case WLAN_MD_DP_SRNG_TCL_STATUS: 2281 case WLAN_MD_DP_SRNG_TX_COMP: 2282 if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_TCL)) 2283 setval = true; 2284 break; 2285 case WLAN_MD_DP_SRNG_WBM_DESC_REL: 2286 case WLAN_MD_DP_SRNG_WBM_IDLE_LINK: 2287 if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_WBM)) 2288 setval = true; 2289 break; 2290 case WLAN_MD_DP_LINK_DESC_BANK: 2291 if (cfg_get(psoc, CFG_OL_MD_DP_LINK_DESC_BANK)) 2292 setval = true; 2293 break; 2294 case WLAN_MD_DP_SRNG_RXDMA_MON_BUF: 2295 case WLAN_MD_DP_SRNG_RXDMA_MON_DST: 2296 case WLAN_MD_DP_SRNG_RXDMA_MON_DESC: 2297 case WLAN_MD_DP_SRNG_RXDMA_ERR_DST: 2298 case WLAN_MD_DP_SRNG_RXDMA_MON_STATUS: 2299 if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_RXDMA)) 2300 setval = true; 2301 break; 2302 case WLAN_MD_DP_HAL_SOC: 2303 if (cfg_get(psoc, CFG_OL_MD_DP_HAL_SOC)) 2304 setval = true; 2305 break; 2306 case WLAN_MD_OBJMGR_PSOC: 2307 case WLAN_MD_OBJMGR_PSOC_TGT_INFO: 2308 if (cfg_get(psoc, CFG_OL_MD_OBJMGR_PSOC)) 2309 setval = true; 2310 break; 2311 case WLAN_MD_OBJMGR_PDEV: 2312 case WLAN_MD_OBJMGR_PDEV_MLME: 2313 if (cfg_get(psoc, CFG_OL_MD_OBJMGR_PDEV)) 2314 setval = true; 2315 break; 2316 case WLAN_MD_OBJMGR_VDEV_MLME: 2317 case WLAN_MD_OBJMGR_VDEV_SM: 2318 case WLAN_MD_OBJMGR_VDEV: 2319 if (cfg_get(psoc, CFG_OL_MD_OBJMGR_VDEV)) 2320 setval = true; 2321 break; 2322 default: 2323 qdf_debug("Minidump: Type not implemented"); 2324 } 2325 2326 return setval; 2327 } 2328 #else /* CONFIG_QCA_MINIDUMP */ 2329 static bool wlan_minidump_log_enabled(struct wlan_objmgr_psoc *psoc, 2330 enum wlan_minidump_host_data type) 2331 { 2332 return false; 2333 } 2334 #endif 2335 2336 void wlan_minidump_log(void *start_addr, const size_t size, 2337 void *psoc_obj, 2338 enum wlan_minidump_host_data type, 2339 const char *name) 2340 { 2341 struct wlan_objmgr_psoc *psoc; 2342 2343 if (!psoc_obj) { 2344 qdf_debug("Minidump: Psoc is NULL"); 2345 return; 2346 } 2347 2348 psoc = (struct wlan_objmgr_psoc *)psoc_obj; 2349 2350 if (psoc && wlan_minidump_log_enabled(psoc, type)) 2351 qdf_minidump_log(start_addr, size, name); 2352 } 2353 qdf_export_symbol(wlan_minidump_log); 2354 2355 void wlan_minidump_remove(void *start_addr, const size_t size, 2356 void *psoc_obj, 2357 enum wlan_minidump_host_data type, 2358 const char *name) 2359 { 2360 struct wlan_objmgr_psoc *psoc; 2361 2362 if (!psoc_obj) { 2363 qdf_debug("Minidump: Psoc is NULL"); 2364 return; 2365 } 2366 2367 psoc = (struct wlan_objmgr_psoc *)psoc_obj; 2368 2369 if (psoc && wlan_minidump_log_enabled(psoc, type)) 2370 qdf_minidump_remove(start_addr, size, name); 2371 } 2372 qdf_export_symbol(wlan_minidump_remove); 2373 2374 static void vdev_cac_in_progress(struct wlan_objmgr_pdev *pdev, 2375 void *object, void *arg) 2376 { 2377 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 2378 bool *cac_is_in_progress = (bool *)arg; 2379 2380 if (*cac_is_in_progress) 2381 return; 2382 2383 if (wlan_vdev_is_dfs_cac_wait(vdev) == QDF_STATUS_SUCCESS) 2384 *cac_is_in_progress = true; 2385 } 2386 2387 bool wlan_util_is_vdev_in_cac_wait(struct wlan_objmgr_pdev *pdev, 2388 wlan_objmgr_ref_dbgid dbg_id) 2389 { 2390 bool cac_is_in_progress = false; 2391 2392 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 2393 vdev_cac_in_progress, 2394 &cac_is_in_progress, 0, 2395 dbg_id); 2396 2397 return cac_is_in_progress; 2398 } 2399 2400 qdf_export_symbol(wlan_util_is_vdev_in_cac_wait); 2401