wlan_utility.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  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. * DOC: This file contains definition for mandatory legacy API
  18. */
  19. #include "qdf_str.h"
  20. #include "wlan_utility.h"
  21. #include <wlan_cmn.h>
  22. #include "wlan_osif_priv.h"
  23. #include <net/cfg80211.h>
  24. #include <qdf_module.h>
  25. #include <wlan_vdev_mlme_api.h>
  26. uint32_t wlan_chan_to_freq(uint8_t chan)
  27. {
  28. /* ch 0 - ch 13 */
  29. if (chan < WLAN_24_GHZ_CHANNEL_14)
  30. return WLAN_24_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
  31. else if (chan == WLAN_24_GHZ_CHANNEL_14)
  32. return WLAN_CHAN_14_FREQ;
  33. else if (chan < WLAN_24_GHZ_CHANNEL_27)
  34. /* ch 15 - ch 26 */
  35. return WLAN_CHAN_15_FREQ +
  36. (chan - WLAN_24_GHZ_CHANNEL_15) * WLAN_CHAN_SPACING_20MHZ;
  37. else if (chan == WLAN_5_GHZ_CHANNEL_170)
  38. return WLAN_CHAN_170_FREQ;
  39. else
  40. return WLAN_5_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
  41. }
  42. uint8_t wlan_freq_to_chan(uint32_t freq)
  43. {
  44. uint8_t chan;
  45. if (freq > WLAN_24_GHZ_BASE_FREQ && freq < WLAN_CHAN_14_FREQ)
  46. chan = ((freq - WLAN_24_GHZ_BASE_FREQ) /
  47. WLAN_CHAN_SPACING_5MHZ);
  48. else if (freq == WLAN_CHAN_14_FREQ)
  49. chan = WLAN_24_GHZ_CHANNEL_14;
  50. else if ((freq > WLAN_24_GHZ_BASE_FREQ) &&
  51. (freq < WLAN_5_GHZ_BASE_FREQ))
  52. chan = (((freq - WLAN_CHAN_15_FREQ) /
  53. WLAN_CHAN_SPACING_20MHZ) +
  54. WLAN_24_GHZ_CHANNEL_15);
  55. else
  56. chan = (freq - WLAN_5_GHZ_BASE_FREQ) /
  57. WLAN_CHAN_SPACING_5MHZ;
  58. return chan;
  59. }
  60. bool wlan_is_ie_valid(const uint8_t *ie, size_t ie_len)
  61. {
  62. uint8_t elen;
  63. while (ie_len) {
  64. if (ie_len < 2)
  65. return false;
  66. elen = ie[1];
  67. ie_len -= 2;
  68. ie += 2;
  69. if (elen > ie_len)
  70. return false;
  71. ie_len -= elen;
  72. ie += elen;
  73. }
  74. return true;
  75. }
  76. static const uint8_t *wlan_get_ie_ptr_from_eid_n_oui(uint8_t eid,
  77. const uint8_t *oui,
  78. uint8_t oui_size,
  79. const uint8_t *ie,
  80. uint16_t ie_len)
  81. {
  82. int32_t left = ie_len;
  83. const uint8_t *ptr = ie;
  84. uint8_t elem_id, elem_len;
  85. while (left >= 2) {
  86. elem_id = ptr[0];
  87. elem_len = ptr[1];
  88. left -= 2;
  89. if (elem_len > left)
  90. return NULL;
  91. if (eid == elem_id) {
  92. /* if oui is not provide eid match is enough */
  93. if (!oui)
  94. return ptr;
  95. /*
  96. * if oui is provided and oui_size is more than left
  97. * bytes, then we cannot have match
  98. */
  99. if (oui_size > left)
  100. return NULL;
  101. if (qdf_mem_cmp(&ptr[2], oui, oui_size) == 0)
  102. return ptr;
  103. }
  104. left -= elem_len;
  105. ptr += (elem_len + 2);
  106. }
  107. return NULL;
  108. }
  109. const uint8_t *wlan_get_ie_ptr_from_eid(uint8_t eid,
  110. const uint8_t *ie,
  111. int ie_len)
  112. {
  113. return wlan_get_ie_ptr_from_eid_n_oui(eid, NULL, 0, ie, ie_len);
  114. }
  115. const uint8_t *wlan_get_vendor_ie_ptr_from_oui(const uint8_t *oui,
  116. uint8_t oui_size,
  117. const uint8_t *ie,
  118. uint16_t ie_len)
  119. {
  120. return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_VENDOR,
  121. oui, oui_size, ie, ie_len);
  122. }
  123. const uint8_t *wlan_get_ext_ie_ptr_from_ext_id(const uint8_t *oui,
  124. uint8_t oui_size,
  125. const uint8_t *ie,
  126. uint16_t ie_len)
  127. {
  128. return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_EXT,
  129. oui, oui_size, ie, ie_len);
  130. }
  131. bool wlan_is_emulation_platform(uint32_t phy_version)
  132. {
  133. if ((phy_version == 0xABC0) || (phy_version == 0xABC1) ||
  134. (phy_version == 0xABC2) || (phy_version == 0xABC3) ||
  135. (phy_version == 0xFFFF) || (phy_version == 0xABCD))
  136. return true;
  137. return false;
  138. }
  139. uint32_t wlan_get_pdev_id_from_vdev_id(struct wlan_objmgr_psoc *psoc,
  140. uint8_t vdev_id,
  141. wlan_objmgr_ref_dbgid dbg_id)
  142. {
  143. struct wlan_objmgr_vdev *vdev;
  144. struct wlan_objmgr_pdev *pdev = NULL;
  145. uint32_t pdev_id = WLAN_INVALID_PDEV_ID;
  146. vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
  147. vdev_id, dbg_id);
  148. if (vdev) {
  149. pdev = wlan_vdev_get_pdev(vdev);
  150. if (pdev)
  151. pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
  152. wlan_objmgr_vdev_release_ref(vdev, dbg_id);
  153. }
  154. return pdev_id;
  155. }
  156. qdf_export_symbol(wlan_get_pdev_id_from_vdev_id);
  157. #ifdef CMN_VDEV_MLME_SM_ENABLE
  158. static void wlan_vdev_active(struct wlan_objmgr_pdev *pdev, void *object,
  159. void *arg)
  160. {
  161. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  162. uint8_t *flag = (uint8_t *)arg;
  163. wlan_vdev_obj_lock(vdev);
  164. if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS)
  165. *flag = 1;
  166. wlan_vdev_obj_unlock(vdev);
  167. }
  168. QDF_STATUS wlan_vdev_is_up(struct wlan_objmgr_vdev *vdev)
  169. {
  170. return wlan_vdev_allow_connect_n_tx(vdev);
  171. }
  172. qdf_export_symbol(wlan_vdev_is_up);
  173. #else
  174. static void wlan_vdev_active(struct wlan_objmgr_pdev *pdev, void *object,
  175. void *arg)
  176. {
  177. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  178. uint8_t *flag = (uint8_t *)arg;
  179. wlan_vdev_obj_lock(vdev);
  180. if ((wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_RUN) ||
  181. (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_DFS_WAIT))
  182. *flag = 1;
  183. wlan_vdev_obj_unlock(vdev);
  184. }
  185. QDF_STATUS wlan_vdev_is_up(struct wlan_objmgr_vdev *vdev)
  186. {
  187. QDF_STATUS is_up = QDF_STATUS_E_FAILURE;
  188. wlan_vdev_obj_lock(vdev);
  189. if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_RUN)
  190. is_up = QDF_STATUS_SUCCESS;
  191. wlan_vdev_obj_unlock(vdev);
  192. return is_up;
  193. }
  194. qdf_export_symbol(wlan_vdev_is_up);
  195. #endif
  196. QDF_STATUS wlan_util_is_vdev_active(struct wlan_objmgr_pdev *pdev,
  197. wlan_objmgr_ref_dbgid dbg_id)
  198. {
  199. uint8_t flag = 0;
  200. if (!pdev)
  201. return QDF_STATUS_E_INVAL;
  202. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, wlan_vdev_active,
  203. &flag, 0, dbg_id);
  204. if (flag == 1)
  205. return QDF_STATUS_SUCCESS;
  206. return QDF_STATUS_E_INVAL;
  207. }
  208. #ifdef CMN_VDEV_MLME_SM_ENABLE
  209. void wlan_util_change_map_index(unsigned long *map, uint8_t id, uint8_t set)
  210. {
  211. if (set)
  212. qdf_set_bit(id, map);
  213. else
  214. qdf_clear_bit(id, map);
  215. }
  216. bool wlan_util_map_index_is_set(unsigned long *map, uint8_t id)
  217. {
  218. return qdf_test_bit(id, map);
  219. }
  220. static void wlan_vdev_chan_change_pending(struct wlan_objmgr_pdev *pdev,
  221. void *object, void *arg)
  222. {
  223. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  224. unsigned long *vdev_id_map = (unsigned long *)arg;
  225. uint8_t id = 0;
  226. struct wlan_objmgr_psoc *psoc;
  227. psoc = wlan_pdev_get_psoc(pdev);
  228. if (!psoc)
  229. return;
  230. wlan_vdev_obj_lock(vdev);
  231. if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) {
  232. id = wlan_vdev_get_id(vdev);
  233. /* Invalid vdev id */
  234. if (id >= wlan_psoc_get_max_vdev_count(psoc)) {
  235. wlan_vdev_obj_unlock(vdev);
  236. return;
  237. }
  238. wlan_util_change_map_index(vdev_id_map, id, 1);
  239. }
  240. wlan_vdev_obj_unlock(vdev);
  241. }
  242. QDF_STATUS wlan_pdev_chan_change_pending_vdevs(struct wlan_objmgr_pdev *pdev,
  243. unsigned long *vdev_id_map,
  244. wlan_objmgr_ref_dbgid dbg_id)
  245. {
  246. if (!pdev)
  247. return QDF_STATUS_E_INVAL;
  248. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  249. wlan_vdev_chan_change_pending,
  250. vdev_id_map, 0, dbg_id);
  251. return QDF_STATUS_SUCCESS;
  252. }
  253. QDF_STATUS wlan_chan_eq(struct wlan_channel *chan1, struct wlan_channel *chan2)
  254. {
  255. if ((chan1->ch_ieee == chan2->ch_ieee) &&
  256. (chan1->ch_freq_seg2 == chan2->ch_freq_seg2))
  257. return QDF_STATUS_SUCCESS;
  258. return QDF_STATUS_E_FAILURE;
  259. }
  260. void wlan_chan_copy(struct wlan_channel *tgt, struct wlan_channel *src)
  261. {
  262. qdf_mem_copy(tgt, src, sizeof(struct wlan_channel));
  263. }
  264. struct wlan_channel *wlan_vdev_get_active_channel(struct wlan_objmgr_vdev *vdev)
  265. {
  266. struct wlan_channel *comp_vdev_chan = NULL;
  267. if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) {
  268. /* compare with BSS channel, when vdev is active, since desired
  269. * channel gets update, if channel is triggered in another path
  270. */
  271. if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS)
  272. comp_vdev_chan = wlan_vdev_mlme_get_bss_chan(vdev);
  273. else
  274. comp_vdev_chan = wlan_vdev_mlme_get_des_chan(vdev);
  275. }
  276. return comp_vdev_chan;
  277. }
  278. static void wlan_pdev_chan_match(struct wlan_objmgr_pdev *pdev, void *object,
  279. void *arg)
  280. {
  281. struct wlan_objmgr_vdev *comp_vdev = (struct wlan_objmgr_vdev *)object;
  282. struct wlan_vdev_ch_check_filter *ch_filter = arg;
  283. struct wlan_channel *vdev_chan;
  284. struct wlan_channel *iter_vdev_chan;
  285. if (ch_filter->flag)
  286. return;
  287. if (comp_vdev == ch_filter->vdev)
  288. return;
  289. wlan_vdev_obj_lock(comp_vdev);
  290. wlan_vdev_obj_lock(ch_filter->vdev);
  291. vdev_chan = wlan_vdev_get_active_channel(comp_vdev);
  292. if (vdev_chan) {
  293. iter_vdev_chan = wlan_vdev_mlme_get_des_chan(
  294. ch_filter->vdev);
  295. if (wlan_chan_eq(vdev_chan, iter_vdev_chan)
  296. != QDF_STATUS_SUCCESS) {
  297. ch_filter->flag = 1;
  298. qdf_nofl_err("==> iter vdev id: %d: ieee %d, mode %d",
  299. wlan_vdev_get_id(comp_vdev),
  300. vdev_chan->ch_ieee,
  301. vdev_chan->ch_phymode);
  302. qdf_nofl_err("fl %016llx, fl-ext %08x, s1 %d, s2 %d ",
  303. vdev_chan->ch_flags, vdev_chan->ch_flagext,
  304. vdev_chan->ch_freq_seg1,
  305. vdev_chan->ch_freq_seg2);
  306. qdf_nofl_err("==> base vdev id: %d: ieee %d mode %d",
  307. wlan_vdev_get_id(ch_filter->vdev),
  308. iter_vdev_chan->ch_ieee,
  309. iter_vdev_chan->ch_phymode);
  310. qdf_nofl_err("fl %016llx, fl-ext %08x s1 %d, s2 %d",
  311. iter_vdev_chan->ch_flags,
  312. iter_vdev_chan->ch_flagext,
  313. iter_vdev_chan->ch_freq_seg1,
  314. iter_vdev_chan->ch_freq_seg2);
  315. }
  316. }
  317. wlan_vdev_obj_unlock(ch_filter->vdev);
  318. wlan_vdev_obj_unlock(comp_vdev);
  319. }
  320. QDF_STATUS wlan_util_pdev_vdevs_deschan_match(struct wlan_objmgr_pdev *pdev,
  321. struct wlan_objmgr_vdev *vdev,
  322. wlan_objmgr_ref_dbgid dbg_id)
  323. {
  324. struct wlan_vdev_ch_check_filter ch_filter;
  325. if (!pdev)
  326. return QDF_STATUS_E_INVAL;
  327. if (wlan_pdev_nif_feat_cap_get(pdev, WLAN_PDEV_F_CHAN_CONCURRENCY))
  328. return QDF_STATUS_SUCCESS;
  329. if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == QDF_STATUS_SUCCESS) {
  330. ch_filter.flag = 0;
  331. ch_filter.vdev = vdev;
  332. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  333. wlan_pdev_chan_match,
  334. &ch_filter, 0, dbg_id);
  335. wlan_objmgr_vdev_release_ref(vdev, dbg_id);
  336. if (ch_filter.flag == 0)
  337. return QDF_STATUS_SUCCESS;
  338. }
  339. return QDF_STATUS_E_FAILURE;
  340. }
  341. static void wlan_vdev_restart_progress(struct wlan_objmgr_pdev *pdev,
  342. void *object, void *arg)
  343. {
  344. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  345. uint8_t *flag = (uint8_t *)arg;
  346. wlan_vdev_obj_lock(vdev);
  347. if (wlan_vdev_is_restart_progress(vdev) == QDF_STATUS_SUCCESS)
  348. *flag = 1;
  349. wlan_vdev_obj_unlock(vdev);
  350. }
  351. QDF_STATUS wlan_util_is_pdev_restart_progress(struct wlan_objmgr_pdev *pdev,
  352. wlan_objmgr_ref_dbgid dbg_id)
  353. {
  354. uint8_t flag = 0;
  355. if (!pdev)
  356. return QDF_STATUS_E_INVAL;
  357. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  358. wlan_vdev_restart_progress,
  359. &flag, 0, dbg_id);
  360. if (flag == 1)
  361. return QDF_STATUS_SUCCESS;
  362. return QDF_STATUS_E_INVAL;
  363. }
  364. static void wlan_vdev_scan_allowed(struct wlan_objmgr_pdev *pdev, void *object,
  365. void *arg)
  366. {
  367. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  368. uint8_t *flag = (uint8_t *)arg;
  369. wlan_vdev_obj_lock(vdev);
  370. if (wlan_vdev_mlme_is_scan_allowed(vdev) != QDF_STATUS_SUCCESS)
  371. *flag = 1;
  372. wlan_vdev_obj_unlock(vdev);
  373. }
  374. QDF_STATUS wlan_util_is_pdev_scan_allowed(struct wlan_objmgr_pdev *pdev,
  375. wlan_objmgr_ref_dbgid dbg_id)
  376. {
  377. uint8_t flag = 0;
  378. if (!pdev)
  379. return QDF_STATUS_E_INVAL;
  380. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  381. wlan_vdev_scan_allowed,
  382. &flag, 0, dbg_id);
  383. if (flag == 1)
  384. return QDF_STATUS_E_FAILURE;
  385. return QDF_STATUS_SUCCESS;
  386. }
  387. #else
  388. QDF_STATUS wlan_util_is_pdev_scan_allowed(struct wlan_objmgr_pdev *pdev,
  389. wlan_objmgr_ref_dbgid dbg_id)
  390. {
  391. return QDF_STATUS_SUCCESS;
  392. }
  393. #endif
  394. void
  395. wlan_util_stats_get_rssi(bool db2dbm_enabled, int32_t bcn_snr, int32_t dat_snr,
  396. int8_t *rssi)
  397. {
  398. uint32_t snr;
  399. if (db2dbm_enabled) {
  400. if (TGT_IS_VALID_RSSI(bcn_snr))
  401. *rssi = bcn_snr;
  402. else if (TGT_IS_VALID_RSSI(dat_snr))
  403. *rssi = dat_snr;
  404. else
  405. *rssi = TGT_NOISE_FLOOR_DBM;
  406. } else {
  407. if (TGT_IS_VALID_SNR(bcn_snr))
  408. snr = bcn_snr;
  409. else if (TGT_IS_VALID_SNR(dat_snr))
  410. snr = dat_snr;
  411. else
  412. snr = TGT_INVALID_SNR;
  413. /* Get the absolute rssi value from the current rssi value */
  414. *rssi = snr + TGT_NOISE_FLOOR_DBM;
  415. }
  416. }