1 /* 2 * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * DOC: This file contains definition for mandatory legacy API 19 */ 20 21 #include "qdf_str.h" 22 #include "wlan_utility.h" 23 #include <wlan_cmn.h> 24 #include "wlan_osif_priv.h" 25 #include <net/cfg80211.h> 26 #include <qdf_module.h> 27 #include <wlan_vdev_mlme_api.h> 28 29 uint32_t wlan_chan_to_freq(uint8_t chan) 30 { 31 /* ch 0 - ch 13 */ 32 if (chan < WLAN_24_GHZ_CHANNEL_14) 33 return WLAN_24_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ; 34 else if (chan == WLAN_24_GHZ_CHANNEL_14) 35 return WLAN_CHAN_14_FREQ; 36 else if (chan < WLAN_24_GHZ_CHANNEL_27) 37 /* ch 15 - ch 26 */ 38 return WLAN_CHAN_15_FREQ + 39 (chan - WLAN_24_GHZ_CHANNEL_15) * WLAN_CHAN_SPACING_20MHZ; 40 else if (chan == WLAN_5_GHZ_CHANNEL_170) 41 return WLAN_CHAN_170_FREQ; 42 else 43 return WLAN_5_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ; 44 } 45 46 uint8_t wlan_freq_to_chan(uint32_t freq) 47 { 48 uint8_t chan; 49 50 if (freq > WLAN_24_GHZ_BASE_FREQ && freq < WLAN_CHAN_14_FREQ) 51 chan = ((freq - WLAN_24_GHZ_BASE_FREQ) / 52 WLAN_CHAN_SPACING_5MHZ); 53 else if (freq == WLAN_CHAN_14_FREQ) 54 chan = WLAN_24_GHZ_CHANNEL_14; 55 else if ((freq > WLAN_24_GHZ_BASE_FREQ) && 56 (freq < WLAN_5_GHZ_BASE_FREQ)) 57 chan = (((freq - WLAN_CHAN_15_FREQ) / 58 WLAN_CHAN_SPACING_20MHZ) + 59 WLAN_24_GHZ_CHANNEL_15); 60 else 61 chan = (freq - WLAN_5_GHZ_BASE_FREQ) / 62 WLAN_CHAN_SPACING_5MHZ; 63 64 return chan; 65 } 66 67 bool wlan_is_ie_valid(const uint8_t *ie, size_t ie_len) 68 { 69 uint8_t elen; 70 71 while (ie_len) { 72 if (ie_len < 2) 73 return false; 74 75 elen = ie[1]; 76 ie_len -= 2; 77 ie += 2; 78 if (elen > ie_len) 79 return false; 80 81 ie_len -= elen; 82 ie += elen; 83 } 84 85 return true; 86 } 87 88 static const uint8_t *wlan_get_ie_ptr_from_eid_n_oui(uint8_t eid, 89 const uint8_t *oui, 90 uint8_t oui_size, 91 const uint8_t *ie, 92 uint16_t ie_len) 93 { 94 int32_t left = ie_len; 95 const uint8_t *ptr = ie; 96 uint8_t elem_id, elem_len; 97 98 while (left >= 2) { 99 elem_id = ptr[0]; 100 elem_len = ptr[1]; 101 left -= 2; 102 103 if (elem_len > left) 104 return NULL; 105 106 if (eid == elem_id) { 107 /* if oui is not provide eid match is enough */ 108 if (!oui) 109 return ptr; 110 111 /* 112 * if oui is provided and oui_size is more than left 113 * bytes, then we cannot have match 114 */ 115 if (oui_size > left) 116 return NULL; 117 118 if (qdf_mem_cmp(&ptr[2], oui, oui_size) == 0) 119 return ptr; 120 } 121 122 left -= elem_len; 123 ptr += (elem_len + 2); 124 } 125 126 return NULL; 127 } 128 129 const uint8_t *wlan_get_ie_ptr_from_eid(uint8_t eid, 130 const uint8_t *ie, 131 int ie_len) 132 { 133 return wlan_get_ie_ptr_from_eid_n_oui(eid, NULL, 0, ie, ie_len); 134 } 135 136 const uint8_t *wlan_get_vendor_ie_ptr_from_oui(const uint8_t *oui, 137 uint8_t oui_size, 138 const uint8_t *ie, 139 uint16_t ie_len) 140 { 141 return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_VENDOR, 142 oui, oui_size, ie, ie_len); 143 } 144 145 const uint8_t *wlan_get_ext_ie_ptr_from_ext_id(const uint8_t *oui, 146 uint8_t oui_size, 147 const uint8_t *ie, 148 uint16_t ie_len) 149 { 150 return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_EXT, 151 oui, oui_size, ie, ie_len); 152 } 153 154 bool wlan_is_emulation_platform(uint32_t phy_version) 155 { 156 if ((phy_version == 0xABC0) || (phy_version == 0xABC1) || 157 (phy_version == 0xABC2) || (phy_version == 0xABC3) || 158 (phy_version == 0xFFFF) || (phy_version == 0xABCD)) 159 return true; 160 161 return false; 162 } 163 164 uint32_t wlan_get_pdev_id_from_vdev_id(struct wlan_objmgr_psoc *psoc, 165 uint8_t vdev_id, 166 wlan_objmgr_ref_dbgid dbg_id) 167 { 168 struct wlan_objmgr_vdev *vdev; 169 struct wlan_objmgr_pdev *pdev = NULL; 170 uint32_t pdev_id = WLAN_INVALID_PDEV_ID; 171 172 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, 173 vdev_id, dbg_id); 174 175 if (vdev) { 176 pdev = wlan_vdev_get_pdev(vdev); 177 if (pdev) 178 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 179 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 180 } 181 182 return pdev_id; 183 } 184 qdf_export_symbol(wlan_get_pdev_id_from_vdev_id); 185 186 static void wlan_util_get_vdev_by_ifname_cb(struct wlan_objmgr_psoc *psoc, 187 void *obj, void *arg) 188 { 189 struct wlan_objmgr_vdev *vdev = obj; 190 struct wlan_find_vdev_filter *filter = arg; 191 192 if (filter->found_vdev) 193 return; 194 195 wlan_vdev_obj_lock(vdev); 196 if (!qdf_str_cmp(vdev->vdev_nif.osdev->wdev->netdev->name, 197 filter->ifname)) { 198 filter->found_vdev = vdev; 199 } 200 wlan_vdev_obj_unlock(vdev); 201 } 202 203 struct wlan_objmgr_vdev *wlan_util_get_vdev_by_ifname( 204 struct wlan_objmgr_psoc *psoc, char *ifname, 205 wlan_objmgr_ref_dbgid ref_id) 206 { 207 QDF_STATUS status; 208 struct wlan_find_vdev_filter filter = {0}; 209 210 filter.ifname = ifname; 211 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 212 wlan_util_get_vdev_by_ifname_cb, 213 &filter, 0, ref_id); 214 215 if (!filter.found_vdev) 216 return NULL; 217 218 status = wlan_objmgr_vdev_try_get_ref(filter.found_vdev, ref_id); 219 if (QDF_IS_STATUS_ERROR(status)) 220 return NULL; 221 222 return filter.found_vdev; 223 } 224 225 /** 226 * wlan_util_vdev_get_if_name() - get vdev's interface name 227 * @vdev: VDEV object 228 * 229 * API to get vdev's interface name 230 * 231 * Return: 232 * @id: vdev's interface name 233 */ 234 uint8_t *wlan_util_vdev_get_if_name(struct wlan_objmgr_vdev *vdev) 235 { 236 uint8_t *name; 237 struct vdev_osif_priv *osif_priv; 238 239 wlan_vdev_obj_lock(vdev); 240 241 osif_priv = wlan_vdev_get_ospriv(vdev); 242 if (!osif_priv) { 243 wlan_vdev_obj_unlock(vdev); 244 return NULL; 245 } 246 247 if (!osif_priv->wdev) { 248 wlan_vdev_obj_unlock(vdev); 249 return NULL; 250 } 251 252 name = osif_priv->wdev->netdev->name; 253 wlan_vdev_obj_unlock(vdev); 254 255 return name; 256 } 257 qdf_export_symbol(wlan_util_vdev_get_if_name); 258 259 #ifdef CMN_VDEV_MLME_SM_ENABLE 260 static void wlan_vdev_active(struct wlan_objmgr_pdev *pdev, void *object, 261 void *arg) 262 { 263 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 264 uint8_t *flag = (uint8_t *)arg; 265 266 wlan_vdev_obj_lock(vdev); 267 if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS) 268 *flag = 1; 269 270 wlan_vdev_obj_unlock(vdev); 271 } 272 273 QDF_STATUS wlan_vdev_is_up(struct wlan_objmgr_vdev *vdev) 274 { 275 return wlan_vdev_allow_connect_n_tx(vdev); 276 } 277 278 qdf_export_symbol(wlan_vdev_is_up); 279 #else 280 static void wlan_vdev_active(struct wlan_objmgr_pdev *pdev, void *object, 281 void *arg) 282 { 283 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 284 uint8_t *flag = (uint8_t *)arg; 285 286 wlan_vdev_obj_lock(vdev); 287 if ((wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_RUN) || 288 (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_DFS_WAIT)) 289 *flag = 1; 290 291 wlan_vdev_obj_unlock(vdev); 292 } 293 294 QDF_STATUS wlan_vdev_is_up(struct wlan_objmgr_vdev *vdev) 295 { 296 QDF_STATUS is_up = QDF_STATUS_E_FAILURE; 297 298 wlan_vdev_obj_lock(vdev); 299 if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_RUN) 300 is_up = QDF_STATUS_SUCCESS; 301 302 wlan_vdev_obj_unlock(vdev); 303 304 return is_up; 305 } 306 307 qdf_export_symbol(wlan_vdev_is_up); 308 #endif 309 310 QDF_STATUS wlan_util_is_vdev_active(struct wlan_objmgr_pdev *pdev, 311 wlan_objmgr_ref_dbgid dbg_id) 312 { 313 uint8_t flag = 0; 314 315 if (!pdev) 316 return QDF_STATUS_E_INVAL; 317 318 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, wlan_vdev_active, 319 &flag, 0, dbg_id); 320 321 if (flag == 1) 322 return QDF_STATUS_SUCCESS; 323 324 return QDF_STATUS_E_INVAL; 325 } 326 327 #ifdef CMN_VDEV_MLME_SM_ENABLE 328 void wlan_util_change_map_index(unsigned long *map, uint8_t id, uint8_t set) 329 { 330 if (set) 331 qdf_set_bit(id, map); 332 else 333 qdf_clear_bit(id, map); 334 } 335 336 bool wlan_util_map_index_is_set(unsigned long *map, uint8_t id) 337 { 338 return qdf_test_bit(id, map); 339 } 340 341 static void wlan_vdev_chan_change_pending(struct wlan_objmgr_pdev *pdev, 342 void *object, void *arg) 343 { 344 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 345 unsigned long *vdev_id_map = (unsigned long *)arg; 346 uint8_t id = 0; 347 struct wlan_objmgr_psoc *psoc; 348 349 psoc = wlan_pdev_get_psoc(pdev); 350 if (!psoc) 351 return; 352 353 wlan_vdev_obj_lock(vdev); 354 if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) { 355 id = wlan_vdev_get_id(vdev); 356 /* Invalid vdev id */ 357 if (id >= wlan_psoc_get_max_vdev_count(psoc)) { 358 wlan_vdev_obj_unlock(vdev); 359 return; 360 } 361 362 wlan_util_change_map_index(vdev_id_map, id, 1); 363 } 364 365 wlan_vdev_obj_unlock(vdev); 366 } 367 368 QDF_STATUS wlan_pdev_chan_change_pending_vdevs(struct wlan_objmgr_pdev *pdev, 369 unsigned long *vdev_id_map, 370 wlan_objmgr_ref_dbgid dbg_id) 371 { 372 if (!pdev) 373 return QDF_STATUS_E_INVAL; 374 375 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 376 wlan_vdev_chan_change_pending, 377 vdev_id_map, 0, dbg_id); 378 379 return QDF_STATUS_SUCCESS; 380 } 381 382 QDF_STATUS wlan_chan_eq(struct wlan_channel *chan1, struct wlan_channel *chan2) 383 { 384 if (!qdf_mem_cmp(chan1, chan2, sizeof(struct wlan_channel))) 385 return QDF_STATUS_SUCCESS; 386 387 return QDF_STATUS_E_FAILURE; 388 } 389 390 void wlan_chan_copy(struct wlan_channel *tgt, struct wlan_channel *src) 391 { 392 qdf_mem_copy(tgt, src, sizeof(struct wlan_channel)); 393 } 394 395 struct wlan_channel *wlan_vdev_get_active_channel(struct wlan_objmgr_vdev *vdev) 396 { 397 struct wlan_channel *comp_vdev_chan = NULL; 398 399 if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) { 400 /* compare with BSS channel, when vdev is active, since desired 401 * channel gets update, if channel is triggered in another path 402 */ 403 if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS) 404 comp_vdev_chan = wlan_vdev_mlme_get_bss_chan(vdev); 405 else 406 comp_vdev_chan = wlan_vdev_mlme_get_des_chan(vdev); 407 } 408 409 return comp_vdev_chan; 410 } 411 412 static void wlan_pdev_chan_match(struct wlan_objmgr_pdev *pdev, void *object, 413 void *arg) 414 { 415 struct wlan_objmgr_vdev *comp_vdev = (struct wlan_objmgr_vdev *)object; 416 struct wlan_vdev_ch_check_filter *ch_filter = arg; 417 struct wlan_channel *vdev_chan; 418 struct wlan_channel *iter_vdev_chan; 419 420 if (ch_filter->flag) 421 return; 422 423 if (comp_vdev == ch_filter->vdev) 424 return; 425 426 wlan_vdev_obj_lock(comp_vdev); 427 wlan_vdev_obj_lock(ch_filter->vdev); 428 429 vdev_chan = wlan_vdev_get_active_channel(comp_vdev); 430 if (vdev_chan) { 431 iter_vdev_chan = wlan_vdev_mlme_get_des_chan( 432 ch_filter->vdev); 433 if (wlan_chan_eq(vdev_chan, iter_vdev_chan) 434 != QDF_STATUS_SUCCESS) { 435 if (!((vdev_chan->ch_ieee == iter_vdev_chan->ch_ieee) && 436 (vdev_chan->ch_freq_seg2 == 437 iter_vdev_chan->ch_freq_seg2) && 438 (vdev_chan->ch_phymode == 439 iter_vdev_chan->ch_phymode))) 440 ch_filter->flag = 1; 441 442 qdf_err("Chan match failed"); 443 qdf_err("==> iter vdev id: %d: ieee %d, freq %d", 444 wlan_vdev_get_id(comp_vdev), vdev_chan->ch_ieee, 445 vdev_chan->ch_freq); 446 qdf_err("flags %016llx, flags ext: %08x, max pwr %d", 447 vdev_chan->ch_flags, vdev_chan->ch_flagext, 448 vdev_chan->ch_maxpower); 449 qdf_err(" seg1 %d seg2 %d chwidth %d, ch_phymode %d", 450 vdev_chan->ch_freq_seg1, 451 vdev_chan->ch_freq_seg2, 452 vdev_chan->ch_width, vdev_chan->ch_phymode); 453 454 qdf_err("==> base vdev id: %d: ieee %d, freq %d", 455 wlan_vdev_get_id(ch_filter->vdev), 456 iter_vdev_chan->ch_ieee, 457 iter_vdev_chan->ch_freq); 458 qdf_err("flags %016llx, flags ext: %08x, max pwr %d", 459 iter_vdev_chan->ch_flags, 460 iter_vdev_chan->ch_flagext, 461 iter_vdev_chan->ch_maxpower); 462 qdf_err(" seg1 %d seg2 %d chwidth %d, ch_phymode %d", 463 iter_vdev_chan->ch_freq_seg1, 464 iter_vdev_chan->ch_freq_seg2, 465 iter_vdev_chan->ch_width, 466 iter_vdev_chan->ch_phymode); 467 } 468 } 469 470 wlan_vdev_obj_unlock(ch_filter->vdev); 471 wlan_vdev_obj_unlock(comp_vdev); 472 } 473 474 QDF_STATUS wlan_util_pdev_vdevs_deschan_match(struct wlan_objmgr_pdev *pdev, 475 struct wlan_objmgr_vdev *vdev, 476 wlan_objmgr_ref_dbgid dbg_id) 477 { 478 struct wlan_vdev_ch_check_filter ch_filter; 479 480 if (!pdev) 481 return QDF_STATUS_E_INVAL; 482 483 if (wlan_pdev_nif_feat_cap_get(pdev, WLAN_PDEV_F_CHAN_CONCURRENCY)) 484 return QDF_STATUS_SUCCESS; 485 486 if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == QDF_STATUS_SUCCESS) { 487 ch_filter.flag = 0; 488 ch_filter.vdev = vdev; 489 490 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 491 wlan_pdev_chan_match, 492 &ch_filter, 0, dbg_id); 493 494 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 495 496 if (ch_filter.flag == 0) 497 return QDF_STATUS_SUCCESS; 498 } 499 500 return QDF_STATUS_E_FAILURE; 501 } 502 503 static void wlan_vdev_restart_progress(struct wlan_objmgr_pdev *pdev, 504 void *object, void *arg) 505 { 506 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 507 uint8_t *flag = (uint8_t *)arg; 508 509 wlan_vdev_obj_lock(vdev); 510 if (wlan_vdev_is_restart_progress(vdev) == QDF_STATUS_SUCCESS) 511 *flag = 1; 512 513 wlan_vdev_obj_unlock(vdev); 514 } 515 516 QDF_STATUS wlan_util_is_pdev_restart_progress(struct wlan_objmgr_pdev *pdev, 517 wlan_objmgr_ref_dbgid dbg_id) 518 { 519 uint8_t flag = 0; 520 521 if (!pdev) 522 return QDF_STATUS_E_INVAL; 523 524 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 525 wlan_vdev_restart_progress, 526 &flag, 0, dbg_id); 527 528 if (flag == 1) 529 return QDF_STATUS_SUCCESS; 530 531 return QDF_STATUS_E_INVAL; 532 } 533 534 static void wlan_vdev_scan_allowed(struct wlan_objmgr_pdev *pdev, void *object, 535 void *arg) 536 { 537 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 538 uint8_t *flag = (uint8_t *)arg; 539 540 wlan_vdev_obj_lock(vdev); 541 if (wlan_vdev_mlme_is_scan_allowed(vdev) != QDF_STATUS_SUCCESS) 542 *flag = 1; 543 544 wlan_vdev_obj_unlock(vdev); 545 } 546 547 QDF_STATUS wlan_util_is_pdev_scan_allowed(struct wlan_objmgr_pdev *pdev, 548 wlan_objmgr_ref_dbgid dbg_id) 549 { 550 uint8_t flag = 0; 551 552 if (!pdev) 553 return QDF_STATUS_E_INVAL; 554 555 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 556 wlan_vdev_scan_allowed, 557 &flag, 0, dbg_id); 558 559 if (flag == 1) 560 return QDF_STATUS_E_FAILURE; 561 562 return QDF_STATUS_SUCCESS; 563 } 564 #else 565 QDF_STATUS wlan_util_is_pdev_scan_allowed(struct wlan_objmgr_pdev *pdev, 566 wlan_objmgr_ref_dbgid dbg_id) 567 { 568 return QDF_STATUS_SUCCESS; 569 } 570 #endif 571 572 void 573 wlan_util_stats_get_rssi(bool db2dbm_enabled, int32_t bcn_snr, int32_t dat_snr, 574 int8_t *rssi) 575 { 576 uint32_t snr; 577 578 if (db2dbm_enabled) { 579 if (TGT_IS_VALID_RSSI(bcn_snr)) 580 *rssi = bcn_snr; 581 else if (TGT_IS_VALID_RSSI(dat_snr)) 582 *rssi = dat_snr; 583 else 584 *rssi = TGT_NOISE_FLOOR_DBM; 585 } else { 586 if (TGT_IS_VALID_SNR(bcn_snr)) 587 snr = bcn_snr; 588 else if (TGT_IS_VALID_SNR(dat_snr)) 589 snr = dat_snr; 590 else 591 snr = TGT_INVALID_SNR; 592 593 /* Get the absolute rssi value from the current rssi value */ 594 *rssi = snr + TGT_NOISE_FLOOR_DBM; 595 } 596 } 597