1 /* 2 * Copyright (c) 2017-2018 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 /** 20 * DOC: This file contains definition for mandatory legacy API 21 */ 22 23 #include "qdf_str.h" 24 #include "wlan_utility.h" 25 #include <wlan_cmn.h> 26 #include "wlan_osif_priv.h" 27 #include <net/cfg80211.h> 28 #include <qdf_module.h> 29 #include <wlan_vdev_mlme_api.h> 30 31 uint32_t wlan_chan_to_freq(uint8_t chan) 32 { 33 /* ch 0 - ch 13 */ 34 if (chan < WLAN_24_GHZ_CHANNEL_14) 35 return WLAN_24_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ; 36 else if (chan == WLAN_24_GHZ_CHANNEL_14) 37 return WLAN_CHAN_14_FREQ; 38 else if (chan < WLAN_24_GHZ_CHANNEL_27) 39 /* ch 15 - ch 26 */ 40 return WLAN_CHAN_15_FREQ + 41 (chan - WLAN_24_GHZ_CHANNEL_15) * WLAN_CHAN_SPACING_20MHZ; 42 else if (chan == WLAN_5_GHZ_CHANNEL_170) 43 return WLAN_CHAN_170_FREQ; 44 else 45 return WLAN_5_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ; 46 } 47 48 uint8_t wlan_freq_to_chan(uint32_t freq) 49 { 50 uint8_t chan; 51 52 if (freq > WLAN_24_GHZ_BASE_FREQ && freq < WLAN_CHAN_14_FREQ) 53 chan = ((freq - WLAN_24_GHZ_BASE_FREQ) / 54 WLAN_CHAN_SPACING_5MHZ); 55 else if (freq == WLAN_CHAN_14_FREQ) 56 chan = WLAN_24_GHZ_CHANNEL_14; 57 else if ((freq > WLAN_24_GHZ_BASE_FREQ) && 58 (freq < WLAN_5_GHZ_BASE_FREQ)) 59 chan = (((freq - WLAN_CHAN_15_FREQ) / 60 WLAN_CHAN_SPACING_20MHZ) + 61 WLAN_24_GHZ_CHANNEL_15); 62 else 63 chan = (freq - WLAN_5_GHZ_BASE_FREQ) / 64 WLAN_CHAN_SPACING_5MHZ; 65 66 return chan; 67 } 68 69 bool wlan_is_ie_valid(const uint8_t *ie, size_t ie_len) 70 { 71 uint8_t elen; 72 73 while (ie_len) { 74 if (ie_len < 2) 75 return false; 76 77 elen = ie[1]; 78 ie_len -= 2; 79 ie += 2; 80 if (elen > ie_len) 81 return false; 82 83 ie_len -= elen; 84 ie += elen; 85 } 86 87 return true; 88 } 89 90 static const uint8_t *wlan_get_ie_ptr_from_eid_n_oui(uint8_t eid, 91 const uint8_t *oui, 92 uint8_t oui_size, 93 const uint8_t *ie, 94 uint16_t ie_len) 95 { 96 int32_t left = ie_len; 97 const uint8_t *ptr = ie; 98 uint8_t elem_id, elem_len; 99 100 while (left >= 2) { 101 elem_id = ptr[0]; 102 elem_len = ptr[1]; 103 left -= 2; 104 105 if (elem_len > left) 106 return NULL; 107 108 if (eid == elem_id) { 109 /* if oui is not provide eid match is enough */ 110 if (!oui) 111 return ptr; 112 113 /* 114 * if oui is provided and oui_size is more than left 115 * bytes, then we cannot have match 116 */ 117 if (oui_size > left) 118 return NULL; 119 120 if (qdf_mem_cmp(&ptr[2], oui, oui_size) == 0) 121 return ptr; 122 } 123 124 left -= elem_len; 125 ptr += (elem_len + 2); 126 } 127 128 return NULL; 129 } 130 131 const uint8_t *wlan_get_ie_ptr_from_eid(uint8_t eid, 132 const uint8_t *ie, 133 int ie_len) 134 { 135 return wlan_get_ie_ptr_from_eid_n_oui(eid, NULL, 0, ie, ie_len); 136 } 137 138 const uint8_t *wlan_get_vendor_ie_ptr_from_oui(const uint8_t *oui, 139 uint8_t oui_size, 140 const uint8_t *ie, 141 uint16_t ie_len) 142 { 143 return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_VENDOR, 144 oui, oui_size, ie, ie_len); 145 } 146 147 const uint8_t *wlan_get_ext_ie_ptr_from_ext_id(const uint8_t *oui, 148 uint8_t oui_size, 149 const uint8_t *ie, 150 uint16_t ie_len) 151 { 152 return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_EXT, 153 oui, oui_size, ie, ie_len); 154 } 155 156 bool wlan_is_emulation_platform(uint32_t phy_version) 157 { 158 if ((phy_version == 0xABC0) || (phy_version == 0xABC1) || 159 (phy_version == 0xABC2) || (phy_version == 0xABC3) || 160 (phy_version == 0xFFFF) || (phy_version == 0xABCD)) 161 return true; 162 163 return false; 164 } 165 166 uint32_t wlan_get_pdev_id_from_vdev_id(struct wlan_objmgr_psoc *psoc, 167 uint8_t vdev_id, 168 wlan_objmgr_ref_dbgid dbg_id) 169 { 170 struct wlan_objmgr_vdev *vdev; 171 struct wlan_objmgr_pdev *pdev = NULL; 172 uint32_t pdev_id = WLAN_INVALID_PDEV_ID; 173 174 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, 175 vdev_id, dbg_id); 176 177 if (vdev) { 178 pdev = wlan_vdev_get_pdev(vdev); 179 if (pdev) 180 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 181 wlan_objmgr_vdev_release_ref(vdev, dbg_id); 182 } 183 184 return pdev_id; 185 } 186 qdf_export_symbol(wlan_get_pdev_id_from_vdev_id); 187 188 static void wlan_util_get_vdev_by_ifname_cb(struct wlan_objmgr_psoc *psoc, 189 void *obj, void *arg) 190 { 191 struct wlan_objmgr_vdev *vdev = obj; 192 struct wlan_find_vdev_filter *filter = arg; 193 194 if (filter->found_vdev) 195 return; 196 197 wlan_vdev_obj_lock(vdev); 198 if (!qdf_str_cmp(vdev->vdev_nif.osdev->wdev->netdev->name, 199 filter->ifname)) { 200 filter->found_vdev = vdev; 201 } 202 wlan_vdev_obj_unlock(vdev); 203 } 204 205 struct wlan_objmgr_vdev *wlan_util_get_vdev_by_ifname( 206 struct wlan_objmgr_psoc *psoc, char *ifname, 207 wlan_objmgr_ref_dbgid ref_id) 208 { 209 QDF_STATUS status; 210 struct wlan_find_vdev_filter filter = {0}; 211 212 filter.ifname = ifname; 213 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 214 wlan_util_get_vdev_by_ifname_cb, 215 &filter, 0, ref_id); 216 217 if (!filter.found_vdev) 218 return NULL; 219 220 status = wlan_objmgr_vdev_try_get_ref(filter.found_vdev, ref_id); 221 if (QDF_IS_STATUS_ERROR(status)) 222 return NULL; 223 224 return filter.found_vdev; 225 } 226 227 /** 228 * wlan_util_vdev_get_if_name() - get vdev's interface name 229 * @vdev: VDEV object 230 * 231 * API to get vdev's interface name 232 * 233 * Return: 234 * @id: vdev's interface name 235 */ 236 uint8_t *wlan_util_vdev_get_if_name(struct wlan_objmgr_vdev *vdev) 237 { 238 uint8_t *name; 239 struct vdev_osif_priv *osif_priv; 240 241 wlan_vdev_obj_lock(vdev); 242 243 osif_priv = wlan_vdev_get_ospriv(vdev); 244 if (!osif_priv) { 245 wlan_vdev_obj_unlock(vdev); 246 return NULL; 247 } 248 249 if (!osif_priv->wdev) { 250 wlan_vdev_obj_unlock(vdev); 251 return NULL; 252 } 253 254 name = osif_priv->wdev->netdev->name; 255 wlan_vdev_obj_unlock(vdev); 256 257 return name; 258 } 259 qdf_export_symbol(wlan_util_vdev_get_if_name); 260 261 #ifdef CMN_VDEV_MLME_SM_ENABLE 262 static void wlan_vdev_active(struct wlan_objmgr_pdev *pdev, void *object, 263 void *arg) 264 { 265 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 266 uint8_t *flag = (uint8_t *)arg; 267 268 wlan_vdev_obj_lock(vdev); 269 if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS) 270 *flag = 1; 271 272 wlan_vdev_obj_unlock(vdev); 273 } 274 275 bool wlan_vdev_is_up(struct wlan_objmgr_vdev *vdev) 276 { 277 bool ret_val = false; 278 279 if (wlan_vdev_allow_connect_n_tx(vdev) == QDF_STATUS_SUCCESS) 280 ret_val = true; 281 282 return ret_val; 283 } 284 285 qdf_export_symbol(wlan_vdev_is_up); 286 #else 287 static void wlan_vdev_active(struct wlan_objmgr_pdev *pdev, void *object, 288 void *arg) 289 { 290 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 291 uint8_t *flag = (uint8_t *)arg; 292 293 wlan_vdev_obj_lock(vdev); 294 if ((wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_RUN) || 295 (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_DFS_WAIT)) 296 *flag = 1; 297 298 wlan_vdev_obj_unlock(vdev); 299 } 300 301 bool wlan_vdev_is_up(struct wlan_objmgr_vdev *vdev) 302 { 303 bool ret_val = false; 304 305 wlan_vdev_obj_lock(vdev); 306 if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_RUN) 307 ret_val = true; 308 309 wlan_vdev_obj_unlock(vdev); 310 311 return ret_val; 312 } 313 314 qdf_export_symbol(wlan_vdev_is_up); 315 #endif 316 317 QDF_STATUS wlan_util_is_vdev_active(struct wlan_objmgr_pdev *pdev, 318 wlan_objmgr_ref_dbgid dbg_id) 319 { 320 uint8_t flag = 0; 321 322 if (!pdev) 323 return QDF_STATUS_E_INVAL; 324 325 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, wlan_vdev_active, 326 &flag, 0, dbg_id); 327 328 if (flag == 1) 329 return QDF_STATUS_SUCCESS; 330 331 return QDF_STATUS_E_INVAL; 332 } 333 334 #ifdef CMN_VDEV_MLME_SM_ENABLE 335 void wlan_util_change_map_index(uint32_t *map, uint8_t id, uint8_t set) 336 { 337 uint8_t map_index = 0; 338 uint8_t map_entry_size = 32; 339 uint8_t adjust_index = 0; 340 341 /* 342 * Derive map_index and adjust_index to find actual DWORD 343 * the id map is present 344 */ 345 while ((id - adjust_index) >= map_entry_size) { 346 map_index++; 347 adjust_index = map_index * map_entry_size; 348 } 349 if (set) 350 map[map_index] |= (1 << (id - adjust_index)); 351 else 352 map[map_index] &= ~(1 << (id - adjust_index)); 353 } 354 355 bool wlan_util_map_index_is_set(uint32_t *map, uint8_t id) 356 { 357 uint8_t map_index = 0; 358 uint8_t map_entry_size = 32; 359 uint8_t adjust_index = 0; 360 361 /* 362 * Derive map_index and adjust_index to find actual DWORD 363 * the id map is present 364 */ 365 while ((id - adjust_index) >= map_entry_size) { 366 map_index++; 367 adjust_index = map_index * map_entry_size; 368 } 369 if (map[map_index] & (1 << (id - adjust_index))) 370 return true; 371 372 return false; 373 } 374 375 static void wlan_vdev_chan_change_pending(struct wlan_objmgr_pdev *pdev, 376 void *object, void *arg) 377 { 378 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 379 uint32_t *vdev_id_map = (uint32_t *)arg; 380 uint8_t id = 0; 381 struct wlan_objmgr_psoc *psoc; 382 383 psoc = wlan_pdev_get_psoc(pdev); 384 if (!psoc) 385 return; 386 387 wlan_vdev_obj_lock(vdev); 388 if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) { 389 id = wlan_vdev_get_id(vdev); 390 /* Invalid vdev id */ 391 if (id >= wlan_psoc_get_max_vdev_count(psoc)) 392 return; 393 394 wlan_util_change_map_index(vdev_id_map, id, 1); 395 } 396 397 wlan_vdev_obj_unlock(vdev); 398 } 399 400 QDF_STATUS wlan_pdev_chan_change_pending_vdevs(struct wlan_objmgr_pdev *pdev, 401 uint32_t *vdev_id_map, 402 wlan_objmgr_ref_dbgid dbg_id) 403 { 404 if (!pdev) 405 return QDF_STATUS_E_INVAL; 406 407 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 408 wlan_vdev_chan_change_pending, 409 vdev_id_map, 0, dbg_id); 410 411 return QDF_STATUS_SUCCESS; 412 } 413 414 QDF_STATUS wlan_chan_eq(struct wlan_channel *chan1, struct wlan_channel *chan2) 415 { 416 if (!qdf_mem_cmp(chan1, chan2, sizeof(struct wlan_channel))) 417 return QDF_STATUS_SUCCESS; 418 419 return QDF_STATUS_E_FAILURE; 420 } 421 422 static void wlan_pdev_chan_match(struct wlan_objmgr_pdev *pdev, void *object, 423 void *arg) 424 { 425 struct wlan_objmgr_vdev *comp_vdev = (struct wlan_objmgr_vdev *)object; 426 struct wlan_vdev_ch_check_filter *ch_filter = arg; 427 428 if (ch_filter->flag) 429 return; 430 431 wlan_vdev_obj_lock(comp_vdev); 432 wlan_vdev_obj_lock(ch_filter->vdev); 433 434 if (wlan_vdev_chan_config_valid(ch_filter->vdev) == QDF_STATUS_SUCCESS) 435 if (wlan_chan_eq(wlan_vdev_mlme_get_des_chan(comp_vdev), 436 wlan_vdev_mlme_get_des_chan(ch_filter->vdev)) 437 != QDF_STATUS_SUCCESS) 438 ch_filter->flag = 1; 439 440 wlan_vdev_obj_unlock(ch_filter->vdev); 441 wlan_vdev_obj_unlock(comp_vdev); 442 } 443 444 QDF_STATUS wlan_util_pdev_vdevs_deschan_match(struct wlan_objmgr_pdev *pdev, 445 struct wlan_objmgr_vdev *vdev, 446 wlan_objmgr_ref_dbgid dbg_id) 447 { 448 struct wlan_vdev_ch_check_filter ch_filter; 449 450 if (!pdev) 451 return QDF_STATUS_E_INVAL; 452 453 ch_filter.flag = 0; 454 ch_filter.vdev = vdev; 455 456 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 457 wlan_pdev_chan_match, &ch_filter, 0, 458 dbg_id); 459 460 if (ch_filter.flag == 0) 461 return QDF_STATUS_SUCCESS; 462 463 return QDF_STATUS_E_FAILURE; 464 } 465 #endif 466 467 void 468 wlan_util_stats_get_rssi(bool db2dbm_enabled, int32_t bcn_snr, int32_t dat_snr, 469 int8_t *rssi) 470 { 471 uint32_t snr; 472 473 if (db2dbm_enabled) { 474 if (TGT_IS_VALID_RSSI(bcn_snr)) 475 *rssi = bcn_snr; 476 else if (TGT_IS_VALID_RSSI(dat_snr)) 477 *rssi = dat_snr; 478 else 479 *rssi = TGT_NOISE_FLOOR_DBM; 480 } else { 481 if (TGT_IS_VALID_SNR(bcn_snr)) 482 snr = bcn_snr; 483 else if (TGT_IS_VALID_SNR(dat_snr)) 484 snr = dat_snr; 485 else 486 snr = TGT_INVALID_SNR; 487 488 /* Get the absolute rssi value from the current rssi value */ 489 *rssi = snr + TGT_NOISE_FLOOR_DBM; 490 } 491 } 492